diff --git a/AppKit/CPAccordionView.j b/AppKit/CPAccordionView.j index c4a6e6e49..3f28cfa3c 100644 --- a/AppKit/CPAccordionView.j +++ b/AppKit/CPAccordionView.j @@ -227,7 +227,7 @@ var secondItem = [[CPAccordionViewItem alloc] initWithIdentifier:@"secondSection { var indexSet = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, _items.length)]; - [indexSet removeIndexes:_expandedIndexes]; + [indexSet removeIndexes:_expandedItemIndexes]; return indexSet; } diff --git a/AppKit/CPAlert.j b/AppKit/CPAlert.j index 896789cdd..372240fd6 100644 --- a/AppKit/CPAlert.j +++ b/AppKit/CPAlert.j @@ -37,6 +37,9 @@ @import "CPPanel.j" @import "CPTextField.j" +@class CPCheckBox + + /* @global @group CPAlertStyle diff --git a/AppKit/CPApplication.j b/AppKit/CPApplication.j index 7024e7f77..5b520a121 100644 --- a/AppKit/CPApplication.j +++ b/AppKit/CPApplication.j @@ -33,6 +33,9 @@ @import "CPCibLoading.j" @import "CPPlatform.j" +@class CPCursor +@class CPColorPanel + var CPMainCibFile = @"CPMainCibFile", CPMainCibFileHumanFriendly = @"Main cib file base name", diff --git a/AppKit/CPArrayController.j b/AppKit/CPArrayController.j index dc13ae452..f907ee032 100644 --- a/AppKit/CPArrayController.j +++ b/AppKit/CPArrayController.j @@ -964,7 +964,7 @@ // be the 'wrong' one - as in not the one the user selected - but the wrong // one is still just another pointer to the same object, so the user will not // be able to see any difference. - contentIndex = [_contentObject indexOfObjectIdenticalTo:object]; + var contentIndex = [_contentObject indexOfObjectIdenticalTo:object]; [_contentObject removeObjectAtIndex:contentIndex]; } [arrangedObjects removeObjectAtIndex:anIndex]; @@ -1093,7 +1093,8 @@ isCompound = [self handlesContentAsCompoundValue], dotIndex = keyPath.lastIndexOf("."), firstPart = dotIndex !== CPNotFound ? keyPath.substring(0, dotIndex) : nil, - isSelectionProxy = firstPart && [[destination valueForKeyPath:firstPart] isKindOfClass:CPControllerSelectionProxy]; + isSelectionProxy = firstPart && [[destination valueForKeyPath:firstPart] isKindOfClass:CPControllerSelectionProxy], + newValue; if (!isCompound && !isSelectionProxy) { diff --git a/AppKit/CPButton.j b/AppKit/CPButton.j index 8dc15f444..8b8148808 100644 --- a/AppKit/CPButton.j +++ b/AppKit/CPButton.j @@ -26,6 +26,8 @@ @import "CPControl.j" @import "CPStringDrawing.j" +@global CPWindowAbove +@global CPWindowBelow /* @group CPBezelStyle */ diff --git a/AppKit/CPButtonBar.j b/AppKit/CPButtonBar.j index ab0b1a212..4e0b4dd4a 100644 --- a/AppKit/CPButtonBar.j +++ b/AppKit/CPButtonBar.j @@ -1,6 +1,10 @@ @import "CPView.j" +@class CPSplitView + +@global CPPopUpButtonStatePullsDown + @implementation CPButtonBar : CPView { diff --git a/AppKit/CPClipView.j b/AppKit/CPClipView.j index 437a210d9..72d4311a7 100644 --- a/AppKit/CPClipView.j +++ b/AppKit/CPClipView.j @@ -22,6 +22,7 @@ @import "CPView.j" +@class CPScrollView /*! @ingroup appkit diff --git a/AppKit/CPColor.j b/AppKit/CPColor.j index 8a0ed9e02..36e852291 100644 --- a/AppKit/CPColor.j +++ b/AppKit/CPColor.j @@ -21,6 +21,7 @@ */ @import +@import "CPGraphicsContext.j" @import "CGColor.j" diff --git a/AppKit/CPColorPanel.j b/AppKit/CPColorPanel.j index d29bc8a57..0f595a4b5 100644 --- a/AppKit/CPColorPanel.j +++ b/AppKit/CPColorPanel.j @@ -26,6 +26,8 @@ @import "CPPanel.j" @import "CPView.j" +@class CPSlider + CPColorPanelColorDidChangeNotification = @"CPColorPanelColorDidChangeNotification"; diff --git a/AppKit/CPColorPicker.j b/AppKit/CPColorPicker.j index 7fe4e7c09..af6ecd051 100644 --- a/AppKit/CPColorPicker.j +++ b/AppKit/CPColorPicker.j @@ -24,6 +24,12 @@ @import "CPView.j" +@class CPSlider + +@global CPColorPickerViewWidth +@global CPColorPickerViewHeight +@global CPWheelColorPickerMode + /*! @ingroup appkit diff --git a/AppKit/CPComboBox.j b/AppKit/CPComboBox.j index efd17405c..f65df0b11 100644 --- a/AppKit/CPComboBox.j +++ b/AppKit/CPComboBox.j @@ -83,7 +83,7 @@ var CPComboBoxTextSubview = @"text", - (void)_initComboBox { _items = [CPArray array]; - _listClass = [_CPPopUpList class]; +// _listClass = [_CPPopUpList class]; _usesDataSource = NO; _completes = NO; _canComplete = NO; diff --git a/AppKit/CPCompatibility.j b/AppKit/CPCompatibility.j index d2fd4ca06..010bde38f 100644 --- a/AppKit/CPCompatibility.j +++ b/AppKit/CPCompatibility.j @@ -21,7 +21,7 @@ */ @import "CPEvent.j" -@import "CPPlatform.j" +//@import "CPPlatform.j" // Browser Engines diff --git a/AppKit/CPControl.j b/AppKit/CPControl.j index c060bd74a..1fc6664c1 100644 --- a/AppKit/CPControl.j +++ b/AppKit/CPControl.j @@ -23,11 +23,14 @@ #import "../Foundation/Ref.h" @import +@import @import "CPFont.j" @import "CPShadow.j" @import "CPView.j" @import "CPKeyValueBinding.j" +@global CPApp + CPLeftTextAlignment = 0; CPRightTextAlignment = 1; CPCenterTextAlignment = 2; diff --git a/AppKit/CPController.j b/AppKit/CPController.j index 8e2eb6f32..5f8f3ae8a 100644 --- a/AppKit/CPController.j +++ b/AppKit/CPController.j @@ -64,7 +64,7 @@ var CPControllerDeclaredKeysKey = @"CPControllerDeclaredKeysKey"; count = _editors.length; for (; index < count; ++index) - if (![[_editors objectAtIndex:i] commitEditing]) + if (![[_editors objectAtIndex:index] commitEditing]) return NO; return YES; diff --git a/AppKit/CPCursor.j b/AppKit/CPCursor.j index 876351f58..b8147a741 100755 --- a/AppKit/CPCursor.j +++ b/AppKit/CPCursor.j @@ -77,7 +77,7 @@ var currentCursor = nil, */ - (id)initWithImage:(CPImage)image foregroundColorHint:(CPColor)foregroundColor backgroundColorHint:(CPColor)backgroundColor hotSpot:(CGPoint)aHotSpot { - return [self initWithImage:image hotSpot:hotSpot]; + return [self initWithImage:image hotSpot:aHotSpot]; } + (void)hide diff --git a/AppKit/CPDocument.j b/AppKit/CPDocument.j index 674a8dc0a..3b0be22b2 100644 --- a/AppKit/CPDocument.j +++ b/AppKit/CPDocument.j @@ -29,6 +29,12 @@ @import "CPViewController.j" @import "CPWindowController.j" +@class CPDocumentController +@class CPAlert + +@global CPApp +@global CPWarningAlertStyle + /* @global diff --git a/AppKit/CPDocumentController.j b/AppKit/CPDocumentController.j index 96c9c3484..11a6e92f0 100644 --- a/AppKit/CPDocumentController.j +++ b/AppKit/CPDocumentController.j @@ -26,6 +26,8 @@ @import "CPDocument.j" @import "CPOpenPanel.j" +@global CPApp + var CPSharedDocumentController = nil; diff --git a/AppKit/CPDragServer.j b/AppKit/CPDragServer.j index bc67ee490..09d8f3f8e 100644 --- a/AppKit/CPDragServer.j +++ b/AppKit/CPDragServer.j @@ -27,6 +27,8 @@ @import "CPView.j" @import "CPWindow.j" +@class _CPDOMDataTransferPasteboard + CPDragOperationNone = 0; CPDragOperationCopy = 1 << 1; diff --git a/AppKit/CPEvent.j b/AppKit/CPEvent.j index 543dcaadd..9ec1ad97a 100644 --- a/AppKit/CPEvent.j +++ b/AppKit/CPEvent.j @@ -21,8 +21,14 @@ */ @import +@import @import "CPText.j" +@class CPTextField + +@global CPApp +@global CPBrowserIsOperatingSystem +@global CPMacOperatingSystem CPLeftMouseDown = 1; CPLeftMouseUp = 2; @@ -206,6 +212,7 @@ var _CPEventPeriodicEventPeriod = 0, DOMEvent _DOMEvent; int _data1; int _data2; + short _subtype; float _deltaX; float _deltaY; diff --git a/AppKit/CPFontManager.j b/AppKit/CPFontManager.j index cfeede594..f8a91851d 100644 --- a/AppKit/CPFontManager.j +++ b/AppKit/CPFontManager.j @@ -54,7 +54,7 @@ var CPSharedFontManager = nil, id _delegate @accessors(property=delegate); CPFont _selectedFont; - BOOL _multiple @accessors; + BOOL _multiple @accessors(getter=isMultiple, setter=setMultiple:); CPDictionary _activeChange; } @@ -139,7 +139,7 @@ var CPSharedFontManager = nil, - (void)setSelectedFont:(CPFont)aFont isMultiple:(BOOL)aFlag { _selectedFont = aFont; - _isMultiple = aFlag; + _multiple = aFlag; // TODO Notify CPFontPanel when it exists. } @@ -149,11 +149,6 @@ var CPSharedFontManager = nil, return _selectedFont; } -- (BOOL)isMultiple -{ - return _isMultiple; -} - - (int)weightOfFont:(CPFont)aFont { // TODO Weight 5 is a normal of book weight and 9 and above is bold, but it would be nice to be more diff --git a/AppKit/CPImage.j b/AppKit/CPImage.j index f19991f7a..fe3aec239 100644 --- a/AppKit/CPImage.j +++ b/AppKit/CPImage.j @@ -26,6 +26,7 @@ @import @import @import +@import CPImageLoadStatusInitialized = 0; diff --git a/AppKit/CPImageView.j b/AppKit/CPImageView.j index e7ea02c3b..43eae53e0 100644 --- a/AppKit/CPImageView.j +++ b/AppKit/CPImageView.j @@ -26,6 +26,9 @@ @import "CPImage.j" @import "CPShadowView.j" +@global CPImagesPboardType +@global appkit_tag_dom_elements + CPImageAlignCenter = 0; CPImageAlignTop = 1; CPImageAlignTopLeft = 2; diff --git a/AppKit/CPKeyValueBinding.j b/AppKit/CPKeyValueBinding.j index 450de2152..bf07b282b 100644 --- a/AppKit/CPKeyValueBinding.j +++ b/AppKit/CPKeyValueBinding.j @@ -27,6 +27,7 @@ @import @import @import +@import var exposedBindingsMap = [CPDictionary new], diff --git a/AppKit/CPMenu/CPMenu.j b/AppKit/CPMenu/CPMenu.j index 958114b91..9cd143918 100644 --- a/AppKit/CPMenu/CPMenu.j +++ b/AppKit/CPMenu/CPMenu.j @@ -31,6 +31,8 @@ @import "CPMenuItem.j" @import "CPPanel.j" +@global CPApp + CPMenuDidAddItemNotification = @"CPMenuDidAddItemNotification"; CPMenuDidChangeItemNotification = @"CPMenuDidChangeItemNotification"; diff --git a/AppKit/CPMenu/_CPMenuBarWindow.j b/AppKit/CPMenu/_CPMenuBarWindow.j index a4a6378fc..964f310df 100644 --- a/AppKit/CPMenu/_CPMenuBarWindow.j +++ b/AppKit/CPMenu/_CPMenuBarWindow.j @@ -1,6 +1,10 @@ @import "CPPanel.j" @import "_CPMenuWindow.j" +@global CPMenuDidAddItemNotification +@global CPMenuDidChangeItemNotification +@global CPMenuDidRemoveItemNotification + @implementation _CPMenuBarWindow : CPPanel { CPMenu _menu; diff --git a/AppKit/CPMenu/_CPMenuManager.j b/AppKit/CPMenu/_CPMenuManager.j index d8a92c39c..3361eea90 100644 --- a/AppKit/CPMenu/_CPMenuManager.j +++ b/AppKit/CPMenu/_CPMenuManager.j @@ -1,5 +1,11 @@ @import +@class _CPMenuWindow + +@global CPApp +@global CPMenuDidEndTrackingNotification +@global _CPMenuWindowMenuBarBackgroundStyle +@global _CPMenuWindowPopUpBackgroundStyle _CPMenuManagerScrollingStateUp = -1; _CPMenuManagerScrollingStateDown = 1; @@ -26,6 +32,8 @@ var STICKY_TIME_INTERVAL = 0.5, CPMenuItem _previousActiveItem; int _showTimerID; + + int _menuBarButtonItemIndex; } + (_CPMenuManager)sharedMenuManager @@ -85,7 +93,7 @@ var STICKY_TIME_INTERVAL = 0.5, activeItem = activeItemIndex !== CPNotFound ? [menu itemAtIndex:activeItemIndex] : nil; _menuBarButtonItemIndex = activeItemIndex; - _menuBarButtonMenuContainer = aMenuContainer; +// _menuBarButtonMenuContainer = aMenuContainer; if ([activeItem _isMenuBarButton]) return [self trackMenuBarButtonEvent:anEvent]; @@ -556,7 +564,7 @@ var STICKY_TIME_INTERVAL = 0.5, return; } - next = current + (last - first); + var next = current + (last - first); if (next < [menu numberOfItems]) [menu _highlightItemAtIndex:next]; @@ -584,7 +592,7 @@ var STICKY_TIME_INTERVAL = 0.5, return; } - next = current - (last - first); + var next = current - (last - first); if (next < 0) [menu _highlightItemAtIndex:0]; diff --git a/AppKit/CPMenuItem/CPMenuItem.j b/AppKit/CPMenuItem/CPMenuItem.j index ea9e49225..e49923d53 100644 --- a/AppKit/CPMenuItem/CPMenuItem.j +++ b/AppKit/CPMenuItem/CPMenuItem.j @@ -29,6 +29,8 @@ @import "CPView.j" @import "_CPMenuItemView.j" +@global CPApp + var CPMenuItemStringRepresentationDictionary = [CPDictionary dictionary]; [CPMenuItemStringRepresentationDictionary setObject:"\u238B" forKey:CPEscapeFunctionKey]; diff --git a/AppKit/CPMenuItem/_CPMenuItemMenuBarView.j b/AppKit/CPMenuItem/_CPMenuItemMenuBarView.j index e088515c3..2f67ce4db 100644 --- a/AppKit/CPMenuItem/_CPMenuItemMenuBarView.j +++ b/AppKit/CPMenuItem/_CPMenuItemMenuBarView.j @@ -1,5 +1,8 @@ @import "CPView.j" +@class _CPMenuBarWindow +@class _CPMenuView + @implementation _CPMenuItemMenuBarView : CPView { CPMenuItem _menuItem @accessors(property=menuItem); diff --git a/AppKit/CPMenuItem/_CPMenuItemView.j b/AppKit/CPMenuItem/_CPMenuItemView.j index fff471bdd..9a2582b4d 100644 --- a/AppKit/CPMenuItem/_CPMenuItemView.j +++ b/AppKit/CPMenuItem/_CPMenuItemView.j @@ -5,6 +5,7 @@ @import "_CPMenuItemStandardView.j" @import "_CPMenuItemMenuBarView.j" +@global CPApp // var LEFT_MARGIN = 3.0, // RIGHT_MARGIN = 16.0, diff --git a/AppKit/CPObjectController.j b/AppKit/CPObjectController.j index 64ee8f5a0..242ce3153 100644 --- a/AppKit/CPObjectController.j +++ b/AppKit/CPObjectController.j @@ -798,7 +798,7 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo [_observationProxies removeObjectAtIndex:index]; - _observedObjects = nil; + _observedObjectsByKeyPath[aKeyPath] = nil; } @end diff --git a/AppKit/CPPasteboard.j b/AppKit/CPPasteboard.j index 5a898ead0..427e8125c 100644 --- a/AppKit/CPPasteboard.j +++ b/AppKit/CPPasteboard.j @@ -117,7 +117,7 @@ var CPPasteboards = nil, if (self) { - _name = aName; +// _name = aName; _types = []; _owners = [CPDictionary dictionary]; diff --git a/AppKit/CPResponder.j b/AppKit/CPResponder.j index 73199a1b5..dc2f9559c 100644 --- a/AppKit/CPResponder.j +++ b/AppKit/CPResponder.j @@ -22,6 +22,7 @@ @import +@class CPKeyBinding CPDeleteKeyCode = 8; CPTabKeyCode = 9; diff --git a/AppKit/CPRuleEditor/CPPredicateEditor.j b/AppKit/CPRuleEditor/CPPredicateEditor.j index 74317e001..887f8af68 100644 --- a/AppKit/CPRuleEditor/CPPredicateEditor.j +++ b/AppKit/CPRuleEditor/CPPredicateEditor.j @@ -220,7 +220,7 @@ var children = [CPArray array], itemsCount = 0, menuIndex = -1, - itemsArray, + itemArray, templateView = [templateViews objectAtIndex:count], isPopup = [templateView isKindOfClass:[CPPopUpButton class]]; diff --git a/AppKit/CPRuleEditor/CPPredicateEditorRowTemplate.j b/AppKit/CPRuleEditor/CPPredicateEditorRowTemplate.j index fda92ebf0..9214c6768 100644 --- a/AppKit/CPRuleEditor/CPPredicateEditorRowTemplate.j +++ b/AppKit/CPRuleEditor/CPPredicateEditorRowTemplate.j @@ -20,6 +20,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +@import + +@class CPDatePicker + + CPUndefinedAttributeType = 0; CPInteger16AttributeType = 100; CPInteger32AttributeType = 200; diff --git a/AppKit/CPRuleEditor/CPRuleEditor.j b/AppKit/CPRuleEditor/CPRuleEditor.j index a8798e475..ab6b703d0 100644 --- a/AppKit/CPRuleEditor/CPRuleEditor.j +++ b/AppKit/CPRuleEditor/CPRuleEditor.j @@ -31,6 +31,14 @@ @import "_CPRuleEditorViewSliceRow.j" @import "_CPRuleEditorLocalizer.j" +@class CPCompoundPredicate +@class CPComparisonPredicate + +@global CPDirectPredicateModifier +@global CPCaseInsensitivePredicateOption +@global CPOrPredicateType + + CPRuleEditorPredicateLeftExpression = "CPRuleEditorPredicateLeftExpression"; CPRuleEditorPredicateRightExpression = "CPRuleEditorPredicateRightExpression"; CPRuleEditorPredicateComparisonModifier = "CPRuleEditorPredicateComparisonModifier"; @@ -1703,8 +1711,8 @@ TODO: implement - (void)_setBoundDataSource:(id)datasource withKeyPath:(CPString)keyPath options:(CPDictionary)options { - if ([observableController respondsToSelector:@selector(objectClass)]) - _rowClass = [observableController objectClass]; + if ([datasource respondsToSelector:@selector(objectClass)]) + _rowClass = [datasource objectClass]; _boundArrayKeyPath = keyPath; _boundArrayOwner = datasource; diff --git a/AppKit/CPRuleEditor/_CPRuleEditorLocalizer.j b/AppKit/CPRuleEditor/_CPRuleEditorLocalizer.j index b5b92ea8f..935b6e759 100644 --- a/AppKit/CPRuleEditor/_CPRuleEditorLocalizer.j +++ b/AppKit/CPRuleEditor/_CPRuleEditorLocalizer.j @@ -13,7 +13,7 @@ var LocalizerStringsRegex = new RegExp("\"(.+)\"\\s*=\\s*\"(.+)\"\\s*;\\s*(//.+) { CPDictionary _dictionary @accessors(property=dictionary); CPURLConnection connection; - CPURLRequest resquest; + CPURLRequest request; } - (void)loadContentOfURL:(CPURL)aURL diff --git a/AppKit/CPRuleEditor/_CPRuleEditorPopUpButton.j b/AppKit/CPRuleEditor/_CPRuleEditorPopUpButton.j index d2f182647..2035b5cdf 100644 --- a/AppKit/CPRuleEditor/_CPRuleEditorPopUpButton.j +++ b/AppKit/CPRuleEditor/_CPRuleEditorPopUpButton.j @@ -46,9 +46,11 @@ else if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine)) { [self setBordered:NO]; +#if PLATFORM(DOM) var style = _DOMElement.style; style.border = "1px solid " + BORDER_COLOR; style[GRADIENT_PROPERTY] = GRADIENT_NORMAL; +#endif } - (id)initWithFrame:(CGRect)aFrame @@ -100,11 +102,13 @@ else if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine)) - (void)layoutSubviews { +#if PLATFORM(DOM) radius = FLOOR(CGRectGetHeight([self bounds]) / 2); var style = _DOMElement.style, radiusCSS = radius + "px"; style.borderRadius = radiusCSS; +#endif [super layoutSubviews]; } @@ -141,9 +145,11 @@ else if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine)) { [self setBordered:NO]; +#if PLATFORM(DOM) var style = _DOMElement.style; style.border = "1px solid " + BORDER_COLOR; style[GRADIENT_PROPERTY] = GRADIENT_NORMAL; +#endif } - (id)initWithFrame:(CGRect)aFrame @@ -164,6 +170,7 @@ else if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine)) - (void)layoutSubviews { +#if PLATFORM(DOM) radius = FLOOR(CGRectGetHeight([self bounds]) / 2); var style = _DOMElement.style, @@ -171,6 +178,7 @@ else if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine)) style.borderRadius = radiusCSS; style[GRADIENT_PROPERTY] = ([self isHighlighted]) ? GRADIENT_HIGHLIGHTED : GRADIENT_NORMAL; +#endif [super layoutSubviews]; } diff --git a/AppKit/CPRuleEditor/_CPRuleEditorViewSliceRow.j b/AppKit/CPRuleEditor/_CPRuleEditorViewSliceRow.j index 127785b67..75f4877cc 100644 --- a/AppKit/CPRuleEditor/_CPRuleEditorViewSliceRow.j +++ b/AppKit/CPRuleEditor/_CPRuleEditorViewSliceRow.j @@ -7,6 +7,11 @@ @import "_CPRuleEditorPopUpButton.j" @import "CPRuleEditor.j" +@global CPRuleEditorNestingModeCompound +@global CPRuleEditorRowTypeCompound +@global CPRuleEditorNestingModeSingle + + var CONTROL_HEIGHT = 16., BUTTON_HEIGHT = 16.; diff --git a/AppKit/CPScroller.j b/AppKit/CPScroller.j index 1e48c66d8..d38e465fe 100644 --- a/AppKit/CPScroller.j +++ b/AppKit/CPScroller.j @@ -27,6 +27,13 @@ @import "CPControl.j" +@class CPViewAnimation + +@global CPViewAnimationFadeOutEffect +@global CPViewAnimationTargetKey +@global CPViewAnimationEffectKey + + // CPScroller Constants CPScrollerNoPart = 0; CPScrollerDecrementPage = 1; diff --git a/AppKit/CPSearchField.j b/AppKit/CPSearchField.j index 2170aa7e5..a2747397e 100644 --- a/AppKit/CPSearchField.j +++ b/AppKit/CPSearchField.j @@ -23,6 +23,9 @@ @import "CPButton.j" @import "CPTextField.j" +@class CPUserDefaults + + CPSearchFieldRecentsTitleMenuItemTag = 1000; CPSearchFieldRecentsMenuItemTag = 1001; CPSearchFieldClearRecentsMenuItemTag = 1002; diff --git a/AppKit/CPSlider.j b/AppKit/CPSlider.j index 63f85c1ed..314d00724 100644 --- a/AppKit/CPSlider.j +++ b/AppKit/CPSlider.j @@ -39,6 +39,8 @@ CPCircularSlider = 1; double _altIncrementValue; BOOL _isVertical; + + CGSize _dragOffset; } + (CPString)defaultThemeClass diff --git a/AppKit/CPSliderColorPicker.j b/AppKit/CPSliderColorPicker.j index 3bf8106db..b1892d010 100644 --- a/AppKit/CPSliderColorPicker.j +++ b/AppKit/CPSliderColorPicker.j @@ -23,6 +23,12 @@ @import "CPView.j" @import "CPColorPicker.j" +@class CPSlider + +@global CPColorPickerViewWidth +@global CPColorPickerViewHeight +@global CPSliderColorPickerMode + /* @ignore @@ -65,7 +71,7 @@ - (id)initView { - aFrame = CGRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight); + var aFrame = CGRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight); _contentView = [[CPView alloc] initWithFrame:aFrame]; [_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; diff --git a/AppKit/CPSound.j b/AppKit/CPSound.j index 9fcbd9a9e..694b1095a 100644 --- a/AppKit/CPSound.j +++ b/AppKit/CPSound.j @@ -59,7 +59,7 @@ CPSoundPlayBackStatePause = 2; if (self = [super init]) { _loadStatus = CPSoundLoadStateEmpty; - _loops = NO; +// _loops = NO; _audioTag = document.createElement("audio"); _audioTag.preload = YES; _playRequestBeforeLoad = NO; diff --git a/AppKit/CPSplitView.j b/AppKit/CPSplitView.j index 53b280207..374c4211b 100644 --- a/AppKit/CPSplitView.j +++ b/AppKit/CPSplitView.j @@ -26,6 +26,9 @@ @import "CPImage.j" @import "CPView.j" +@class CPUserDefaults + + #define SPLIT_VIEW_MAYBE_POST_WILL_RESIZE() \ if ((_suppressResizeNotificationsMask & DidPostWillResizeNotification) === 0) \ { \ diff --git a/AppKit/CPTabViewItem.j b/AppKit/CPTabViewItem.j index 34cf8c01b..c2e4347ea 100644 --- a/AppKit/CPTabViewItem.j +++ b/AppKit/CPTabViewItem.j @@ -60,6 +60,7 @@ CPPressedTab = 2; CPView _auxiliaryView; CPTabView _tabView; + unsigned _tabState; // Looks like it is not yet implemented } - (id)init diff --git a/AppKit/CPTableColumn.j b/AppKit/CPTableColumn.j index 2ba2de937..bf1b4913e 100644 --- a/AppKit/CPTableColumn.j +++ b/AppKit/CPTableColumn.j @@ -29,6 +29,8 @@ @import "CPTableHeaderView.j" @import "CPKeyValueBinding.j" +@global CPTableViewColumnDidResizeNotification + CPTableColumnNoResizing = 0; CPTableColumnAutoresizingMask = 1 << 0; diff --git a/AppKit/CPTableHeaderView.j b/AppKit/CPTableHeaderView.j index 9051de645..1c459247b 100644 --- a/AppKit/CPTableHeaderView.j +++ b/AppKit/CPTableHeaderView.j @@ -26,6 +26,10 @@ @import "CPTableView.j" @import "CPView.j" +@class CPCursor + +@global CPTableColumnUserResizingMask + @implementation _CPTableColumnHeaderView : CPView { diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 6c548968f..3a607ecaf 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -31,6 +31,9 @@ @import "CPScroller.j" @import "CPCompatibility.j" +@class CPScrollView +@class CPUserDefaults + CPTableViewColumnDidMoveNotification = @"CPTableViewColumnDidMoveNotification"; CPTableViewColumnDidResizeNotification = @"CPTableViewColumnDidResizeNotification"; diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index 83a552b7f..79c6f2613 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -27,6 +27,10 @@ @import "CPCompatibility.j" @import "_CPImageAndTextView.j" +@class CPPasteboard + +@global CPApp +@global CPStringPboardType CPTextFieldSquareBezel = 0; /*! A textfield bezel with squared corners. */ CPTextFieldRoundedBezel = 1; /*! A textfield bezel with rounded corners. */ @@ -34,8 +38,6 @@ CPTextFieldRoundedBezel = 1; /*! A textfield bezel with rounded corne CPTextFieldDidFocusNotification = @"CPTextFieldDidFocusNotification"; CPTextFieldDidBlurNotification = @"CPTextFieldDidBlurNotification"; -#if PLATFORM(DOM) - var CPTextFieldDOMInputElement = nil, CPTextFieldDOMPasswordInputElement = nil, CPTextFieldDOMStandardInputElement = nil, @@ -49,8 +51,6 @@ var CPTextFieldDOMInputElement = nil, CPTextFieldBlurHandler = nil, CPTextFieldInputFunction = nil; -#endif - var CPSecureTextFieldCharacter = "\u2022"; diff --git a/AppKit/CPTheme.j b/AppKit/CPTheme.j index e5fd49d85..1b74f6081 100644 --- a/AppKit/CPTheme.j +++ b/AppKit/CPTheme.j @@ -25,6 +25,7 @@ @import @import +@class CPView var CPThemesByName = { }, CPThemeDefaultTheme = nil, @@ -146,7 +147,7 @@ var CPThemesByName = { }, className = [aClass defaultThemeClass]; else if ([aClass respondsToSelector:@selector(themeClass)]) { - CPLog.warn(@"%@ themeClass is deprecated in favor of defaultThemeClass",CPStringFromClass([anObject class])); + CPLog.warn(@"%@ themeClass is deprecated in favor of defaultThemeClass",CPStringFromClass(aClass)); className = [aClass themeClass]; } else diff --git a/AppKit/CPTokenField.j b/AppKit/CPTokenField.j index 5ad794e3a..a16a77af2 100755 --- a/AppKit/CPTokenField.j +++ b/AppKit/CPTokenField.j @@ -911,7 +911,9 @@ var CPScrollDestinationNone = 0, - (void)keyDown:(CPEvent)anEvent { +#if PLATFORM(DOM) CPTokenFieldTextDidChangeValue = [self stringValue]; +#endif // Leave the default _propagateCurrentDOMEvent setting in place. This might be YES or NO depending // on if something that could be a browser shortcut was pressed or not, such as Cmd-R to reload. @@ -925,10 +927,12 @@ var CPScrollDestinationNone = 0, - (void)keyUp:(CPEvent)anEvent { +#if PLATFORM(DOM) if ([self stringValue] !== CPTokenFieldTextDidChangeValue) { [self textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:self userInfo:nil]]; } +#endif [[[self window] platformWindow] _propagateCurrentDOMEvent:YES]; } diff --git a/AppKit/CPUserDefaultsController.j b/AppKit/CPUserDefaultsController.j index 4decd0ec3..0cf110da0 100644 --- a/AppKit/CPUserDefaultsController.j +++ b/AppKit/CPUserDefaultsController.j @@ -27,6 +27,11 @@ @import @import "CPController.j" +@class CPUserDefaults + +@global CPUserDefaultsDidChangeNotification + + var SharedUserDefaultsController = nil; @implementation CPUserDefaultsController : CPController @@ -34,6 +39,7 @@ var SharedUserDefaultsController = nil; CPUserDefaults _defaults @accessors(readonly, property=defaults); CPDictionary _initialValues @accessors(property=initialValues); BOOL _appliesImmediately @accessors(property=appliesImmediately); + id _valueProxy; } + (id)sharedUserDefaultsController diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 25801757a..9abfa56fe 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -34,6 +34,18 @@ @import "CPTheme.j" @import "_CPDisplayServer.j" +@class _CPToolTip +@class CPWindow +@class _CPMenuItemView +@class CPPlatformWindow +@class CPMenu +@class CPClipView +@class CPScrollView + +@global appkit_tag_dom_elements +@global CPWindowAbove +@global CPBorderlessWindowMask +@global CPScreenSaverWindowLevel /* @global @@ -2192,6 +2204,7 @@ setBoundsOrigin: { var graphicsPort = CGBitmapGraphicsContextCreate(); +#if PLATFORM(DOM) _DOMContentsElement = graphicsPort.DOMElement; _DOMContentsElement.style.zIndex = -100; @@ -2208,7 +2221,6 @@ setBoundsOrigin: _DOMContentsElement.style.width = ROUND(_CGRectGetWidth(_frame)) + "px"; _DOMContentsElement.style.height = ROUND(_CGRectGetHeight(_frame)) + "px"; -#if PLATFORM(DOM) // The performance implications of this aren't clear, but without this subviews might not be redrawn when this // view moves. if (CPPlatformHasBug(CPCanvasParentDrawErrorsOnMovementBug)) diff --git a/AppKit/CPViewController.j b/AppKit/CPViewController.j index f6268b4dc..caddcbd62 100644 --- a/AppKit/CPViewController.j +++ b/AppKit/CPViewController.j @@ -26,6 +26,10 @@ @import "CPCib.j" @import "CPResponder.j" +@class CPDocument + +@global CPApp + var CPViewControllerCachedCibs; @@ -222,7 +226,7 @@ var CPViewControllerCachedCibs; { [self willChangeValueForKey:"isViewLoaded"]; [self viewDidLoad]; - isViewLoaded = YES; + _isViewLoaded = YES; [self didChangeValueForKey:"isViewLoaded"]; } diff --git a/AppKit/CPWindow/_CPAttachedWindowView.j b/AppKit/CPWindow/_CPAttachedWindowView.j index fb3b2c7b4..c92ca0b4d 100644 --- a/AppKit/CPWindow/_CPAttachedWindowView.j +++ b/AppKit/CPWindow/_CPAttachedWindowView.j @@ -21,6 +21,9 @@ */ @import "_CPWindowView.j" +@import "CGGradient.j" + +@global CPPopoverAppearanceMinimal #define ALIGN_STROKE(point) (FLOOR(point) === (point) ? (point) + halfStrokeWidth : (point)) #define ALIGN_COORD(point) (FLOOR(point)) diff --git a/AppKit/CPWindow/_CPStandardWindowView.j b/AppKit/CPWindow/_CPStandardWindowView.j index 1994cf3eb..36e6b56b1 100644 --- a/AppKit/CPWindow/_CPStandardWindowView.j +++ b/AppKit/CPWindow/_CPStandardWindowView.j @@ -23,6 +23,8 @@ @import "CPTextField.j" @import "_CPTitleableWindowView.j" +@class _CPDocModalWindowView + @implementation _CPTexturedWindowHeadView : CPView { CPView _gradientView; diff --git a/AppKit/CPWindow/_CPWindow.j b/AppKit/CPWindow/_CPWindow.j index 0cbec5113..5a2cd8e7c 100644 --- a/AppKit/CPWindow/_CPWindow.j +++ b/AppKit/CPWindow/_CPWindow.j @@ -34,6 +34,17 @@ @import "CPPlatformWindow+DOM.j" #endif +@class _CPShadowWindowView +@class CPCursor +@class CPDragServer +@class CPMenu +@class CPProgressIndicator + +@global CPApp +@global CPWindowPositionFlexibleLeft +@global CPWindowPositionFlexibleRight +@global CPWindowPositionFlexibleTop +@global CPWindowPositionFlexibleBottom /* Borderless window mask option. diff --git a/AppKit/CPWindow/_CPWindowView.j b/AppKit/CPWindow/_CPWindowView.j index af367ed0f..c94317f02 100644 --- a/AppKit/CPWindow/_CPWindowView.j +++ b/AppKit/CPWindow/_CPWindowView.j @@ -23,6 +23,10 @@ @import "CPImageView.j" @import "CPView.j" +@class CPCursor +@class CPMenu + +@global CPApp var _CPWindowViewCornerResizeRectWidth = 10, _CPWindowViewResizeRegionNone = -1, diff --git a/AppKit/CPWindowController.j b/AppKit/CPWindowController.j index f8c0a2149..feb4ae668 100644 --- a/AppKit/CPWindowController.j +++ b/AppKit/CPWindowController.j @@ -27,6 +27,13 @@ @import "CPWindow.j" @import "CPDocument.j" +@class CPDocument + +@global CPApp +@global CPDocumentWillSaveNotification +@global CPDocumentDidSaveNotification +@global CPDocumentDidFailToSaveNotification + /*! @ingroup appkit diff --git a/AppKit/Cib/_CPCibCustomObject.j b/AppKit/Cib/_CPCibCustomObject.j index 165b24153..89652fe84 100644 --- a/AppKit/Cib/_CPCibCustomObject.j +++ b/AppKit/Cib/_CPCibCustomObject.j @@ -1,6 +1,8 @@ @import +@class CPApplication + var _CPCibCustomObjectClassName = @"_CPCibCustomObjectClassName"; diff --git a/AppKit/Cib/_CPCibCustomResource.j b/AppKit/Cib/_CPCibCustomResource.j index 7da52200b..514292520 100644 --- a/AppKit/Cib/_CPCibCustomResource.j +++ b/AppKit/Cib/_CPCibCustomResource.j @@ -26,6 +26,8 @@ @import @import +@class CPButtonBar + var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey", _CPCibCustomResourceResourceNameKey = @"_CPCibCustomResourceResourceNameKey", diff --git a/AppKit/Cib/_CPCibObjectData.j b/AppKit/Cib/_CPCibObjectData.j index 2d1eecf95..3b7ed9f67 100644 --- a/AppKit/Cib/_CPCibObjectData.j +++ b/AppKit/Cib/_CPCibObjectData.j @@ -32,6 +32,8 @@ @import "CPCibRuntimeAttributesConnector.j" @import "CPCibHelpConnector.j" +@class CPScrollView + @implementation _CPCibObjectData : CPObject { diff --git a/AppKit/Cib/_CPCibWindowTemplate.j b/AppKit/Cib/_CPCibWindowTemplate.j index 15be5c261..6cee86b69 100644 --- a/AppKit/Cib/_CPCibWindowTemplate.j +++ b/AppKit/Cib/_CPCibWindowTemplate.j @@ -4,6 +4,11 @@ @import "CGGeometry.j" @import "CPWindow.j" +@class CPToolbar + +@global CPPositionProportionalHorizontal +@global CPPositionProportionalVertical + CPWindowPositionFlexibleRight = 1 << 19; CPWindowPositionFlexibleLeft = 1 << 20; CPWindowPositionFlexibleBottom = 1 << 21; diff --git a/AppKit/CoreAnimation/CALayer.j b/AppKit/CoreAnimation/CALayer.j index 8e1d19651..a86b1795a 100644 --- a/AppKit/CoreAnimation/CALayer.j +++ b/AppKit/CoreAnimation/CALayer.j @@ -85,6 +85,7 @@ var CALayerRegisteredRunLoopUpdates = nil; float _opacity; BOOL _isHidden; + BOOL _masksToBounds; CPColor _backgroundColor; // Managing Layer Hierarchy @@ -856,7 +857,7 @@ if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex) */ - (void)setNeedsDisplayInRect:(CGRect)aRect { - _dirtyRect = aRect; +// _dirtyRect = aRect; [self display]; } diff --git a/AppKit/Platform/CPPlatformWindow.j b/AppKit/Platform/CPPlatformWindow.j index 6a1188fe2..f1920e57c 100644 --- a/AppKit/Platform/CPPlatformWindow.j +++ b/AppKit/Platform/CPPlatformWindow.j @@ -21,7 +21,14 @@ */ @import +@import "CPKeyBinding.j" +//@import "CPMenu.j" +@import "CPPlatform.j" +//@import "CPEvent.j" +@class CPMenu + +@global CPApp var PrimaryPlatformWindow = NULL; diff --git a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j index dff0fb70f..c7b6233ea 100644 --- a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j +++ b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j @@ -119,6 +119,25 @@ @import "CPPlatformWindow.j" @import "CPPlatformWindow+DOMKeys.j" +@class CPCursor +@class CPDragServer +@class CPPasteboard +@class _CPDOMDataTransferPasteboard +@class _CPToolTip + +@global CPDragOperationNone +@global CPDragOperationMove +@global CPDragOperationCopy +@global CPDragOperationLink +@global CPDragOperationPrivate +@global CPDragOperationGeneric +@global CPApp +@global CPStringPboardType +@global CPWindowOut +@global _CPRunModalLoop +@global CPDraggingWindowLevel +@global CPWindowAbove + // List of all open native windows var PlatformWindows = [CPSet set]; @@ -192,6 +211,7 @@ var ModifierKeyCodes = [ var resizeTimer = nil; +#if PLATFORM(DOM) @implementation CPPlatformWindow (DOM) - (id)_init @@ -795,7 +815,7 @@ var resizeTimer = nil; if (!characters) characters = String.fromCharCode(charCode); - charactersIgnoringModifiers = characters.toLowerCase(); // FIXME: This isn't correct. It SHOULD include Shift. + var charactersIgnoringModifiers = characters.toLowerCase(); // FIXME: This isn't correct. It SHOULD include Shift. // Safari won't send proper capitalization during cmd-key events if (!overrideCharacters && (modifierFlags & CPCommandKeyMask) && ((modifierFlags & CPShiftKeyMask) || _capsLockActive)) @@ -879,7 +899,7 @@ var resizeTimer = nil; windowNumber = [[CPApp keyWindow] windowNumber], modifierFlags = CPPlatformActionKeyMask; - event = [CPEvent keyEventWithType:CPKeyDown location:location modifierFlags:modifierFlags + var event = [CPEvent keyEventWithType:CPKeyDown location:location modifierFlags:modifierFlags timestamp:timestamp windowNumber:windowNumber context:nil characters:characters charactersIgnoringModifiers:characters isARepeat:NO keyCode:keyCode]; @@ -1581,6 +1601,7 @@ var resizeTimer = nil; } @end +#endif var CPEventClass = [CPEvent class]; diff --git a/AppKit/_CPAttachedWindow.j b/AppKit/_CPAttachedWindow.j index fdb0e0a0f..be5e16a72 100644 --- a/AppKit/_CPAttachedWindow.j +++ b/AppKit/_CPAttachedWindow.j @@ -354,8 +354,10 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, { var browserProperty = CPBrowserStyleProperty(aProperty); +#if PLATFORM(DOM) if (browserProperty) _DOMElement.style[browserProperty] = value; +#endif } /*! @ignore */ @@ -430,7 +432,7 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, var transformOrigin = "50% 100%", frame = [self frame], preferredEdge = [_windowView preferredEdge], - posX; + posX, posY; switch (preferredEdge) { @@ -455,9 +457,11 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, window.setTimeout(function() { // We are watching opacity, so this triggers the next transition +#if PLATFORM(DOM) _DOMElement.style.opacity = 1; _DOMElement.style.height = frame.size.height + @"px"; _DOMElement.style.width = frame.size.width + @"px"; +#endif // Set up the pop-out transition [self setCSS3Property:@"Transform" value:@"scale(1.1)"]; @@ -465,7 +469,9 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, var transitionEndFunction = function() { +#if PLATFORM(DOM) _DOMElement.removeEventListener(CPBrowserStyleProperty('transitionend'), transitionEndFunction, YES); +#endif // Now set up the pop-in to normal size transition. // Because we are watching the -webkit-transform, it will occur now. @@ -474,21 +480,29 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, var transitionCompleteFunction = function() { +#if PLATFORM(DOM) _DOMElement.removeEventListener(CPBrowserStyleProperty('transitionend'), transitionCompleteFunction, YES); +#endif if (_implementedDelegateMethods & _CPAttachedWindow_attachedWindowDidShow_) [_delegate attachedWindowDidShow:self]; } +#if PLATFORM(DOM) _DOMElement.addEventListener(CPBrowserStyleProperty('transitionend'), transitionCompleteFunction, YES); +#endif }; +#if PLATFORM(DOM) _DOMElement.addEventListener(CPBrowserStyleProperty('transitionend'), transitionEndFunction, YES); +#endif }, 0); } else { [self setCSS3Property:@"Transition" value:@""]; +#if PLATFORM(DOM) _DOMElement.style.opacity = 1; +#endif } } @@ -511,15 +525,21 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, { // Tell the element to fade out when the opacity changes [self setCSS3Property:@"Transition" value:@"opacity 250ms linear"]; +#if PLATFORM(DOM) _DOMElement.style.opacity = 0; +#endif var transitionEndFunction = function() { +#if PLATFORM(DOM) _DOMElement.removeEventListener(CPBrowserStyleProperty("transitionend"), transitionEndFunction, YES); +#endif [self _close]; }; +#if PLATFORM(DOM) _DOMElement.addEventListener(CPBrowserStyleProperty("transitionend"), transitionEndFunction, YES); +#endif } else { diff --git a/AppKit/_CPAutocompleteMenu.j b/AppKit/_CPAutocompleteMenu.j index 59a8bef3a..8e5c0b402 100644 --- a/AppKit/_CPAutocompleteMenu.j +++ b/AppKit/_CPAutocompleteMenu.j @@ -26,6 +26,9 @@ @import "CPTableView.j" @import "_CPMenuWindow.j" +@class CPScrollView + + // TODO Make themable. var _CPAutocompleteMenuMaximumHeight = 307; diff --git a/AppKit/_CPImageAndTextView.j b/AppKit/_CPImageAndTextView.j index 73e68a251..5398166e8 100644 --- a/AppKit/_CPImageAndTextView.j +++ b/AppKit/_CPImageAndTextView.j @@ -27,6 +27,7 @@ @import "CPImage.j" @import "CPView.j" @import "CPControl.j" +@import "CPPlatform.j" var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0, @@ -294,6 +295,7 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0, var textFrame = _CGRectMakeZero(); +#if PLATFORM(DOM) if (_DOMTextElement) { var textStyle = _DOMTextElement.style; @@ -306,6 +308,7 @@ var _CPimageAndTextViewFrameSizeChangedFlag = 1 << 0, textFrame.size.width += _textShadowOffset.width; textFrame.size.height += _textShadowOffset.height; } +#endif return textFrame; } diff --git a/AppKit/_CPPopUpList.j b/AppKit/_CPPopUpList.j index fd6cfa920..34ea79cc3 100644 --- a/AppKit/_CPPopUpList.j +++ b/AppKit/_CPPopUpList.j @@ -24,6 +24,10 @@ @import "CPPanel.j" @import "_CPPopUpListDataSource.j" +@class CPScrollView + +@global CPLineBorder + /*! Notification sent when the list is about to pop up. \c object is the _CPPopUpList. @@ -840,7 +844,7 @@ var _CPPopUpListDataSourceKey = @"_CPPopUpListDataSourceKey", */ - (CPTableColumn)listColumn { - return _tableColumn; + return _tableColumns[0]; } @end diff --git a/Foundation/CPArray+KVO.j b/Foundation/CPArray+KVO.j index 0f6ca990c..e5c381a70 100644 --- a/Foundation/CPArray+KVO.j +++ b/Foundation/CPArray+KVO.j @@ -24,6 +24,7 @@ @import "CPNull.j" @import "_CPCollectionKVCOperators.j" +@class CPIndexSet @implementation CPObject (CPArrayKVO) diff --git a/Foundation/CPArray/CPMutableArray.j b/Foundation/CPArray/CPMutableArray.j index f950e3a6a..a1b3538ee 100644 --- a/Foundation/CPArray/CPMutableArray.j +++ b/Foundation/CPArray/CPMutableArray.j @@ -1,6 +1,7 @@ @import "_CPArray.j" +@class CPIndexSet /*! @class CPMutableArray diff --git a/Foundation/CPArray/_CPArray.j b/Foundation/CPArray/_CPArray.j index 2f38e3faf..7b61092eb 100755 --- a/Foundation/CPArray/_CPArray.j +++ b/Foundation/CPArray/_CPArray.j @@ -26,6 +26,8 @@ @import "CPRange.j" @import "CPSortDescriptor.j" +@class _CPJavaScriptArray +@class CPIndexSet CPEnumerationNormal = 0; CPEnumerationConcurrent = 1 << 0; diff --git a/Foundation/CPCharacterSet.j b/Foundation/CPCharacterSet.j index 8a372e0a5..c9b376f34 100644 --- a/Foundation/CPCharacterSet.j +++ b/Foundation/CPCharacterSet.j @@ -237,8 +237,8 @@ var CPCharacterSetInvertedKey = @"CPCharacterSetInvertedKey"; - (BOOL)characterIsMember:(CPString)aCharacter { - c = aCharacter.charCodeAt(0); - var enu = [_ranges objectEnumerator], + var c = aCharacter.charCodeAt(0), + enu = [_ranges objectEnumerator], range; while ((range = [enu nextObject]) !== nil) diff --git a/Foundation/CPCoder.j b/Foundation/CPCoder.j index bb07ac846..dddcf6f3b 100644 --- a/Foundation/CPCoder.j +++ b/Foundation/CPCoder.j @@ -23,6 +23,8 @@ @import "CPException.j" @import "CPObject.j" +@global _CPRaiseInvalidAbstractInvocation; + /*! @class CPCoder @ingroup foundation diff --git a/Foundation/CPDateFormatter.j b/Foundation/CPDateFormatter.j index 0dd9d4062..175cb9aa8 100644 --- a/Foundation/CPDateFormatter.j +++ b/Foundation/CPDateFormatter.j @@ -78,9 +78,9 @@ CPDateFormatterFullStyle = 4; { case CPDateFormatterShortStyle: var format = "d/m/Y"; - return Date.parseDate(string, format); + return Date.parseDate(aString, format); default: - return Date.parseDate(string); + return Date.parseDate(aString); } } diff --git a/Foundation/CPException.j b/Foundation/CPException.j index 8b0d99342..be23f3d62 100755 --- a/Foundation/CPException.j +++ b/Foundation/CPException.j @@ -28,6 +28,7 @@ CPInvalidArgumentException = @"CPInvalidArgumentException"; CPUnsupportedMethodException = @"CPUnsupportedMethodException"; CPRangeException = @"CPRangeException"; CPInternalInconsistencyException = @"CPInternalInconsistencyException"; +CPGenericException = @"CPGenericException"; /*! @class CPException diff --git a/Foundation/CPKeyedArchiver.j b/Foundation/CPKeyedArchiver.j index 0dd5b1659..5dec686e2 100644 --- a/Foundation/CPKeyedArchiver.j +++ b/Foundation/CPKeyedArchiver.j @@ -33,8 +33,8 @@ var CPArchiverReplacementClassNames = nil; var _CPKeyedArchiverDidEncodeObjectSelector = 1, _CPKeyedArchiverWillEncodeObjectSelector = 2, _CPKeyedArchiverWillReplaceObjectWithObjectSelector = 4, - _CPKeyedArchiverDidFinishSelector = 8, - _CPKeyedArchiverWillFinishSelector = 16; + _CPKeyedArchiverDidFinishEncodingSelector = 8, + _CPKeyedArchiverWillFinishEncodingSelector = 16; var _CPKeyedArchiverNullString = "$null", _CPKeyedArchiverNullReference = nil, @@ -190,7 +190,7 @@ var _CPKeyedArchiverStringClass = Nil, */ - (void)finishEncoding { - if (_delegate && _delegateSelectors & _CPKeyedArchiverWillFinishSelector) + if (_delegate && _delegateSelectors & _CPKeyedArchiverDidFinishEncodingSelector) [_delegate archiverWillFinish:self]; var i = 0, @@ -220,7 +220,7 @@ var _CPKeyedArchiverStringClass = Nil, [_data setPlistObject:_plistObject]; - if (_delegate && _delegateSelectors & _CPKeyedArchiverDidFinishSelector) + if (_delegate && _delegateSelectors & _CPKeyedArchiverDidFinishEncodingSelector) [_delegate archiverDidFinish:self]; } @@ -460,7 +460,7 @@ var _CPKeyedArchiverStringClass = Nil, if (!_replacementClassNames) return aClass.name; - var className = [_replacementClassNames objectForKey:CPStringFromClass(aClassName)]; + var className = [_replacementClassNames objectForKey:CPStringFromClass(aClass)]; return className ? className : aClass.name; } diff --git a/Foundation/CPKeyedUnarchiver.j b/Foundation/CPKeyedUnarchiver.j index 9d5f0a3f6..1a01beb8e 100644 --- a/Foundation/CPKeyedUnarchiver.j +++ b/Foundation/CPKeyedUnarchiver.j @@ -417,7 +417,7 @@ var CPArrayClass = Ni _delegateSelectors |= _CPKeyedUnarchiverWillReplaceObjectWithObjectSelector; if ([_delegate respondsToSelector:@selector(unarchiverWillFinish:)]) - _delegateSelectors |= _CPKeyedUnarchiverWilFinishSelector; + _delegateSelectors |= _CPKeyedUnarchiverWillFinishSelector; if ([_delegate respondsToSelector:@selector(unarchiverDidFinish:)]) _delegateSelectors |= _CPKeyedUnarchiverDidFinishSelector; diff --git a/Foundation/CPNotificationCenter.j b/Foundation/CPNotificationCenter.j index dcf611bad..25107027f 100644 --- a/Foundation/CPNotificationCenter.j +++ b/Foundation/CPNotificationCenter.j @@ -25,6 +25,7 @@ @import "CPException.j" @import "CPNotification.j" @import "CPNull.j" +@import "CPSet.j" var CPNotificationDefaultCenter = nil; diff --git a/Foundation/CPOperation.j b/Foundation/CPOperation.j index efe2e5d25..4fbdd5612 100644 --- a/Foundation/CPOperation.j +++ b/Foundation/CPOperation.j @@ -22,6 +22,8 @@ @import "CPArray.j" @import "CPObject.j" +@global CPKeyValueObservingOptionNew + /*! Operations receive very low priority for execution. @global diff --git a/Foundation/CPOperationQueue.j b/Foundation/CPOperationQueue.j index 1007ea633..1e018df15 100644 --- a/Foundation/CPOperationQueue.j +++ b/Foundation/CPOperationQueue.j @@ -50,7 +50,7 @@ var cpOperationMainQueue = nil; { _operations = [[CPArray alloc] init]; _suspended = NO; - _currentlyModifyingOps = NO; +// _currentlyModifyingOps = NO; _timer = [CPTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(_runNextOpsInQueue) diff --git a/Foundation/CPPredicate/CPComparisonPredicate.j b/Foundation/CPPredicate/CPComparisonPredicate.j index d890aa76e..962d4e277 100644 --- a/Foundation/CPPredicate/CPComparisonPredicate.j +++ b/Foundation/CPPredicate/CPComparisonPredicate.j @@ -26,7 +26,7 @@ @import "CPEnumerator.j" @import "CPExpression.j" @import "CPNull.j" -@import "CPPredicate.j" +@import "_CPPredicate.j" @import "CPString.j" /*! diff --git a/Foundation/CPPredicate/CPCompoundPredicate.j b/Foundation/CPPredicate/CPCompoundPredicate.j index d4fa0b1b2..97aabe002 100644 --- a/Foundation/CPPredicate/CPCompoundPredicate.j +++ b/Foundation/CPPredicate/CPCompoundPredicate.j @@ -23,7 +23,7 @@ */ @import "CPArray.j" -@import "CPPredicate.j" +@import "_CPPredicate.j" /*! A predicate to directly compare the left and right hand sides. diff --git a/Foundation/CPPredicate/CPPredicate.j b/Foundation/CPPredicate/CPPredicate.j index b0a9c984f..10c0db099 100644 --- a/Foundation/CPPredicate/CPPredicate.j +++ b/Foundation/CPPredicate/CPPredicate.j @@ -22,954 +22,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -@import "CPArray.j" -@import "CPException.j" -@import "CPNull.j" -@import "CPObject.j" -@import "CPScanner.j" -@import "CPSet.j" -@import "CPValue.j" -@import "CPCharacterSet.j" - -/*! - @ingroup foundation - @class CPPredicate - @brief The CPPredicate class is used to define logical conditions used to constrain a search either for a fetch or for in-memory filtering. - - You use predicates to represent logical conditions, used for describing objects in persistent stores - and in-memory filtering of objects. Although it is common to create predicates directly from instances - of CPComparisonPredicate, CPCompoundPredicate, and CPExpression, you often create predicates from a - format string which is parsed by the class methods on CPPredicate. Examples of predicate format strings include: - - - Simple comparisons, such as grade == "7" or firstName like "Shaffiq" - - Case/diacritic insensitive lookups, such as name contains[cd] "itroen" - - Logical operations, such as (firstName like "Mark") OR (lastName like "Adderley") - - “Between” predicates such as date between {$YESTERDAY, $TOMORROW}. - - You can create predicates for relationships, such as: - - - group.name like "work*" - - ALL children.age > 12 - - ANY children.age > 12 - - You can create predicates for operations, such as \@sum.items.price < 1000. - - You can also create predicates that include variables, so that the predicate can be pre-defined before - substituting concrete values at runtime with the \c evaluateWithObject:substitutionVariables: method. -*/ - -@implementation CPPredicate : CPObject -{ -} - -/*! - Creates and returns a new predicate formed by creating a new string with a given format and parsing the result. - @param format The format string for the new predicate. - @param … A comma-separated list of arguments to substitute into format. - @return A new predicate formed by creating a new string with format and parsing the result. -*/ -+ (CPPredicate)predicateWithFormat:(CPString)format, ... -{ - if (!format) - [CPException raise:CPInvalidArgumentException reason:_cmd + " the format can't be 'nil'"]; - - var args = Array.prototype.slice.call(arguments, 3); - return [self predicateWithFormat:arguments[2] argumentArray:args]; -} - -/*! - Creates and returns a new predicate by substituting the values in a given array into a format string and parsing the result. - @param format The format string for the new predicate. - @param arguments The arguments to substitute into predicateFormat. Values are substituted into predicateFormat in the order they appear in the array. - @return A new predicate by substituting the values in arguments into predicateFormat, and parsing the result. -*/ -+ (CPPredicate)predicateWithFormat:(CPString)format argumentArray:(CPArray)args -{ - if (!format) - [CPException raise:CPInvalidArgumentException reason:_cmd + " the format can't be 'nil'"]; - - var s = [[CPPredicateScanner alloc] initWithString:format args:args], - p = [s parse]; - - return p; -} - -/*! - Creates and returns a new predicate by substituting the values in an argument list into a format string and parsing the result. - @param format The format string for the new predicate. - @param argList The arguments to substitute into predicateFormat. Values are substituted into predicateFormat in the order they appear in the argument list. - @return A new predicate by substituting the values in argList into predicateFormat and parsing the result. -*/ -+ (CPPredicate)predicateWithFormat:(CPString)format arguments:(va_list)argList -{ - // UNIMPLEMENTED - return nil; -} - -/*! - Returns a copy of the receiver with the receiver’s variables substituted by values specified in a given substitution variables dictionary. - @param variables The substitution variables dictionary. The dictionary must contain key-value pairs for all variables in the receiver. - @return A copy of the receiver with the receiver’s variables substituted by values specified in variables. -*/ -- (CPPredicate)predicateWithSubstitutionVariables:(CPDictionary)variables -{ - // IMPLEMENTED BY SUBCLASSES -} - -/*! - Creates and returns a predicate that always evaluates to a given value. - @param value The value to which the new predicate should evaluate. - @return A predicate that always evaluates to value. -*/ -+ (CPPredicate)predicateWithValue:(BOOL)value -{ - return [[CPPredicate_BOOL alloc] initWithBool:value]; -} - -// Evaluating a Predicate -/*! - Returns a Boolean value that indicates whether a given object matches the conditions specified by the receiver. - @param object The object against which to evaluate the receiver. - @return YES if object matches the conditions specified by the receiver, otherwise NO. -*/ -- (BOOL)evaluateWithObject:(id)object -{ - // IMPLEMENTED BY SUBCLASSES -} - -/*! - Returns a Boolean value that indicates whether a given object matches the conditions specified by the receiver after substituting in the values in a given variables dictionary. - @param object The object against which to evaluate the receiver. - @param variables The substitution variables dictionary. The dictionary must contain key-value pairs for all variables in the receiver. - @return YES if object matches the conditions specified by the receiver after substituting in the values in variables for any replacement tokens, otherwise NO. -*/ -- (BOOL)evaluateWithObject:(id)object substitutionVariables:(CPDictionary)variables -{ - // IMPLEMENTED BY SUBCLASSES -} - -// Getting Format Information -/*! - Returns the receiver’s format string. - @return The receiver’s format string. -*/ -- (CPString)predicateFormat -{ - // IMPLEMENTED BY SUBCLASSES -} - -- (CPString)description -{ - return [self predicateFormat]; -} - -@end - -@implementation CPPredicate_BOOL : CPPredicate -{ - BOOL _value; -} - -- (id)initWithBool:(BOOL)value -{ - _value = value; - return self; -} - -- (BOOL)isEqual:(id)anObject -{ - if (self === anObject) - return YES; - - if (self.isa !== anObject.isa || _value !== [anObject evaluateObject:nil]) - return NO; - - return YES; -} - -- (BOOL)evaluateObject:(id)object -{ - return _value; -} - -- (CPString)predicateFormat -{ - return (_value) ? @"TRUEPREDICATE" : @"FALSEPREDICATE"; -} - -@end - - -@implementation CPArray (CPPredicate) - -- (CPArray)filteredArrayUsingPredicate:(CPPredicate)predicate -{ - var count = [self count], - result = [CPArray array], - i = 0; - - for (; i < count; i++) - { - var object = [self objectAtIndex:i]; - if ([predicate evaluateWithObject:object]) - result.push(object); - } - - return result; -} - -- (void)filterUsingPredicate:(CPPredicate)predicate -{ - var count = [self count]; - - while (count--) - { - if (![predicate evaluateWithObject:[self objectAtIndex:count]]) - self.splice(count, 1); - } -} - -@end - -@implementation CPSet (CPPredicate) - -- (CPSet)filteredSetUsingPredicate:(CPPredicate)predicate -{ - var count = [self count], - result = [CPSet set], - i = 0; - - for (; i < count; i++) - { - var object = [self objectAtIndex:i]; - - if ([predicate evaluateWithObject:object]) - [result addObject:object]; - } - - return result; -} - -- (void)filterUsingPredicate:(CPPredicate)predicate -{ - var count = [self count]; - - while (--count >= 0) - { - var object = [self objectAtIndex:count]; - - if (![predicate evaluateWithObject:object]) - [self removeObjectAtIndex:count]; - } -} - -@end - -#define REFERENCE(variable) \ -function(newValue)\ -{\ - var oldValue = variable;\ - if (typeof newValue != 'undefined')\ - variable = newValue;\ - return oldValue;\ -} - -@implementation CPPredicateScanner : CPScanner -{ - CPEnumerator _args; - unsigned _retrieved; -} - -- (id)initWithString:(CPString)format args:(CPArray)args -{ - self = [super initWithString:format] - - if (self) - { - _args = [args objectEnumerator]; - } - return self; -} - -- (id)nextArg -{ - return [_args nextObject]; -} - -- (BOOL)scanPredicateKeyword:(CPString)key -{ - var loc = [self scanLocation]; - - [self setCaseSensitive:NO]; - if (![self scanString:key intoString:NULL]) - return NO; - - if ([self isAtEnd]) - return YES; - - var c = [[self string] characterAtIndex:[self scanLocation]]; - if (![[CPCharacterSet alphanumericCharacterSet] characterIsMember:c]) - return YES; - - [self setScanLocation:loc]; - - return NO; -} - -- (CPPredicate)parse -{ - var r = nil; - - try - { - [self setCharactersToBeSkipped:[CPCharacterSet whitespaceCharacterSet]]; - r = [self parsePredicate]; - } - catch(error) - { - CPLogConsole(@"Unable to parse predicate '" + [self string] + "' with " + error); - } - finally - { - if (![self isAtEnd]) - { - var pstr = [self string], - loc = [self scanLocation]; - CPLogConsole(@"Format string contains extra characters: '" + [pstr substringToIndex:loc] + "**" + [pstr substringFromIndex:loc] + "**'"); - } - } - - return r; -} - -- (CPPredicate)parsePredicate -{ - return [self parseAnd]; -} - -- (CPPredicate)parseAnd -{ - var l = [self parseOr]; - - while ([self scanPredicateKeyword:@"AND"] || [self scanPredicateKeyword:@"&&"]) - { - var r = [self parseOr]; - - if ([r isKindOfClass:[CPCompoundPredicate class]] && [r compoundPredicateType] == CPAndPredicateType) - { - if ([l isKindOfClass:[CPCompoundPredicate class]] && [l compoundPredicateType] == CPAndPredicateType) - { - [[l subpredicates] addObjectsFromArray:[r subpredicates]]; - } - else - { - [[r subpredicates] insertObject:l atIndex:0]; - l = r; - } - } - else if ([l isKindOfClass:[CPCompoundPredicate class]] && [l compoundPredicateType] == CPAndPredicateType) - { - [[l subpredicates] addObject:r]; - } - else - { - l = [CPCompoundPredicate andPredicateWithSubpredicates:[CPArray arrayWithObjects:l, r]]; - } - } - return l; -} - -- (CPPredicate)parseNot -{ - if ([self scanString:@"(" intoString:NULL]) - { - var r = [self parsePredicate]; - - if (![self scanString:@")" intoString:NULL]) - CPRaiseParseError(self, @"predicate"); - - return r; - } - - if ([self scanPredicateKeyword:@"NOT"] || [self scanPredicateKeyword:@"!"]) - { - return [CPCompoundPredicate notPredicateWithSubpredicate:[self parseNot]]; - } - if ([self scanPredicateKeyword:@"TRUEPREDICATE"]) - { - return [CPPredicate predicateWithValue:YES]; - } - if ([self scanPredicateKeyword:@"FALSEPREDICATE"]) - { - return [CPPredicate predicateWithValue:NO]; - } - - return [self parseComparison]; -} - -- (CPPredicate)parseOr -{ - var l = [self parseNot]; - while ([self scanPredicateKeyword:@"OR"] || [self scanPredicateKeyword:@"||"]) - { - var r = [self parseNot]; - - if ([r isKindOfClass:[CPCompoundPredicate class]] && [r compoundPredicateType] == CPOrPredicateType) - { - if ([l isKindOfClass:[CPCompoundPredicate class]] && [l compoundPredicateType] == CPOrPredicateType) - { - [[l subpredicates] addObjectsFromArray:[r subpredicates]]; - } - else - { - [[r subpredicates] insertObject:l atIndex:0]; - l = r; - } - } - else if ([l isKindOfClass:[CPCompoundPredicate class]] && [l compoundPredicateType] == CPOrPredicateType) - { - [[l subpredicates] addObject:r]; - } - else - { - l = [CPCompoundPredicate orPredicateWithSubpredicates:[CPArray arrayWithObjects:l, r]]; - } - } - return l; -} - -- (CPPredicate)parseComparison -{ - var modifier = CPDirectPredicateModifier, - type = 0, - opts = 0, - left, - right, - p, - negate = NO; - - if ([self scanPredicateKeyword:@"ANY"]) - { - modifier = CPAnyPredicateModifier; - } - else if ([self scanPredicateKeyword:@"ALL"]) - { - modifier = CPAllPredicateModifier; - } - else if ([self scanPredicateKeyword:@"NONE"]) - { - modifier = CPAnyPredicateModifier; - negate = YES; - } - else if ([self scanPredicateKeyword:@"SOME"]) - { - modifier = CPAllPredicateModifier; - negate = YES; - } - - left = [self parseExpression]; - if ([self scanString:@"!=" intoString:NULL] || [self scanString:@"<>" intoString:NULL]) - { - type = CPNotEqualToPredicateOperatorType; - } - else if ([self scanString:@"<=" intoString:NULL] || [self scanString:@"=<" intoString:NULL]) - { - type = CPLessThanOrEqualToPredicateOperatorType; - } - else if ([self scanString:@">=" intoString:NULL] || [self scanString:@"=>" intoString:NULL]) - { - type = CPGreaterThanOrEqualToPredicateOperatorType; - } - else if ([self scanString:@"<" intoString:NULL]) - { - type = CPLessThanPredicateOperatorType; - } - else if ([self scanString:@">" intoString:NULL]) - { - type = CPGreaterThanPredicateOperatorType; - } - else if ([self scanString:@"==" intoString:NULL] || [self scanString:@"=" intoString:NULL]) - { - type = CPEqualToPredicateOperatorType; - } - else if ([self scanPredicateKeyword:@"MATCHES"]) - { - type = CPMatchesPredicateOperatorType; - } - else if ([self scanPredicateKeyword:@"LIKE"]) - { - type = CPLikePredicateOperatorType; - } - else if ([self scanPredicateKeyword:@"BEGINSWITH"]) - { - type = CPBeginsWithPredicateOperatorType; - } - else if ([self scanPredicateKeyword:@"ENDSWITH"]) - { - type = CPEndsWithPredicateOperatorType; - } - else if ([self scanPredicateKeyword:@"IN"]) - { - type = CPInPredicateOperatorType; - } - else if ([self scanPredicateKeyword:@"CONTAINS"]) - { - type = CPContainsPredicateOperatorType; - } - else if ([self scanPredicateKeyword:@"BETWEEN"]) - { - type = CPBetweenPredicateOperatorType; - } - else - CPRaiseParseError(self, @"comparison predicate"); - - if ([self scanString:@"[cd]" intoString:NULL]) - { - opts = CPCaseInsensitivePredicateOption | CPDiacriticInsensitivePredicateOption; - } - else if ([self scanString:@"[c]" intoString:NULL]) - { - opts = CPCaseInsensitivePredicateOption; - } - else if ([self scanString:@"[d]" intoString:NULL]) - { - opts = CPDiacriticInsensitivePredicateOption; - } - - right = [self parseExpression]; - - p = [CPComparisonPredicate predicateWithLeftExpression:left - rightExpression:right - modifier:modifier - type:type - options:opts]; - - return negate ? [CPCompoundPredicate notPredicateWithSubpredicate:p]:p; -} - -- (CPExpression)parseExpression -{ - return [self parseBinaryExpression]; -} - -- (CPExpression)parseSimpleExpression -{ - var identifier, - location, - ident, - dbl; - - if ([self scanDouble:REFERENCE(dbl)]) - return [CPExpression expressionForConstantValue:dbl]; - - // FIXME: handle integer, hex constants, 0x 0o 0b - if ([self scanString:@"-" intoString:NULL]) - return [CPExpression expressionForFunction:@"chs:" arguments:[CPArray arrayWithObject:[self parseExpression]]]; - - if ([self scanString:@"(" intoString:NULL]) - { - var arg = [self parseExpression]; - - if (![self scanString:@")" intoString:NULL]) - CPRaiseParseError(self, @"expression"); - - return arg; - } - - if ([self scanString:@"{" intoString:NULL]) - { - if ([self scanString:@"}" intoString:NULL]) - return [CPExpression expressionForConstantValue:a]; - - var a = []; - - [a addObject:[self parseExpression]]; - - while ([self scanString:@"," intoString:NULL]) - [a addObject:[self parseExpression]]; - - if (![self scanString:@"}" intoString:NULL]) - CPRaiseParseError(self, @"expression"); - - return [CPExpression expressionForAggregate:a]; - } - - if ([self scanPredicateKeyword:@"NULL"] || [self scanPredicateKeyword:@"NIL"]) - { - return [CPExpression expressionForConstantValue:[CPNull null]]; - } - if ([self scanPredicateKeyword:@"TRUE"] || [self scanPredicateKeyword:@"YES"]) - { - return [CPExpression expressionForConstantValue:[CPNumber numberWithBool:YES]]; - } - if ([self scanPredicateKeyword:@"FALSE"] || [self scanPredicateKeyword:@"NO"]) - { - return [CPExpression expressionForConstantValue:[CPNumber numberWithBool:NO]]; - } - if ([self scanPredicateKeyword:@"SELF"]) - { - return [CPExpression expressionForEvaluatedObject]; - } - - if ([self scanString:@"$" intoString:NULL]) - { - var variable = [self parseSimpleExpression]; - - if (![variable keyPath]) - CPRaiseParseError(self, @"expression"); - - return [CPExpression expressionForVariable:variable]; - } - - location = [self scanLocation]; - - if ([self scanString:@"%" intoString:NULL]) - { - if ([self isAtEnd] == NO) - { - var c = [[self string] characterAtIndex:[self scanLocation]]; - - switch (c) - { - case '%':// '%%' is treated as '%' - location = [self scanLocation]; - break; - case 'K': - [self setScanLocation:[self scanLocation] + 1]; - return [CPExpression expressionForKeyPath:[self nextArg]]; - case '@': - case 'c': - case 'C': - case 'd': - case 'D': - case 'i': - case 'o': - case 'O': - case 'u': - case 'U': - case 'x': - case 'X': - case 'e': - case 'E': - case 'f': - case 'g': - case 'G': - [self setScanLocation:[self scanLocation] + 1]; - return [CPExpression expressionForConstantValue:[self nextArg]]; - case 'h': - [self scanString:@"h" intoString:NULL]; - if ([self isAtEnd] == NO) - { - c = [[self string] characterAtIndex:[self scanLocation]]; - if (c == 'i' || c == 'u') - { - [self setScanLocation:[self scanLocation] + 1]; - return [CPExpression expressionForConstantValue:[self nextArg]]; - } - } - break; - case 'q': - [self scanString:@"q" intoString:NULL]; - if ([self isAtEnd] == NO) - { - c = [[self string] characterAtIndex:[self scanLocation]]; - if (c == 'i' || c == 'u' || c == 'x' || c == 'X') - { - [self setScanLocation:[self scanLocation] + 1]; - return [CPExpression expressionForConstantValue:[self nextArg]]; - } - } - break; - } - } - - [self setScanLocation:location]; - } - - if ([self scanString:@"\"" intoString:NULL]) - { - var skip = [self charactersToBeSkipped], - str = @""; - - [self setCharactersToBeSkipped:nil]; - [self scanUpToString:@"\"" intoString:REFERENCE(str)]; - - if ([self scanString:@"\"" intoString:NULL] == NO) - CPRaiseParseError(self, @"expression"); - - [self setCharactersToBeSkipped:skip]; - - return [CPExpression expressionForConstantValue:str]; - } - - if ([self scanString:@"'" intoString:NULL]) - { - var skip = [self charactersToBeSkipped], - str = @""; - - [self setCharactersToBeSkipped:nil]; - [self scanUpToString:@"'" intoString:REFERENCE(str)]; - - if ([self scanString:@"'" intoString:NULL] == NO) - CPRaiseParseError(self, @"expression"); - - [self setCharactersToBeSkipped:skip]; - - return [CPExpression expressionForConstantValue:str]; - } - - if ([self scanString:@"@" intoString:NULL]) - { - var e = [self parseExpression]; - - if (![e keyPath]) - CPRaiseParseError(self, @"expression"); - - return [CPExpression expressionForKeyPath:[e keyPath] + "@"]; - } - - if ([self scanString:@"SUBQUERY" intoString:NULL]) - { - if (![self scanString:@"(" intoString:NULL]) - CPRaiseParseError(self, @"expression"); - - var collection = [self parseExpression], - variableExpression, - subpredicate; - - if (![self scanString:@"," intoString:NULL]) - CPRaiseParseError(self, @"expression"); - variableExpression = [self parseExpression]; - - if (![self scanString:@"," intoString:NULL]) - CPRaiseParseError(self, @"expression"); - subpredicate = [self parsePredicate]; - - if (![self scanString:@")" intoString:NULL]) - CPRaiseParseError(self, @"expression"); - - return [[_CPSubqueryExpression alloc] initWithExpression:collection usingIteratorExpression:variableExpression predicate:subpredicate]; - } - - if ([self scanString:@"FUNCTION" intoString:NULL]) - { - if (![self scanString:@"(" intoString:NULL]) - CPRaiseParseError(self, @"expression"); - - var args = [CPArray arrayWithObject:[self parseExpression]]; - while ([self scanString:@"," intoString:NULL]) - [args addObject:[self parseExpression]]; - - if (![self scanString:@")" intoString:NULL] || [args count] < 2 || [args[1] expressionType] != CPConstantValueExpressionType) - CPRaiseParseError(self, @"expression"); - - return [CPExpression expressionForFunction:args[0] selectorName:[args[1] constantValue] arguments:args.slice(2)]; - } - - [self scanString:@"#" intoString:NULL]; - if (!identifier) - identifier = [CPCharacterSet characterSetWithCharactersInString:@"_$abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"]; - - if (![self scanCharactersFromSet:identifier intoString:REFERENCE(ident)]) - CPRaiseParseError(self, @"expression"); - - return [CPExpression expressionForKeyPath:ident]; -} - -- (CPExpression)parseFunctionalExpression -{ - var left = [self parseSimpleExpression]; - - while (YES) - { - if ([self scanString:@"." intoString:NULL]) - { - var right = [self parseSimpleExpression], - expressionType = [right expressionType]; - - if (expressionType == CPKeyPathExpressionType) - left = [[_CPKeyPathExpression alloc] initWithOperand:left andKeyPath:[right keyPath]]; - else if (expressionType == CPVariableExpressionType) - left = [CPExpression expressionForFunction:left selectorName:@"valueForKey:" arguments:[right]]; - else - CPRaiseParseError(self, @"expression"); - } - else if ([self scanString:@"[" intoString:NULL]) - { - // index expression - if ([self scanPredicateKeyword:@"FIRST"]) - { - left = [CPExpression expressionForFunction:@"first:" arguments:[CPArray arrayWithObject:left]]; - } - else if ([self scanPredicateKeyword:@"LAST"]) - { - left = [CPExpression expressionForFunction:@"last:" arguments:[CPArray arrayWithObject:left]]; - } - else if ([self scanPredicateKeyword:@"SIZE"]) - { - left = [CPExpression expressionForFunction:@"count:" arguments:[CPArray arrayWithObject:left]]; - } - else - { - var index = [self parseExpression]; - left = [CPExpression expressionForFunction:@"fromObject:index:" arguments:[CPArray arrayWithObjects:left, index]]; - } - - if (![self scanString:@"]" intoString:NULL]) - CPRaiseParseError(self, @"expression"); - } - else if ([self scanString:@":" intoString:NULL]) - { - // function - this parser allows for (max)(a, b, c) to be properly - // recognized and even (%K)(a, b, c) if %K evaluates to "max" - - if (![left keyPath]) - CPRaiseParseError(self, @"expression"); - - var selector = [left keyPath] + @":", - args = []; - - if (![self scanString:@"(" intoString:NULL]) - { - var str; - [self scanCharactersFromSet:[CPCharacterSet lowercaseLetterCharacterSet] intoString:REFERENCE(str)]; - - if (![self scanString:@":(" intoString:NULL]) - CPRaiseParseError(self, @"expression"); - - selector += str + @":"; - } - - if (![self scanString:@")" intoString:NULL]) - { - [args addObject:[self parseExpression]]; - while ([self scanString:@"," intoString:NULL]) - [args addObject:[self parseExpression]]; - - if (![self scanString:@")" intoString:NULL]) - CPRaiseParseError(self, @"expression"); - } - - left = [CPExpression expressionForFunction:selector arguments:args]; - } - else if ([self scanString:@"UNION" intoString:NULL]) - { - left = [CPExpression expressionForUnionSet:left with:[self parseExpression]]; - } - else if ([self scanString:@"INTERSECT" intoString:NULL]) - { - left = [CPExpression expressionForIntersectSet:left with:[self parseExpression]]; - } - else if ([self scanString:@"MINUS" intoString:NULL]) - { - left = [CPExpression expressionForMinusSet:left with:[self parseExpression]]; - } - else - { - // done with suffixes - return left; - } - } -} - -- (CPExpression)parsePowerExpression -{ - var left = [self parseFunctionalExpression]; - - while (YES) - { - var right; - - if ([self scanString:@"**" intoString:NULL]) - { - right = [self parseFunctionalExpression]; - left = [CPExpression expressionForFunction:@"raise:to:" arguments:[CPArray arrayWithObjects:left, right]]; - } - else - { - return left; - } - } -} - -- (CPExpression)parseMultiplicationExpression -{ - var left = [self parsePowerExpression]; - - while (YES) - { - var right; - - if ([self scanString:@"*" intoString:NULL]) - { - right = [self parsePowerExpression]; - left = [CPExpression expressionForFunction:@"multiply:by:" arguments:[CPArray arrayWithObjects:left, right]]; - } - else if ([self scanString:@"/" intoString:NULL]) - { - right = [self parsePowerExpression]; - left = [CPExpression expressionForFunction:@"divide:by:" arguments:[CPArray arrayWithObjects:left, right]]; - } - else - { - return left; - } - } -} - -- (CPExpression)parseAdditionExpression -{ - var left = [self parseMultiplicationExpression]; - - while (YES) - { - var right; - - if ([self scanString:@"+" intoString:NULL]) - { - right = [self parseMultiplicationExpression]; - left = [CPExpression expressionForFunction:@"add:to:" arguments:[CPArray arrayWithObjects:left, right]]; - } - else if ([self scanString:@"-" intoString:NULL]) - { - right = [self parseMultiplicationExpression]; - left = [CPExpression expressionForFunction:@"from:substract:" arguments:[CPArray arrayWithObjects:left, right]]; - } - else - { - return left; - } - } -} - -- (CPExpression)parseBinaryExpression -{ - var left = [self parseAdditionExpression]; - - while (YES) - { - var right; - - if ([self scanString:@":=" intoString:NULL]) // assignment - { - // check left to be a variable? - right = [self parseAdditionExpression]; - // FIXME - } - else - { - return left; - } - } -} - -@end - -var CPRaiseParseError = function CPRaiseParseError(aScanner, target) -{ - [CPException raise:CPInvalidArgumentException reason:@"unable to parse " + target + " at index " + [aScanner scanLocation]]; -}; - -//@import "CPCompoundPredicate.j" -//@import "CPComparisonPredicate.j" -//@import "CPExpression.j" +@import "_CPPredicate.j" +@import "CPCompoundPredicate.j" +@import "CPComparisonPredicate.j" +@import "CPExpression.j" diff --git a/Foundation/CPPredicate/_CPPredicate.j b/Foundation/CPPredicate/_CPPredicate.j new file mode 100644 index 000000000..2fc1392fe --- /dev/null +++ b/Foundation/CPPredicate/_CPPredicate.j @@ -0,0 +1,1001 @@ +/* + * CPPredicate.j + * + * CPPredicate parsing based on NSPredicate.m in GNUStep Base Library (http://www.gnustep.org/) + * Copyright (c) 2005 Free Software Foundation. + * + * Created by cacaodev. + * Copyright 2010. + * + * 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 "CPArray.j" +@import "CPException.j" +@import "CPNull.j" +@import "CPObject.j" +@import "CPScanner.j" +@import "CPSet.j" +@import "CPValue.j" +@import "CPCharacterSet.j" + +@class CPCompoundPredicate +@class CPComparisonPredicate +@class _CPSubqueryExpression + +@global CPAndPredicateType +@global CPDirectPredicateModifier +@global CPAnyPredicateModifier +@global CPAllPredicateModifier +@global CPOrPredicateType +@global CPEqualToPredicateOperatorType +@global CPNotEqualToPredicateOperatorType +@global CPLessThanPredicateOperatorType +@global CPGreaterThanPredicateOperatorType +@global CPLessThanOrEqualToPredicateOperatorType +@global CPGreaterThanOrEqualToPredicateOperatorType +@global CPMatchesPredicateOperatorType +@global CPLikePredicateOperatorType +@global CPBeginsWithPredicateOperatorType +@global CPEndsWithPredicateOperatorType +@global CPInPredicateOperatorType +@global CPContainsPredicateOperatorType +@global CPBetweenPredicateOperatorType +@global CPCaseInsensitivePredicateOption +@global CPDiacriticInsensitivePredicateOption + + +/*! + @ingroup foundation + @class CPPredicate + @brief The CPPredicate class is used to define logical conditions used to constrain a search either for a fetch or for in-memory filtering. + + You use predicates to represent logical conditions, used for describing objects in persistent stores + and in-memory filtering of objects. Although it is common to create predicates directly from instances + of CPComparisonPredicate, CPCompoundPredicate, and CPExpression, you often create predicates from a + format string which is parsed by the class methods on CPPredicate. Examples of predicate format strings include: + + - Simple comparisons, such as grade == "7" or firstName like "Shaffiq" + - Case/diacritic insensitive lookups, such as name contains[cd] "itroen" + - Logical operations, such as (firstName like "Mark") OR (lastName like "Adderley") + - “Between” predicates such as date between {$YESTERDAY, $TOMORROW}. + + You can create predicates for relationships, such as: + + - group.name like "work*" + - ALL children.age > 12 + - ANY children.age > 12 + + You can create predicates for operations, such as \@sum.items.price < 1000. + + You can also create predicates that include variables, so that the predicate can be pre-defined before + substituting concrete values at runtime with the \c evaluateWithObject:substitutionVariables: method. +*/ + +@implementation CPPredicate : CPObject +{ +} + +/*! + Creates and returns a new predicate formed by creating a new string with a given format and parsing the result. + @param format The format string for the new predicate. + @param … A comma-separated list of arguments to substitute into format. + @return A new predicate formed by creating a new string with format and parsing the result. +*/ ++ (CPPredicate)predicateWithFormat:(CPString)format, ... +{ + if (!format) + [CPException raise:CPInvalidArgumentException reason:_cmd + " the format can't be 'nil'"]; + + var args = Array.prototype.slice.call(arguments, 3); + return [self predicateWithFormat:arguments[2] argumentArray:args]; +} + +/*! + Creates and returns a new predicate by substituting the values in a given array into a format string and parsing the result. + @param format The format string for the new predicate. + @param arguments The arguments to substitute into predicateFormat. Values are substituted into predicateFormat in the order they appear in the array. + @return A new predicate by substituting the values in arguments into predicateFormat, and parsing the result. +*/ ++ (CPPredicate)predicateWithFormat:(CPString)format argumentArray:(CPArray)args +{ + if (!format) + [CPException raise:CPInvalidArgumentException reason:_cmd + " the format can't be 'nil'"]; + + var s = [[CPPredicateScanner alloc] initWithString:format args:args], + p = [s parse]; + + return p; +} + +/*! + Creates and returns a new predicate by substituting the values in an argument list into a format string and parsing the result. + @param format The format string for the new predicate. + @param argList The arguments to substitute into predicateFormat. Values are substituted into predicateFormat in the order they appear in the argument list. + @return A new predicate by substituting the values in argList into predicateFormat and parsing the result. +*/ ++ (CPPredicate)predicateWithFormat:(CPString)format arguments:(va_list)argList +{ + // UNIMPLEMENTED + return nil; +} + +/*! + Returns a copy of the receiver with the receiver’s variables substituted by values specified in a given substitution variables dictionary. + @param variables The substitution variables dictionary. The dictionary must contain key-value pairs for all variables in the receiver. + @return A copy of the receiver with the receiver’s variables substituted by values specified in variables. +*/ +- (CPPredicate)predicateWithSubstitutionVariables:(CPDictionary)variables +{ + // IMPLEMENTED BY SUBCLASSES +} + +/*! + Creates and returns a predicate that always evaluates to a given value. + @param value The value to which the new predicate should evaluate. + @return A predicate that always evaluates to value. +*/ ++ (CPPredicate)predicateWithValue:(BOOL)value +{ + return [[CPPredicate_BOOL alloc] initWithBool:value]; +} + +// Evaluating a Predicate +/*! + Returns a Boolean value that indicates whether a given object matches the conditions specified by the receiver. + @param object The object against which to evaluate the receiver. + @return YES if object matches the conditions specified by the receiver, otherwise NO. +*/ +- (BOOL)evaluateWithObject:(id)object +{ + // IMPLEMENTED BY SUBCLASSES +} + +/*! + Returns a Boolean value that indicates whether a given object matches the conditions specified by the receiver after substituting in the values in a given variables dictionary. + @param object The object against which to evaluate the receiver. + @param variables The substitution variables dictionary. The dictionary must contain key-value pairs for all variables in the receiver. + @return YES if object matches the conditions specified by the receiver after substituting in the values in variables for any replacement tokens, otherwise NO. +*/ +- (BOOL)evaluateWithObject:(id)object substitutionVariables:(CPDictionary)variables +{ + // IMPLEMENTED BY SUBCLASSES +} + +// Getting Format Information +/*! + Returns the receiver’s format string. + @return The receiver’s format string. +*/ +- (CPString)predicateFormat +{ + // IMPLEMENTED BY SUBCLASSES +} + +- (CPString)description +{ + return [self predicateFormat]; +} + +@end + +@implementation CPPredicate_BOOL : CPPredicate +{ + BOOL _value; +} + +- (id)initWithBool:(BOOL)value +{ + _value = value; + return self; +} + +- (BOOL)isEqual:(id)anObject +{ + if (self === anObject) + return YES; + + if (self.isa !== anObject.isa || _value !== [anObject evaluateObject:nil]) + return NO; + + return YES; +} + +- (BOOL)evaluateObject:(id)object +{ + return _value; +} + +- (CPString)predicateFormat +{ + return (_value) ? @"TRUEPREDICATE" : @"FALSEPREDICATE"; +} + +@end + + +@implementation CPArray (CPPredicate) + +- (CPArray)filteredArrayUsingPredicate:(CPPredicate)predicate +{ + var count = [self count], + result = [CPArray array], + i = 0; + + for (; i < count; i++) + { + var object = [self objectAtIndex:i]; + if ([predicate evaluateWithObject:object]) + result.push(object); + } + + return result; +} + +- (void)filterUsingPredicate:(CPPredicate)predicate +{ + var count = [self count]; + + while (count--) + { + if (![predicate evaluateWithObject:[self objectAtIndex:count]]) + self.splice(count, 1); + } +} + +@end + +@implementation CPSet (CPPredicate) + +- (CPSet)filteredSetUsingPredicate:(CPPredicate)predicate +{ + var count = [self count], + result = [CPSet set], + i = 0; + + for (; i < count; i++) + { + var object = [self objectAtIndex:i]; + + if ([predicate evaluateWithObject:object]) + [result addObject:object]; + } + + return result; +} + +- (void)filterUsingPredicate:(CPPredicate)predicate +{ + var count = [self count]; + + while (--count >= 0) + { + var object = [self objectAtIndex:count]; + + if (![predicate evaluateWithObject:object]) + [self removeObjectAtIndex:count]; + } +} + +@end + +#define REFERENCE(variable) \ +function(newValue)\ +{\ + var oldValue = variable;\ + if (typeof newValue != 'undefined')\ + variable = newValue;\ + return oldValue;\ +} + +@implementation CPPredicateScanner : CPScanner +{ + CPEnumerator _args; + unsigned _retrieved; +} + +- (id)initWithString:(CPString)format args:(CPArray)args +{ + self = [super initWithString:format] + + if (self) + { + _args = [args objectEnumerator]; + } + return self; +} + +- (id)nextArg +{ + return [_args nextObject]; +} + +- (BOOL)scanPredicateKeyword:(CPString)key +{ + var loc = [self scanLocation]; + + [self setCaseSensitive:NO]; + if (![self scanString:key intoString:NULL]) + return NO; + + if ([self isAtEnd]) + return YES; + + var c = [[self string] characterAtIndex:[self scanLocation]]; + if (![[CPCharacterSet alphanumericCharacterSet] characterIsMember:c]) + return YES; + + [self setScanLocation:loc]; + + return NO; +} + +- (CPPredicate)parse +{ + var r = nil; + + try + { + [self setCharactersToBeSkipped:[CPCharacterSet whitespaceCharacterSet]]; + r = [self parsePredicate]; + } + catch(error) + { + CPLogConsole(@"Unable to parse predicate '" + [self string] + "' with " + error); + } + finally + { + if (![self isAtEnd]) + { + var pstr = [self string], + loc = [self scanLocation]; + CPLogConsole(@"Format string contains extra characters: '" + [pstr substringToIndex:loc] + "**" + [pstr substringFromIndex:loc] + "**'"); + } + } + + return r; +} + +- (CPPredicate)parsePredicate +{ + return [self parseAnd]; +} + +- (CPPredicate)parseAnd +{ + var l = [self parseOr]; + + while ([self scanPredicateKeyword:@"AND"] || [self scanPredicateKeyword:@"&&"]) + { + var r = [self parseOr]; + + if ([r isKindOfClass:[CPCompoundPredicate class]] && [r compoundPredicateType] == CPAndPredicateType) + { + if ([l isKindOfClass:[CPCompoundPredicate class]] && [l compoundPredicateType] == CPAndPredicateType) + { + [[l subpredicates] addObjectsFromArray:[r subpredicates]]; + } + else + { + [[r subpredicates] insertObject:l atIndex:0]; + l = r; + } + } + else if ([l isKindOfClass:[CPCompoundPredicate class]] && [l compoundPredicateType] == CPAndPredicateType) + { + [[l subpredicates] addObject:r]; + } + else + { + l = [CPCompoundPredicate andPredicateWithSubpredicates:[CPArray arrayWithObjects:l, r]]; + } + } + return l; +} + +- (CPPredicate)parseNot +{ + if ([self scanString:@"(" intoString:NULL]) + { + var r = [self parsePredicate]; + + if (![self scanString:@")" intoString:NULL]) + CPRaiseParseError(self, @"predicate"); + + return r; + } + + if ([self scanPredicateKeyword:@"NOT"] || [self scanPredicateKeyword:@"!"]) + { + return [CPCompoundPredicate notPredicateWithSubpredicate:[self parseNot]]; + } + if ([self scanPredicateKeyword:@"TRUEPREDICATE"]) + { + return [CPPredicate predicateWithValue:YES]; + } + if ([self scanPredicateKeyword:@"FALSEPREDICATE"]) + { + return [CPPredicate predicateWithValue:NO]; + } + + return [self parseComparison]; +} + +- (CPPredicate)parseOr +{ + var l = [self parseNot]; + while ([self scanPredicateKeyword:@"OR"] || [self scanPredicateKeyword:@"||"]) + { + var r = [self parseNot]; + + if ([r isKindOfClass:[CPCompoundPredicate class]] && [r compoundPredicateType] == CPOrPredicateType) + { + if ([l isKindOfClass:[CPCompoundPredicate class]] && [l compoundPredicateType] == CPOrPredicateType) + { + [[l subpredicates] addObjectsFromArray:[r subpredicates]]; + } + else + { + [[r subpredicates] insertObject:l atIndex:0]; + l = r; + } + } + else if ([l isKindOfClass:[CPCompoundPredicate class]] && [l compoundPredicateType] == CPOrPredicateType) + { + [[l subpredicates] addObject:r]; + } + else + { + l = [CPCompoundPredicate orPredicateWithSubpredicates:[CPArray arrayWithObjects:l, r]]; + } + } + return l; +} + +- (CPPredicate)parseComparison +{ + var modifier = CPDirectPredicateModifier, + type = 0, + opts = 0, + left, + right, + p, + negate = NO; + + if ([self scanPredicateKeyword:@"ANY"]) + { + modifier = CPAnyPredicateModifier; + } + else if ([self scanPredicateKeyword:@"ALL"]) + { + modifier = CPAllPredicateModifier; + } + else if ([self scanPredicateKeyword:@"NONE"]) + { + modifier = CPAnyPredicateModifier; + negate = YES; + } + else if ([self scanPredicateKeyword:@"SOME"]) + { + modifier = CPAllPredicateModifier; + negate = YES; + } + + left = [self parseExpression]; + if ([self scanString:@"!=" intoString:NULL] || [self scanString:@"<>" intoString:NULL]) + { + type = CPNotEqualToPredicateOperatorType; + } + else if ([self scanString:@"<=" intoString:NULL] || [self scanString:@"=<" intoString:NULL]) + { + type = CPLessThanOrEqualToPredicateOperatorType; + } + else if ([self scanString:@">=" intoString:NULL] || [self scanString:@"=>" intoString:NULL]) + { + type = CPGreaterThanOrEqualToPredicateOperatorType; + } + else if ([self scanString:@"<" intoString:NULL]) + { + type = CPLessThanPredicateOperatorType; + } + else if ([self scanString:@">" intoString:NULL]) + { + type = CPGreaterThanPredicateOperatorType; + } + else if ([self scanString:@"==" intoString:NULL] || [self scanString:@"=" intoString:NULL]) + { + type = CPEqualToPredicateOperatorType; + } + else if ([self scanPredicateKeyword:@"MATCHES"]) + { + type = CPMatchesPredicateOperatorType; + } + else if ([self scanPredicateKeyword:@"LIKE"]) + { + type = CPLikePredicateOperatorType; + } + else if ([self scanPredicateKeyword:@"BEGINSWITH"]) + { + type = CPBeginsWithPredicateOperatorType; + } + else if ([self scanPredicateKeyword:@"ENDSWITH"]) + { + type = CPEndsWithPredicateOperatorType; + } + else if ([self scanPredicateKeyword:@"IN"]) + { + type = CPInPredicateOperatorType; + } + else if ([self scanPredicateKeyword:@"CONTAINS"]) + { + type = CPContainsPredicateOperatorType; + } + else if ([self scanPredicateKeyword:@"BETWEEN"]) + { + type = CPBetweenPredicateOperatorType; + } + else + CPRaiseParseError(self, @"comparison predicate"); + + if ([self scanString:@"[cd]" intoString:NULL]) + { + opts = CPCaseInsensitivePredicateOption | CPDiacriticInsensitivePredicateOption; + } + else if ([self scanString:@"[c]" intoString:NULL]) + { + opts = CPCaseInsensitivePredicateOption; + } + else if ([self scanString:@"[d]" intoString:NULL]) + { + opts = CPDiacriticInsensitivePredicateOption; + } + + right = [self parseExpression]; + + p = [CPComparisonPredicate predicateWithLeftExpression:left + rightExpression:right + modifier:modifier + type:type + options:opts]; + + return negate ? [CPCompoundPredicate notPredicateWithSubpredicate:p]:p; +} + +- (CPExpression)parseExpression +{ + return [self parseBinaryExpression]; +} + +- (CPExpression)parseSimpleExpression +{ + var identifier, + location, + ident, + dbl; + + if ([self scanDouble:REFERENCE(dbl)]) + return [CPExpression expressionForConstantValue:dbl]; + + // FIXME: handle integer, hex constants, 0x 0o 0b + if ([self scanString:@"-" intoString:NULL]) + return [CPExpression expressionForFunction:@"chs:" arguments:[CPArray arrayWithObject:[self parseExpression]]]; + + if ([self scanString:@"(" intoString:NULL]) + { + var arg = [self parseExpression]; + + if (![self scanString:@")" intoString:NULL]) + CPRaiseParseError(self, @"expression"); + + return arg; + } + + if ([self scanString:@"{" intoString:NULL]) + { + var a = []; + + if ([self scanString:@"}" intoString:NULL]) + return [CPExpression expressionForConstantValue:a]; + + [a addObject:[self parseExpression]]; + + while ([self scanString:@"," intoString:NULL]) + [a addObject:[self parseExpression]]; + + if (![self scanString:@"}" intoString:NULL]) + CPRaiseParseError(self, @"expression"); + + return [CPExpression expressionForAggregate:a]; + } + + if ([self scanPredicateKeyword:@"NULL"] || [self scanPredicateKeyword:@"NIL"]) + { + return [CPExpression expressionForConstantValue:[CPNull null]]; + } + if ([self scanPredicateKeyword:@"TRUE"] || [self scanPredicateKeyword:@"YES"]) + { + return [CPExpression expressionForConstantValue:[CPNumber numberWithBool:YES]]; + } + if ([self scanPredicateKeyword:@"FALSE"] || [self scanPredicateKeyword:@"NO"]) + { + return [CPExpression expressionForConstantValue:[CPNumber numberWithBool:NO]]; + } + if ([self scanPredicateKeyword:@"SELF"]) + { + return [CPExpression expressionForEvaluatedObject]; + } + + if ([self scanString:@"$" intoString:NULL]) + { + var variable = [self parseSimpleExpression]; + + if (![variable keyPath]) + CPRaiseParseError(self, @"expression"); + + return [CPExpression expressionForVariable:variable]; + } + + location = [self scanLocation]; + + if ([self scanString:@"%" intoString:NULL]) + { + if ([self isAtEnd] == NO) + { + var c = [[self string] characterAtIndex:[self scanLocation]]; + + switch (c) + { + case '%':// '%%' is treated as '%' + location = [self scanLocation]; + break; + case 'K': + [self setScanLocation:[self scanLocation] + 1]; + return [CPExpression expressionForKeyPath:[self nextArg]]; + case '@': + case 'c': + case 'C': + case 'd': + case 'D': + case 'i': + case 'o': + case 'O': + case 'u': + case 'U': + case 'x': + case 'X': + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + [self setScanLocation:[self scanLocation] + 1]; + return [CPExpression expressionForConstantValue:[self nextArg]]; + case 'h': + [self scanString:@"h" intoString:NULL]; + if ([self isAtEnd] == NO) + { + c = [[self string] characterAtIndex:[self scanLocation]]; + if (c == 'i' || c == 'u') + { + [self setScanLocation:[self scanLocation] + 1]; + return [CPExpression expressionForConstantValue:[self nextArg]]; + } + } + break; + case 'q': + [self scanString:@"q" intoString:NULL]; + if ([self isAtEnd] == NO) + { + c = [[self string] characterAtIndex:[self scanLocation]]; + if (c == 'i' || c == 'u' || c == 'x' || c == 'X') + { + [self setScanLocation:[self scanLocation] + 1]; + return [CPExpression expressionForConstantValue:[self nextArg]]; + } + } + break; + } + } + + [self setScanLocation:location]; + } + + if ([self scanString:@"\"" intoString:NULL]) + { + var skip = [self charactersToBeSkipped], + str = @""; + + [self setCharactersToBeSkipped:nil]; + [self scanUpToString:@"\"" intoString:REFERENCE(str)]; + + if ([self scanString:@"\"" intoString:NULL] == NO) + CPRaiseParseError(self, @"expression"); + + [self setCharactersToBeSkipped:skip]; + + return [CPExpression expressionForConstantValue:str]; + } + + if ([self scanString:@"'" intoString:NULL]) + { + var skip = [self charactersToBeSkipped], + str = @""; + + [self setCharactersToBeSkipped:nil]; + [self scanUpToString:@"'" intoString:REFERENCE(str)]; + + if ([self scanString:@"'" intoString:NULL] == NO) + CPRaiseParseError(self, @"expression"); + + [self setCharactersToBeSkipped:skip]; + + return [CPExpression expressionForConstantValue:str]; + } + + if ([self scanString:@"@" intoString:NULL]) + { + var e = [self parseExpression]; + + if (![e keyPath]) + CPRaiseParseError(self, @"expression"); + + return [CPExpression expressionForKeyPath:[e keyPath] + "@"]; + } + + if ([self scanString:@"SUBQUERY" intoString:NULL]) + { + if (![self scanString:@"(" intoString:NULL]) + CPRaiseParseError(self, @"expression"); + + var collection = [self parseExpression], + variableExpression, + subpredicate; + + if (![self scanString:@"," intoString:NULL]) + CPRaiseParseError(self, @"expression"); + variableExpression = [self parseExpression]; + + if (![self scanString:@"," intoString:NULL]) + CPRaiseParseError(self, @"expression"); + subpredicate = [self parsePredicate]; + + if (![self scanString:@")" intoString:NULL]) + CPRaiseParseError(self, @"expression"); + + return [[_CPSubqueryExpression alloc] initWithExpression:collection usingIteratorExpression:variableExpression predicate:subpredicate]; + } + + if ([self scanString:@"FUNCTION" intoString:NULL]) + { + if (![self scanString:@"(" intoString:NULL]) + CPRaiseParseError(self, @"expression"); + + var args = [CPArray arrayWithObject:[self parseExpression]]; + while ([self scanString:@"," intoString:NULL]) + [args addObject:[self parseExpression]]; + + if (![self scanString:@")" intoString:NULL] || [args count] < 2 || [args[1] expressionType] != CPConstantValueExpressionType) + CPRaiseParseError(self, @"expression"); + + return [CPExpression expressionForFunction:args[0] selectorName:[args[1] constantValue] arguments:args.slice(2)]; + } + + [self scanString:@"#" intoString:NULL]; + if (!identifier) + identifier = [CPCharacterSet characterSetWithCharactersInString:@"_$abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"]; + + if (![self scanCharactersFromSet:identifier intoString:REFERENCE(ident)]) + CPRaiseParseError(self, @"expression"); + + return [CPExpression expressionForKeyPath:ident]; +} + +- (CPExpression)parseFunctionalExpression +{ + var left = [self parseSimpleExpression]; + + while (YES) + { + if ([self scanString:@"." intoString:NULL]) + { + var right = [self parseSimpleExpression], + expressionType = [right expressionType]; + + if (expressionType == CPKeyPathExpressionType) + left = [[_CPKeyPathExpression alloc] initWithOperand:left andKeyPath:[right keyPath]]; + else if (expressionType == CPVariableExpressionType) + left = [CPExpression expressionForFunction:left selectorName:@"valueForKey:" arguments:[right]]; + else + CPRaiseParseError(self, @"expression"); + } + else if ([self scanString:@"[" intoString:NULL]) + { + // index expression + if ([self scanPredicateKeyword:@"FIRST"]) + { + left = [CPExpression expressionForFunction:@"first:" arguments:[CPArray arrayWithObject:left]]; + } + else if ([self scanPredicateKeyword:@"LAST"]) + { + left = [CPExpression expressionForFunction:@"last:" arguments:[CPArray arrayWithObject:left]]; + } + else if ([self scanPredicateKeyword:@"SIZE"]) + { + left = [CPExpression expressionForFunction:@"count:" arguments:[CPArray arrayWithObject:left]]; + } + else + { + var index = [self parseExpression]; + left = [CPExpression expressionForFunction:@"fromObject:index:" arguments:[CPArray arrayWithObjects:left, index]]; + } + + if (![self scanString:@"]" intoString:NULL]) + CPRaiseParseError(self, @"expression"); + } + else if ([self scanString:@":" intoString:NULL]) + { + // function - this parser allows for (max)(a, b, c) to be properly + // recognized and even (%K)(a, b, c) if %K evaluates to "max" + + if (![left keyPath]) + CPRaiseParseError(self, @"expression"); + + var selector = [left keyPath] + @":", + args = []; + + if (![self scanString:@"(" intoString:NULL]) + { + var str; + [self scanCharactersFromSet:[CPCharacterSet lowercaseLetterCharacterSet] intoString:REFERENCE(str)]; + + if (![self scanString:@":(" intoString:NULL]) + CPRaiseParseError(self, @"expression"); + + selector += str + @":"; + } + + if (![self scanString:@")" intoString:NULL]) + { + [args addObject:[self parseExpression]]; + while ([self scanString:@"," intoString:NULL]) + [args addObject:[self parseExpression]]; + + if (![self scanString:@")" intoString:NULL]) + CPRaiseParseError(self, @"expression"); + } + + left = [CPExpression expressionForFunction:selector arguments:args]; + } + else if ([self scanString:@"UNION" intoString:NULL]) + { + left = [CPExpression expressionForUnionSet:left with:[self parseExpression]]; + } + else if ([self scanString:@"INTERSECT" intoString:NULL]) + { + left = [CPExpression expressionForIntersectSet:left with:[self parseExpression]]; + } + else if ([self scanString:@"MINUS" intoString:NULL]) + { + left = [CPExpression expressionForMinusSet:left with:[self parseExpression]]; + } + else + { + // done with suffixes + return left; + } + } +} + +- (CPExpression)parsePowerExpression +{ + var left = [self parseFunctionalExpression]; + + while (YES) + { + var right; + + if ([self scanString:@"**" intoString:NULL]) + { + right = [self parseFunctionalExpression]; + left = [CPExpression expressionForFunction:@"raise:to:" arguments:[CPArray arrayWithObjects:left, right]]; + } + else + { + return left; + } + } +} + +- (CPExpression)parseMultiplicationExpression +{ + var left = [self parsePowerExpression]; + + while (YES) + { + var right; + + if ([self scanString:@"*" intoString:NULL]) + { + right = [self parsePowerExpression]; + left = [CPExpression expressionForFunction:@"multiply:by:" arguments:[CPArray arrayWithObjects:left, right]]; + } + else if ([self scanString:@"/" intoString:NULL]) + { + right = [self parsePowerExpression]; + left = [CPExpression expressionForFunction:@"divide:by:" arguments:[CPArray arrayWithObjects:left, right]]; + } + else + { + return left; + } + } +} + +- (CPExpression)parseAdditionExpression +{ + var left = [self parseMultiplicationExpression]; + + while (YES) + { + var right; + + if ([self scanString:@"+" intoString:NULL]) + { + right = [self parseMultiplicationExpression]; + left = [CPExpression expressionForFunction:@"add:to:" arguments:[CPArray arrayWithObjects:left, right]]; + } + else if ([self scanString:@"-" intoString:NULL]) + { + right = [self parseMultiplicationExpression]; + left = [CPExpression expressionForFunction:@"from:substract:" arguments:[CPArray arrayWithObjects:left, right]]; + } + else + { + return left; + } + } +} + +- (CPExpression)parseBinaryExpression +{ + var left = [self parseAdditionExpression]; + + while (YES) + { + var right; + + if ([self scanString:@":=" intoString:NULL]) // assignment + { + // check left to be a variable? + right = [self parseAdditionExpression]; + // FIXME + } + else + { + return left; + } + } +} + +@end + +var CPRaiseParseError = function CPRaiseParseError(aScanner, target) +{ + [CPException raise:CPInvalidArgumentException reason:@"unable to parse " + target + " at index " + [aScanner scanLocation]]; +}; + +//@import "CPCompoundPredicate.j" +//@import "CPComparisonPredicate.j" +//@import "CPExpression.j" diff --git a/Foundation/CPProxy.j b/Foundation/CPProxy.j index 98e0aa50f..ceeac578d 100644 --- a/Foundation/CPProxy.j +++ b/Foundation/CPProxy.j @@ -86,7 +86,7 @@ - (BOOL)isEqual:(id)anObject { - return self === object; + return self === anObject; } - (id)self diff --git a/Foundation/CPSet/_CPSet.j b/Foundation/CPSet/_CPSet.j index 078e29c34..f80124c31 100644 --- a/Foundation/CPSet/_CPSet.j +++ b/Foundation/CPSet/_CPSet.j @@ -29,6 +29,8 @@ @import "CPNumber.j" @import "CPObject.j" +@class _CPConcreteMutableSet + /*! @class CPMutableSet @ingroup Foundation diff --git a/Foundation/CPSortDescriptor.j b/Foundation/CPSortDescriptor.j index ec093160a..3a61d3ca2 100755 --- a/Foundation/CPSortDescriptor.j +++ b/Foundation/CPSortDescriptor.j @@ -24,6 +24,8 @@ @import "CPObjJRuntime.j" @import "CPString.j" +@class CPString + /*! @class CPSortDescriptor @ingroup foundation diff --git a/Foundation/CPString.j b/Foundation/CPString.j index 8ab93f840..7983111dc 100644 --- a/Foundation/CPString.j +++ b/Foundation/CPString.j @@ -28,6 +28,11 @@ @import "CPURL.j" @import "CPValue.j" +@class CPException + +@global CPInvalidArgumentException +@global CPRangeException + #define _CPMaxRange(aRange) ((aRange).location + (aRange).length) /*! @@ -250,7 +255,7 @@ var CPStringUIDs = new CFMutableDictionary(), return self; if (aLength < self.length) - return substr(0, aLength); + return self.substr(0, aLength); var string = self, substring = aString.substring(anIndex), diff --git a/Foundation/CPUndoManager.j b/Foundation/CPUndoManager.j index 42c24163b..25006a4af 100644 --- a/Foundation/CPUndoManager.j +++ b/Foundation/CPUndoManager.j @@ -858,7 +858,7 @@ var CPUndoManagerRedoStackKey = @"CPUndoManagerRedoStackKey", _undoStack = [aCoder decodeObjectForKey:CPUndoManagerUndoStackKey]; _levelsOfUndo = [aCoder decodeObjectForKey:CPUndoManagerLevelsOfUndoKey]; - _actionName = [aCoder decodeObjectForKey:CPUndoManagerActionNameKey]; +// _actionName = [aCoder decodeObjectForKey:CPUndoManagerActionNameKey]; _currentGrouping = [aCoder decodeObjectForKey:CPUndoManagerCurrentGroupingKey]; _state = CPUndoManagerNormal; @@ -876,7 +876,7 @@ var CPUndoManagerRedoStackKey = @"CPUndoManagerRedoStackKey", [aCoder encodeObject:_undoStack forKey:CPUndoManagerUndoStackKey]; [aCoder encodeInt:_levelsOfUndo forKey:CPUndoManagerLevelsOfUndoKey]; - [aCoder encodeObject:_actionName forKey:CPUndoManagerActionNameKey]; +// [aCoder encodeObject:_actionName forKey:CPUndoManagerActionNameKey]; [aCoder encodeObject:_currentGrouping forKey:CPUndoManagerCurrentGroupingKey]; diff --git a/Foundation/CPUserDefaults.j b/Foundation/CPUserDefaults.j index 88685aa4a..4805aca51 100644 --- a/Foundation/CPUserDefaults.j +++ b/Foundation/CPUserDefaults.j @@ -34,6 +34,9 @@ @import "CPURLConnection.j" @import "CPURLRequest.j" +@class CPCookie + +@global CPApp CPArgumentDomain = @"CPArgumentDomain"; CPApplicationDomain = [[[CPBundle mainBundle] infoDictionary] objectForKey:@"CPBundleIdentifier"] || @"CPApplicationDomain";