From a97bb72800a90c65fe25ab1e20b55a9a9f0839e8 Mon Sep 17 00:00:00 2001 From: Francisco Ryan Tolmasky I Date: Thu, 4 Sep 2008 03:52:20 -0700 Subject: [PATCH] Initial commit. Reviewed by francisco, ross and tom. --- AppKit/AppKit.j | 60 + AppKit/AppKit.steam | 46 + AppKit/CPAnimation.j | 191 ++ AppKit/CPApplication.j | 552 ++++ AppKit/CPButton.j | 604 ++++ AppKit/CPClipView.j | 130 + AppKit/CPCollectionView.j | 546 ++++ AppKit/CPColor.j | 394 +++ AppKit/CPColorPanel.j | 614 ++++ AppKit/CPColorPicker.j | 336 ++ AppKit/CPColorWell.j | 198 ++ AppKit/CPCompatibility.j | 162 + AppKit/CPControl.j | 391 +++ AppKit/CPCookie.j | 89 + AppKit/CPDocument.j | 514 +++ AppKit/CPDocumentController.j | 184 ++ AppKit/CPDragServer.j | 263 ++ AppKit/CPEvent.j | 326 ++ AppKit/CPFlashMovie.j | 46 + AppKit/CPFlashView.j | 110 + AppKit/CPFont.j | 112 + AppKit/CPFontManager.j | 158 + AppKit/CPGeometry.j | 264 ++ AppKit/CPGraphicsContext.j | 60 + AppKit/CPImage.j | 323 ++ AppKit/CPImageView.j | 307 ++ AppKit/CPKulerColorPicker.j | 367 +++ AppKit/CPMenu.j | 1513 +++++++++ AppKit/CPMenuItem.j | 897 ++++++ AppKit/CPOutlineView.j | 79 + AppKit/CPPanel.j | 70 + AppKit/CPPasteboard.j | 226 ++ AppKit/CPPopUpButton.j | 577 ++++ AppKit/CPProgressIndicator.j | 375 +++ AppKit/CPResponder.j | 225 ++ AppKit/CPScrollView.j | 467 +++ AppKit/CPScroller.j | 621 ++++ AppKit/CPSegmentedControl.j | 542 ++++ AppKit/CPShadow.j | 75 + AppKit/CPShadowView.j | 175 + AppKit/CPSlider.j | 378 +++ AppKit/CPSliderColorPicker.j | 404 +++ AppKit/CPStringDrawing.j | 67 + AppKit/CPTabView.j | 627 ++++ AppKit/CPTabViewItem.j | 113 + AppKit/CPTableColumn.j | 171 + AppKit/CPTableView.j | 339 ++ AppKit/CPTextField.j | 419 +++ AppKit/CPToolbar.j | 585 ++++ AppKit/CPToolbarItem.j | 300 ++ AppKit/CPView.j | 1380 ++++++++ AppKit/CPWindow.j | 1259 ++++++++ AppKit/CPWindowController.j | 215 ++ AppKit/Cib/CPCib.j | 128 + AppKit/Cib/CPCustomView.j | 83 + AppKit/Cib/_CPCibLoading.j | 69 + AppKit/Cib/_CPCibObjectData.j | 181 ++ AppKit/CoreAnimation/CAAnimation.j | 193 ++ AppKit/CoreAnimation/CABackingStore.j | 72 + AppKit/CoreAnimation/CAFlashLayer.j | 50 + AppKit/CoreAnimation/CALayer.j | 980 ++++++ AppKit/CoreAnimation/CAMediaTimingFunction.j | 102 + AppKit/CoreGraphics/CGAffineTransform.h | 62 + AppKit/CoreGraphics/CGAffineTransform.j | 112 + AppKit/CoreGraphics/CGColor.j | 188 ++ AppKit/CoreGraphics/CGColorSpace.j | 212 ++ AppKit/CoreGraphics/CGContext.j | 438 +++ AppKit/CoreGraphics/CGContextCanvas.j | 433 +++ AppKit/CoreGraphics/CGContextVML.j | 261 ++ AppKit/CoreGraphics/CGGeometry.h | 64 + AppKit/CoreGraphics/CGGeometry.j | 173 + AppKit/CoreGraphics/CGGradient.j | 57 + AppKit/CoreGraphics/CGPath.j | 285 ++ AppKit/Info.plist | 14 + AppKit/Platform/DOM/CPDOMDisplayServer.h | 88 + AppKit/Platform/DOM/CPDOMDisplayServer.j | 129 + AppKit/Platform/DOM/CPDOMWindowBridge.j | 836 +++++ AppKit/Platform/DOM/CPDOMWindowLayer.j | 119 + AppKit/Platform/Platform.h | 25 + AppKit/Resources/CPApplication/New.png | Bin 0 -> 3240 bytes .../CPApplication/NewHighlighted.png | Bin 0 -> 3223 bytes AppKit/Resources/CPApplication/Open.png | Bin 0 -> 3307 bytes .../CPApplication/OpenHighlighted.png | Bin 0 -> 3259 bytes AppKit/Resources/CPApplication/Save.png | Bin 0 -> 437 bytes .../CPApplication/SaveHighlighted.png | Bin 0 -> 471 bytes .../CPButton/CPButtonHUDRegular0.png | Bin 0 -> 3309 bytes .../CPButton/CPButtonHUDRegular1.png | Bin 0 -> 2844 bytes .../CPButton/CPButtonHUDRegular2.png | Bin 0 -> 3313 bytes .../CPButtonHUDRegularHighlighted0.png | Bin 0 -> 3300 bytes .../CPButtonHUDRegularHighlighted1.png | Bin 0 -> 2838 bytes .../CPButtonHUDRegularHighlighted2.png | Bin 0 -> 3307 bytes .../CPButton/CPButtonRoundRectRegular0.png | Bin 0 -> 393 bytes .../CPButton/CPButtonRoundRectRegular1.png | Bin 0 -> 141 bytes .../CPButton/CPButtonRoundRectRegular2.png | Bin 0 -> 409 bytes .../CPButtonRoundRectRegularHighlighted0.png | Bin 0 -> 378 bytes .../CPButtonRoundRectRegularHighlighted1.png | Bin 0 -> 133 bytes .../CPButtonRoundRectRegularHighlighted2.png | Bin 0 -> 385 bytes .../CPButtonTexturedRoundedRegular0.png | Bin 0 -> 230 bytes .../CPButtonTexturedRoundedRegular1.png | Bin 0 -> 143 bytes .../CPButtonTexturedRoundedRegular2.png | Bin 0 -> 232 bytes ...ttonTexturedRoundedRegularHighlighted0.png | Bin 0 -> 3001 bytes ...ttonTexturedRoundedRegularHighlighted1.png | Bin 0 -> 2841 bytes ...ttonTexturedRoundedRegularHighlighted2.png | Bin 0 -> 3027 bytes .../CPImageViewBottomLeftShadow.png | Bin 0 -> 2893 bytes .../CPImageViewBottomRightShadow.png | Bin 0 -> 2895 bytes .../CPImageView/CPImageViewBottomShadow.png | Bin 0 -> 2758 bytes .../CPImageView/CPImageViewLeftShadow.png | Bin 0 -> 2800 bytes .../CPImageView/CPImageViewRightShadow.png | Bin 0 -> 2746 bytes .../CPImageView/CPImageViewTopLeftShadow.png | Bin 0 -> 2867 bytes .../CPImageView/CPImageViewTopRightShadow.png | Bin 0 -> 2878 bytes .../CPImageView/CPImageViewTopShadow.png | Bin 0 -> 2802 bytes .../CPMenuItem/CPMenuItemOnState.png | Bin 0 -> 2877 bytes .../CPMenuItemOnStateHighlighted.png | Bin 0 -> 2875 bytes .../CPProgressIndicatorBarBarRegular.png | Bin 0 -> 2818 bytes .../CPProgressIndicatorBarHUDBarSmall.png | Bin 0 -> 2816 bytes ...rogressIndicatorBezelBorderBarRegular0.png | Bin 0 -> 2840 bytes ...rogressIndicatorBezelBorderBarRegular1.png | Bin 0 -> 2811 bytes ...rogressIndicatorBezelBorderBarRegular2.png | Bin 0 -> 2834 bytes ...ogressIndicatorBezelBorderHUDBarSmall0.png | Bin 0 -> 2838 bytes ...ogressIndicatorBezelBorderHUDBarSmall1.png | Bin 0 -> 2815 bytes ...ogressIndicatorBezelBorderHUDBarSmall2.png | Bin 0 -> 2833 bytes ...PProgressIndicatorSpinningStyleRegular.gif | Bin 0 -> 4481 bytes ...crollerDecrementArrowHorizontalRegular.png | Bin 0 -> 3200 bytes ...ementArrowHorizontalRegularHighlighted.png | Bin 0 -> 3232 bytes ...PScrollerDecrementArrowVerticalRegular.png | Bin 0 -> 472 bytes ...crementArrowVerticalRegularHighlighted.png | Bin 0 -> 498 bytes .../CPScrollerDecrementArrowVerticalSmall.png | Bin 0 -> 3020 bytes ...DecrementArrowVerticalSmallHighlighted.png | Bin 0 -> 3038 bytes ...crollerIncrementArrowHorizontalRegular.png | Bin 0 -> 3196 bytes ...ementArrowHorizontalRegularHighlighted.png | Bin 0 -> 3212 bytes ...PScrollerIncrementArrowVerticalRegular.png | Bin 0 -> 458 bytes ...crementArrowVerticalRegularHighlighted.png | Bin 0 -> 472 bytes .../CPScrollerIncrementArrowVerticalSmall.png | Bin 0 -> 3024 bytes ...IncrementArrowVerticalSmallHighlighted.png | Bin 0 -> 3044 bytes .../CPScrollerKnobHorizontalRegular0.png | Bin 0 -> 3032 bytes .../CPScrollerKnobHorizontalRegular1.png | Bin 0 -> 2809 bytes .../CPScrollerKnobHorizontalRegular2.png | Bin 0 -> 3031 bytes .../CPScrollerKnobSlotHorizontalRegular.png | Bin 0 -> 2808 bytes .../CPScrollerKnobSlotVerticalRegular.png | Bin 0 -> 2822 bytes .../CPScrollerKnobSlotVerticalSmall.png | Bin 0 -> 2821 bytes .../CPScrollerKnobVerticalRegular0.png | Bin 0 -> 3020 bytes .../CPScrollerKnobVerticalRegular1.png | Bin 0 -> 2826 bytes .../CPScrollerKnobVerticalRegular2.png | Bin 0 -> 3004 bytes .../CPScrollerKnobVerticalSmall0.png | Bin 0 -> 2938 bytes .../CPScrollerKnobVerticalSmall1.png | Bin 0 -> 2822 bytes .../CPScrollerKnobVerticalSmall2.png | Bin 0 -> 2926 bytes .../CPShadowView/CPShadowViewHeavyBottom.png | Bin 0 -> 2755 bytes .../CPShadowViewHeavyBottomLeft.png | Bin 0 -> 2951 bytes .../CPShadowViewHeavyBottomRight.png | Bin 0 -> 2973 bytes .../CPShadowView/CPShadowViewHeavyLeft.png | Bin 0 -> 2819 bytes .../CPShadowView/CPShadowViewHeavyRight.png | Bin 0 -> 2821 bytes .../CPShadowView/CPShadowViewHeavyTop.png | Bin 0 -> 2818 bytes .../CPShadowView/CPShadowViewHeavyTopLeft.png | Bin 0 -> 2940 bytes .../CPShadowViewHeavyTopRight.png | Bin 0 -> 2955 bytes .../CPShadowView/CPShadowViewLightBottom.png | Bin 0 -> 2758 bytes .../CPShadowViewLightBottomLeft.png | Bin 0 -> 2893 bytes .../CPShadowViewLightBottomRight.png | Bin 0 -> 2895 bytes .../CPShadowView/CPShadowViewLightLeft.png | Bin 0 -> 2807 bytes .../CPShadowView/CPShadowViewLightRight.png | Bin 0 -> 2746 bytes .../CPShadowView/CPShadowViewLightTop.png | Bin 0 -> 2810 bytes .../CPShadowView/CPShadowViewLightTopLeft.png | Bin 0 -> 2867 bytes .../CPShadowViewLightTopRight.png | Bin 0 -> 2878 bytes .../CPSlider/CPSliderKnobRegular.png | Bin 0 -> 3093 bytes .../CPSlider/CPSliderKnobRegularPushed.png | Bin 0 -> 3064 bytes .../CPSliderTrackHorizontalCenter.png | Bin 0 -> 2802 bytes .../CPSlider/CPSliderTrackHorizontalLeft.png | Bin 0 -> 2819 bytes .../CPSlider/CPSliderTrackHorizontalRight.png | Bin 0 -> 2819 bytes .../CPTabViewBezelBackgroundCenter.png | Bin 0 -> 2732 bytes .../CPTabView/CPTabViewBezelBorder.png | Bin 0 -> 2732 bytes .../CPTabView/CPTabViewBezelBorderLeft.png | Bin 0 -> 2745 bytes .../CPTabView/CPTabViewBezelBorderRight.png | Bin 0 -> 2753 bytes .../CPTabView/_CPTabLabelBackgroundCenter.png | Bin 0 -> 2823 bytes .../CPTabView/_CPTabLabelBackgroundLeft.png | Bin 0 -> 2931 bytes .../CPTabView/_CPTabLabelBackgroundRight.png | Bin 0 -> 2925 bytes .../CPTabView/_CPTabLabelSelectedCenter.png | Bin 0 -> 157 bytes .../CPTabView/_CPTabLabelSelectedLeft.png | Bin 0 -> 184 bytes .../CPTabView/_CPTabLabelSelectedRight.png | Bin 0 -> 186 bytes .../CPTabView/_CPTabLabelsViewCenter.png | Bin 0 -> 2832 bytes .../CPTabView/_CPTabLabelsViewLeft.png | Bin 0 -> 3022 bytes .../CPTabView/_CPTabLabelsViewRight.png | Bin 0 -> 3035 bytes .../CPTextField/CPTextFieldBezelSquare0.png | Bin 0 -> 124 bytes .../CPTextField/CPTextFieldBezelSquare1.png | Bin 0 -> 117 bytes .../CPTextField/CPTextFieldBezelSquare2.png | Bin 0 -> 126 bytes .../CPTextField/CPTextFieldBezelSquare3.png | Bin 0 -> 112 bytes .../CPTextField/CPTextFieldBezelSquare4.png | Bin 0 -> 109 bytes .../CPTextField/CPTextFieldBezelSquare5.png | Bin 0 -> 112 bytes .../CPTextField/CPTextFieldBezelSquare6.png | Bin 0 -> 120 bytes .../CPTextField/CPTextFieldBezelSquare7.png | Bin 0 -> 113 bytes .../CPTextField/CPTextFieldBezelSquare8.png | Bin 0 -> 120 bytes AppKit/Resources/CPWindow/CPWindowShadow0.png | Bin 0 -> 250 bytes AppKit/Resources/CPWindow/CPWindowShadow1.png | Bin 0 -> 154 bytes AppKit/Resources/CPWindow/CPWindowShadow2.png | Bin 0 -> 319 bytes AppKit/Resources/CPWindow/CPWindowShadow3.png | Bin 0 -> 126 bytes AppKit/Resources/CPWindow/CPWindowShadow4.png | Bin 0 -> 109 bytes AppKit/Resources/CPWindow/CPWindowShadow5.png | Bin 0 -> 127 bytes AppKit/Resources/CPWindow/CPWindowShadow6.png | Bin 0 -> 263 bytes AppKit/Resources/CPWindow/CPWindowShadow7.png | Bin 0 -> 142 bytes AppKit/Resources/CPWindow/CPWindowShadow8.png | Bin 0 -> 296 bytes AppKit/Resources/CPWindowResizeIndicator.png | Bin 0 -> 242 bytes AppKit/Resources/FIXME_ImageShadow.png | Bin 0 -> 581 bytes .../HUDTheme/CPSliderHorizontalBarCenter.png | Bin 0 -> 107 bytes .../HUDTheme/CPSliderHorizontalBarLeft.png | Bin 0 -> 130 bytes .../HUDTheme/CPSliderHorizontalBarRight.png | Bin 0 -> 129 bytes .../HUDTheme/CPSliderHorizontalKnob.png | Bin 0 -> 509 bytes .../Resources/HUDTheme/WindowBottomCenter.png | Bin 0 -> 2844 bytes .../Resources/HUDTheme/WindowBottomLeft.png | Bin 0 -> 3093 bytes .../Resources/HUDTheme/WindowBottomRight.png | Bin 0 -> 3105 bytes AppKit/Resources/HUDTheme/WindowCenter.png | Bin 0 -> 2792 bytes .../Resources/HUDTheme/WindowCenterLeft.png | Bin 0 -> 2822 bytes .../Resources/HUDTheme/WindowCenterRight.png | Bin 0 -> 2823 bytes AppKit/Resources/HUDTheme/WindowClose.png | Bin 0 -> 3138 bytes .../Resources/HUDTheme/WindowCloseActive.png | Bin 0 -> 3513 bytes AppKit/Resources/HUDTheme/WindowTopCenter.png | Bin 0 -> 2929 bytes AppKit/Resources/HUDTheme/WindowTopLeft.png | Bin 0 -> 3462 bytes AppKit/Resources/HUDTheme/WindowTopRight.png | Bin 0 -> 3454 bytes .../_CPMenuBarWindowBackground.png | Bin 0 -> 2841 bytes .../_CPMenuItemViewMenuBarArrow.png | Bin 0 -> 2872 bytes .../_CPMenuItemViewMenuBarArrowActivated.png | Bin 0 -> 2869 bytes .../_CPMenuWindow/_CPMenuWindow1.png | Bin 0 -> 120 bytes .../_CPMenuWindow/_CPMenuWindow3.png | Bin 0 -> 115 bytes .../_CPMenuWindow/_CPMenuWindow4.png | Bin 0 -> 110 bytes .../_CPMenuWindow/_CPMenuWindow5.png | Bin 0 -> 116 bytes .../_CPMenuWindow/_CPMenuWindow7.png | Bin 0 -> 120 bytes .../_CPMenuWindow/_CPMenuWindowMoreAbove.png | Bin 0 -> 243 bytes .../_CPMenuWindow/_CPMenuWindowMoreBelow.png | Bin 0 -> 239 bytes .../_CPMenuWindow/_CPMenuWindowRounded0.png | Bin 0 -> 160 bytes .../_CPMenuWindow/_CPMenuWindowRounded2.png | Bin 0 -> 165 bytes .../_CPMenuWindow/_CPMenuWindowRounded6.png | Bin 0 -> 164 bytes .../_CPMenuWindow/_CPMenuWindowRounded8.png | Bin 0 -> 162 bytes .../_CPToolbarViewBackground.png | Bin 0 -> 2870 bytes ..._CPToolbarViewExtraItemsAlternateImage.png | Bin 0 -> 3171 bytes .../_CPToolbarViewExtraItemsImage.png | Bin 0 -> 3192 bytes .../_CPWindowViewResizeIndicator.png | Bin 0 -> 242 bytes AppKit/Resources/brightness_bar.png | Bin 0 -> 235 bytes AppKit/Resources/color_well.png | Bin 0 -> 225 bytes AppKit/Resources/kuler_button.png | Bin 0 -> 4411 bytes AppKit/Resources/kuler_button_h.png | Bin 0 -> 1777 bytes AppKit/Resources/slider_button.png | Bin 0 -> 315 bytes AppKit/Resources/slider_button_h.png | Bin 0 -> 319 bytes AppKit/Resources/wheel.png | Bin 0 -> 84870 bytes AppKit/Resources/wheel_black.png | Bin 0 -> 10393 bytes AppKit/Resources/wheel_button.png | Bin 0 -> 4691 bytes AppKit/Resources/wheel_button_h.png | Bin 0 -> 1952 bytes AppKit/_CPImageAndTitleView.j | 399 +++ AppKit/_CPWindowView.j | 270 ++ AppKit/build.xml | 45 + Foundation/CPArray.j | 762 +++++ Foundation/CPBundle.j | 82 + Foundation/CPCoder.j | 100 + Foundation/CPData.j | 112 + Foundation/CPDictionary.j | 320 ++ Foundation/CPEnumerator.j | 37 + Foundation/CPException.j | 130 + Foundation/CPIndexSet.j | 735 +++++ Foundation/CPInvocation.j | 133 + Foundation/CPJSONPConnection.j | 107 + Foundation/CPKeyValueCoding.j | 135 + Foundation/CPKeyedArchiver.j | 457 +++ Foundation/CPKeyedUnarchiver.j | 353 ++ Foundation/CPLog.j | 418 +++ Foundation/CPNotification.j | 71 + Foundation/CPNotificationCenter.j | 305 ++ Foundation/CPNull.j | 47 + Foundation/CPNumber.j | 318 ++ Foundation/CPObjJRuntime.j | 68 + Foundation/CPObject.j | 291 ++ Foundation/CPPropertyListSerialization.j | 42 + Foundation/CPRange.j | 83 + Foundation/CPRunLoop.j | 224 ++ Foundation/CPSortDescriptor.j | 83 + Foundation/CPString.j | 285 ++ Foundation/CPURLConnection.j | 181 ++ Foundation/CPURLRequest.j | 103 + Foundation/CPURLResponse.j | 67 + Foundation/CPUndoManager.j | 599 ++++ Foundation/CPUserSessionManager.j | 98 + Foundation/CPValue.j | 196 ++ Foundation/Foundation.j | 53 + Foundation/Foundation.steam | 40 + Foundation/Info.plist | 14 + Foundation/Resources/log.css | 72 + Foundation/build.xml | 45 + LICENSE | 503 +++ Objective-J/Object.j | 41 + Objective-J/build.xml | 84 + Objective-J/constants.js | 101 + Objective-J/dictionary.js | 119 + Objective-J/evaluate.js | 239 ++ Objective-J/exception.js | 66 + Objective-J/file.js | 533 ++++ Objective-J/license.txt | 22 + Objective-J/plist.js | 661 ++++ Objective-J/preprocess.js | 568 ++++ Objective-J/runtime.js | 571 ++++ Objective-J/static.js | 70 + README | 0 Tools/Install/build.xml | 39 + Tools/Install/install-tools | 59 + Tools/Jars/ant-apache-bsf-1.7.0.jar | Bin 0 -> 3980 bytes Tools/Jars/bsf.jar | Bin 0 -> 113369 bytes Tools/Jars/commons-logging-1.1.jar | Bin 0 -> 52915 bytes Tools/Jars/js.jar | Bin 0 -> 708951 bytes Tools/NewApplication/AppController.j | 32 + Tools/NewApplication/Info.plist | 12 + Tools/NewApplication/build.xml | 30 + Tools/NewApplication/index.html | 36 + Tools/NewApplication/main.j | 17 + Tools/NibApp/Info.plist | 25 + Tools/NibApp/MyDocument.j | 33 + Tools/NibApp/Resources/spinner.gif | Bin 0 -> 4481 bytes Tools/NibApp/index.html | 34 + Tools/NibApp/main.j | 20 + .../Objective-J.mode/Contents/Info.plist | 23 + .../Contents/Resources/ChangeLog.txt | 25 + .../Resources/English.lproj/InfoPlist.strings | Bin 0 -> 220 bytes .../English.lproj/Localizable.strings | Bin 0 -> 1626 bytes .../Resources/German.lproj/InfoPlist.strings | Bin 0 -> 222 bytes .../German.lproj/Localizable.strings | Bin 0 -> 1422 bytes .../Contents/Resources/ModeSettings.xml | 8 + .../Contents/Resources/RegexSymbols.xml | 56 + .../10-InsertNSLogWithFunctionCall.scpt | Bin 0 -> 1944 bytes .../Scripts/20-InsertCallToSuper.scpt | Bin 0 -> 4830 bytes .../Resources/Scripts/30-OpenCounterpart.scpt | Bin 0 -> 5788 bytes .../Scripts/40-OpenFileInProject.scpt | Bin 0 -> 17278 bytes .../Scripts/45-OpenXcodeProject.scpt | Bin 0 -> 15838 bytes .../Scripts/50-CompileUsingXcode.scpt | Bin 0 -> 16040 bytes .../Scripts/60-un_comment_lines.scpt | Bin 0 -> 6594 bytes .../Resources/Scripts/Lookup in AppKiDo.scpt | Bin 0 -> 2622 bytes .../Resources/Scripts/shell/insert_super.py | 42 + .../Contents/Resources/SyntaxDefinition.xml | 2833 +++++++++++++++++ .../Contents/Resources/ToolbarAppKiDo.png | Bin 0 -> 5206 bytes .../Contents/Resources/ToolbarBuild.tiff | Bin 0 -> 16080 bytes .../Contents/Resources/ToolbarCounterpart.png | Bin 0 -> 1677 bytes .../Resources/ToolbarXcodeProject.png | Bin 0 -> 1867 bytes Tools/TextMate/Objective-J.tmbundle.zip | Bin 0 -> 26251 bytes Tools/Utilities/bridge.js | 476 +++ Tools/Utilities/build.xml | 22 + Tools/Utilities/cat | 17 + Tools/Utilities/regex-bridge.js | 76 + Tools/bake/bake | 33 + Tools/bake/bake.j | 263 ++ Tools/bake/bake_template.html | 65 + Tools/bake/build.xml | 41 + Tools/bake/example.bakefile | 49 + Tools/build.xml | 56 + Tools/nib2cib/HelloWorld.nib/classes.nib | 8 + Tools/nib2cib/HelloWorld.nib/info.nib | 18 + Tools/nib2cib/HelloWorld.nib/keyedobjects.nib | 604 ++++ Tools/nib2cib/NSAppKit.j | 10 + Tools/nib2cib/NSArray.j | 19 + Tools/nib2cib/NSButton.j | 88 + Tools/nib2cib/NSCell.j | 45 + Tools/nib2cib/NSControl.j | 43 + Tools/nib2cib/NSCustomView.j | 42 + Tools/nib2cib/NSFont.j | 28 + Tools/nib2cib/NSFoundation.j | 2 + Tools/nib2cib/NSIBObjectData.j | 96 + Tools/nib2cib/NSResponder.j | 33 + Tools/nib2cib/NSSlider.j | 47 + Tools/nib2cib/NSView.j | 96 + Tools/nib2cib/nib2cib | 6 + Tools/nib2cib/nib2cib.j | 83 + Tools/nib2cib/project.properties | 5 + Tools/objj/build.xml | 65 + Tools/objj/objj | 51 + Tools/objj/objj.js | 47 + Tools/objjc/build.xml | 56 + Tools/objjc/objjc | 31 + Tools/objjc/objjc.js | 106 + Tools/steam/build.xml | 61 + Tools/steam/sjheader.txt | 1 + Tools/steam/steam | 31 + Tools/steam/steam.js | 504 +++ Tools/steam/steam.xml | 17 + build.xml | 46 + common.xml | 118 + 376 files changed, 43087 insertions(+) create mode 100644 AppKit/AppKit.j create mode 100644 AppKit/AppKit.steam create mode 100644 AppKit/CPAnimation.j create mode 100644 AppKit/CPApplication.j create mode 100644 AppKit/CPButton.j create mode 100644 AppKit/CPClipView.j create mode 100644 AppKit/CPCollectionView.j create mode 100644 AppKit/CPColor.j create mode 100644 AppKit/CPColorPanel.j create mode 100644 AppKit/CPColorPicker.j create mode 100644 AppKit/CPColorWell.j create mode 100644 AppKit/CPCompatibility.j create mode 100644 AppKit/CPControl.j create mode 100644 AppKit/CPCookie.j create mode 100644 AppKit/CPDocument.j create mode 100644 AppKit/CPDocumentController.j create mode 100644 AppKit/CPDragServer.j create mode 100644 AppKit/CPEvent.j create mode 100644 AppKit/CPFlashMovie.j create mode 100644 AppKit/CPFlashView.j create mode 100644 AppKit/CPFont.j create mode 100644 AppKit/CPFontManager.j create mode 100644 AppKit/CPGeometry.j create mode 100644 AppKit/CPGraphicsContext.j create mode 100644 AppKit/CPImage.j create mode 100644 AppKit/CPImageView.j create mode 100644 AppKit/CPKulerColorPicker.j create mode 100644 AppKit/CPMenu.j create mode 100644 AppKit/CPMenuItem.j create mode 100644 AppKit/CPOutlineView.j create mode 100644 AppKit/CPPanel.j create mode 100644 AppKit/CPPasteboard.j create mode 100644 AppKit/CPPopUpButton.j create mode 100644 AppKit/CPProgressIndicator.j create mode 100644 AppKit/CPResponder.j create mode 100644 AppKit/CPScrollView.j create mode 100644 AppKit/CPScroller.j create mode 100644 AppKit/CPSegmentedControl.j create mode 100644 AppKit/CPShadow.j create mode 100644 AppKit/CPShadowView.j create mode 100644 AppKit/CPSlider.j create mode 100644 AppKit/CPSliderColorPicker.j create mode 100644 AppKit/CPStringDrawing.j create mode 100644 AppKit/CPTabView.j create mode 100644 AppKit/CPTabViewItem.j create mode 100644 AppKit/CPTableColumn.j create mode 100644 AppKit/CPTableView.j create mode 100644 AppKit/CPTextField.j create mode 100644 AppKit/CPToolbar.j create mode 100644 AppKit/CPToolbarItem.j create mode 100644 AppKit/CPView.j create mode 100644 AppKit/CPWindow.j create mode 100644 AppKit/CPWindowController.j create mode 100644 AppKit/Cib/CPCib.j create mode 100644 AppKit/Cib/CPCustomView.j create mode 100644 AppKit/Cib/_CPCibLoading.j create mode 100644 AppKit/Cib/_CPCibObjectData.j create mode 100644 AppKit/CoreAnimation/CAAnimation.j create mode 100644 AppKit/CoreAnimation/CABackingStore.j create mode 100644 AppKit/CoreAnimation/CAFlashLayer.j create mode 100644 AppKit/CoreAnimation/CALayer.j create mode 100644 AppKit/CoreAnimation/CAMediaTimingFunction.j create mode 100644 AppKit/CoreGraphics/CGAffineTransform.h create mode 100644 AppKit/CoreGraphics/CGAffineTransform.j create mode 100644 AppKit/CoreGraphics/CGColor.j create mode 100644 AppKit/CoreGraphics/CGColorSpace.j create mode 100644 AppKit/CoreGraphics/CGContext.j create mode 100644 AppKit/CoreGraphics/CGContextCanvas.j create mode 100644 AppKit/CoreGraphics/CGContextVML.j create mode 100644 AppKit/CoreGraphics/CGGeometry.h create mode 100644 AppKit/CoreGraphics/CGGeometry.j create mode 100644 AppKit/CoreGraphics/CGGradient.j create mode 100644 AppKit/CoreGraphics/CGPath.j create mode 100644 AppKit/Info.plist create mode 100644 AppKit/Platform/DOM/CPDOMDisplayServer.h create mode 100644 AppKit/Platform/DOM/CPDOMDisplayServer.j create mode 100644 AppKit/Platform/DOM/CPDOMWindowBridge.j create mode 100644 AppKit/Platform/DOM/CPDOMWindowLayer.j create mode 100644 AppKit/Platform/Platform.h create mode 100644 AppKit/Resources/CPApplication/New.png create mode 100644 AppKit/Resources/CPApplication/NewHighlighted.png create mode 100644 AppKit/Resources/CPApplication/Open.png create mode 100644 AppKit/Resources/CPApplication/OpenHighlighted.png create mode 100644 AppKit/Resources/CPApplication/Save.png create mode 100644 AppKit/Resources/CPApplication/SaveHighlighted.png create mode 100644 AppKit/Resources/CPButton/CPButtonHUDRegular0.png create mode 100644 AppKit/Resources/CPButton/CPButtonHUDRegular1.png create mode 100644 AppKit/Resources/CPButton/CPButtonHUDRegular2.png create mode 100644 AppKit/Resources/CPButton/CPButtonHUDRegularHighlighted0.png create mode 100644 AppKit/Resources/CPButton/CPButtonHUDRegularHighlighted1.png create mode 100644 AppKit/Resources/CPButton/CPButtonHUDRegularHighlighted2.png create mode 100644 AppKit/Resources/CPButton/CPButtonRoundRectRegular0.png create mode 100644 AppKit/Resources/CPButton/CPButtonRoundRectRegular1.png create mode 100644 AppKit/Resources/CPButton/CPButtonRoundRectRegular2.png create mode 100644 AppKit/Resources/CPButton/CPButtonRoundRectRegularHighlighted0.png create mode 100644 AppKit/Resources/CPButton/CPButtonRoundRectRegularHighlighted1.png create mode 100644 AppKit/Resources/CPButton/CPButtonRoundRectRegularHighlighted2.png create mode 100644 AppKit/Resources/CPButton/CPButtonTexturedRoundedRegular0.png create mode 100644 AppKit/Resources/CPButton/CPButtonTexturedRoundedRegular1.png create mode 100644 AppKit/Resources/CPButton/CPButtonTexturedRoundedRegular2.png create mode 100644 AppKit/Resources/CPButton/CPButtonTexturedRoundedRegularHighlighted0.png create mode 100644 AppKit/Resources/CPButton/CPButtonTexturedRoundedRegularHighlighted1.png create mode 100644 AppKit/Resources/CPButton/CPButtonTexturedRoundedRegularHighlighted2.png create mode 100644 AppKit/Resources/CPImageView/CPImageViewBottomLeftShadow.png create mode 100644 AppKit/Resources/CPImageView/CPImageViewBottomRightShadow.png create mode 100644 AppKit/Resources/CPImageView/CPImageViewBottomShadow.png create mode 100644 AppKit/Resources/CPImageView/CPImageViewLeftShadow.png create mode 100644 AppKit/Resources/CPImageView/CPImageViewRightShadow.png create mode 100644 AppKit/Resources/CPImageView/CPImageViewTopLeftShadow.png create mode 100644 AppKit/Resources/CPImageView/CPImageViewTopRightShadow.png create mode 100644 AppKit/Resources/CPImageView/CPImageViewTopShadow.png create mode 100644 AppKit/Resources/CPMenuItem/CPMenuItemOnState.png create mode 100644 AppKit/Resources/CPMenuItem/CPMenuItemOnStateHighlighted.png create mode 100644 AppKit/Resources/CPProgressIndicator/CPProgressIndicatorBarBarRegular.png create mode 100644 AppKit/Resources/CPProgressIndicator/CPProgressIndicatorBarHUDBarSmall.png create mode 100644 AppKit/Resources/CPProgressIndicator/CPProgressIndicatorBezelBorderBarRegular0.png create mode 100644 AppKit/Resources/CPProgressIndicator/CPProgressIndicatorBezelBorderBarRegular1.png create mode 100644 AppKit/Resources/CPProgressIndicator/CPProgressIndicatorBezelBorderBarRegular2.png create mode 100644 AppKit/Resources/CPProgressIndicator/CPProgressIndicatorBezelBorderHUDBarSmall0.png create mode 100644 AppKit/Resources/CPProgressIndicator/CPProgressIndicatorBezelBorderHUDBarSmall1.png create mode 100644 AppKit/Resources/CPProgressIndicator/CPProgressIndicatorBezelBorderHUDBarSmall2.png create mode 100644 AppKit/Resources/CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif create mode 100644 AppKit/Resources/CPScroller/CPScrollerDecrementArrowHorizontalRegular.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerDecrementArrowHorizontalRegularHighlighted.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerDecrementArrowVerticalRegular.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerDecrementArrowVerticalRegularHighlighted.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerDecrementArrowVerticalSmall.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerDecrementArrowVerticalSmallHighlighted.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerIncrementArrowHorizontalRegular.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerIncrementArrowHorizontalRegularHighlighted.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerIncrementArrowVerticalRegular.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerIncrementArrowVerticalRegularHighlighted.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerIncrementArrowVerticalSmall.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerIncrementArrowVerticalSmallHighlighted.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerKnobHorizontalRegular0.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerKnobHorizontalRegular1.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerKnobHorizontalRegular2.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerKnobSlotHorizontalRegular.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerKnobSlotVerticalRegular.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerKnobSlotVerticalSmall.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerKnobVerticalRegular0.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerKnobVerticalRegular1.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerKnobVerticalRegular2.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerKnobVerticalSmall0.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerKnobVerticalSmall1.png create mode 100644 AppKit/Resources/CPScroller/CPScrollerKnobVerticalSmall2.png create mode 100644 AppKit/Resources/CPShadowView/CPShadowViewHeavyBottom.png create mode 100644 AppKit/Resources/CPShadowView/CPShadowViewHeavyBottomLeft.png create mode 100644 AppKit/Resources/CPShadowView/CPShadowViewHeavyBottomRight.png create mode 100644 AppKit/Resources/CPShadowView/CPShadowViewHeavyLeft.png create mode 100644 AppKit/Resources/CPShadowView/CPShadowViewHeavyRight.png create mode 100644 AppKit/Resources/CPShadowView/CPShadowViewHeavyTop.png create mode 100644 AppKit/Resources/CPShadowView/CPShadowViewHeavyTopLeft.png create mode 100644 AppKit/Resources/CPShadowView/CPShadowViewHeavyTopRight.png create mode 100644 AppKit/Resources/CPShadowView/CPShadowViewLightBottom.png create mode 100644 AppKit/Resources/CPShadowView/CPShadowViewLightBottomLeft.png create mode 100644 AppKit/Resources/CPShadowView/CPShadowViewLightBottomRight.png create mode 100644 AppKit/Resources/CPShadowView/CPShadowViewLightLeft.png create mode 100644 AppKit/Resources/CPShadowView/CPShadowViewLightRight.png create mode 100644 AppKit/Resources/CPShadowView/CPShadowViewLightTop.png create mode 100644 AppKit/Resources/CPShadowView/CPShadowViewLightTopLeft.png create mode 100644 AppKit/Resources/CPShadowView/CPShadowViewLightTopRight.png create mode 100644 AppKit/Resources/CPSlider/CPSliderKnobRegular.png create mode 100644 AppKit/Resources/CPSlider/CPSliderKnobRegularPushed.png create mode 100644 AppKit/Resources/CPSlider/CPSliderTrackHorizontalCenter.png create mode 100644 AppKit/Resources/CPSlider/CPSliderTrackHorizontalLeft.png create mode 100644 AppKit/Resources/CPSlider/CPSliderTrackHorizontalRight.png create mode 100644 AppKit/Resources/CPTabView/CPTabViewBezelBackgroundCenter.png create mode 100644 AppKit/Resources/CPTabView/CPTabViewBezelBorder.png create mode 100644 AppKit/Resources/CPTabView/CPTabViewBezelBorderLeft.png create mode 100644 AppKit/Resources/CPTabView/CPTabViewBezelBorderRight.png create mode 100644 AppKit/Resources/CPTabView/_CPTabLabelBackgroundCenter.png create mode 100644 AppKit/Resources/CPTabView/_CPTabLabelBackgroundLeft.png create mode 100644 AppKit/Resources/CPTabView/_CPTabLabelBackgroundRight.png create mode 100644 AppKit/Resources/CPTabView/_CPTabLabelSelectedCenter.png create mode 100644 AppKit/Resources/CPTabView/_CPTabLabelSelectedLeft.png create mode 100644 AppKit/Resources/CPTabView/_CPTabLabelSelectedRight.png create mode 100644 AppKit/Resources/CPTabView/_CPTabLabelsViewCenter.png create mode 100644 AppKit/Resources/CPTabView/_CPTabLabelsViewLeft.png create mode 100644 AppKit/Resources/CPTabView/_CPTabLabelsViewRight.png create mode 100644 AppKit/Resources/CPTextField/CPTextFieldBezelSquare0.png create mode 100644 AppKit/Resources/CPTextField/CPTextFieldBezelSquare1.png create mode 100644 AppKit/Resources/CPTextField/CPTextFieldBezelSquare2.png create mode 100644 AppKit/Resources/CPTextField/CPTextFieldBezelSquare3.png create mode 100644 AppKit/Resources/CPTextField/CPTextFieldBezelSquare4.png create mode 100644 AppKit/Resources/CPTextField/CPTextFieldBezelSquare5.png create mode 100644 AppKit/Resources/CPTextField/CPTextFieldBezelSquare6.png create mode 100644 AppKit/Resources/CPTextField/CPTextFieldBezelSquare7.png create mode 100644 AppKit/Resources/CPTextField/CPTextFieldBezelSquare8.png create mode 100644 AppKit/Resources/CPWindow/CPWindowShadow0.png create mode 100644 AppKit/Resources/CPWindow/CPWindowShadow1.png create mode 100644 AppKit/Resources/CPWindow/CPWindowShadow2.png create mode 100644 AppKit/Resources/CPWindow/CPWindowShadow3.png create mode 100644 AppKit/Resources/CPWindow/CPWindowShadow4.png create mode 100644 AppKit/Resources/CPWindow/CPWindowShadow5.png create mode 100644 AppKit/Resources/CPWindow/CPWindowShadow6.png create mode 100644 AppKit/Resources/CPWindow/CPWindowShadow7.png create mode 100644 AppKit/Resources/CPWindow/CPWindowShadow8.png create mode 100644 AppKit/Resources/CPWindowResizeIndicator.png create mode 100644 AppKit/Resources/FIXME_ImageShadow.png create mode 100644 AppKit/Resources/HUDTheme/CPSliderHorizontalBarCenter.png create mode 100644 AppKit/Resources/HUDTheme/CPSliderHorizontalBarLeft.png create mode 100644 AppKit/Resources/HUDTheme/CPSliderHorizontalBarRight.png create mode 100644 AppKit/Resources/HUDTheme/CPSliderHorizontalKnob.png create mode 100644 AppKit/Resources/HUDTheme/WindowBottomCenter.png create mode 100644 AppKit/Resources/HUDTheme/WindowBottomLeft.png create mode 100644 AppKit/Resources/HUDTheme/WindowBottomRight.png create mode 100644 AppKit/Resources/HUDTheme/WindowCenter.png create mode 100644 AppKit/Resources/HUDTheme/WindowCenterLeft.png create mode 100644 AppKit/Resources/HUDTheme/WindowCenterRight.png create mode 100644 AppKit/Resources/HUDTheme/WindowClose.png create mode 100644 AppKit/Resources/HUDTheme/WindowCloseActive.png create mode 100644 AppKit/Resources/HUDTheme/WindowTopCenter.png create mode 100644 AppKit/Resources/HUDTheme/WindowTopLeft.png create mode 100644 AppKit/Resources/HUDTheme/WindowTopRight.png create mode 100644 AppKit/Resources/_CPMenuBarWindow/_CPMenuBarWindowBackground.png create mode 100644 AppKit/Resources/_CPMenuItemView/_CPMenuItemViewMenuBarArrow.png create mode 100644 AppKit/Resources/_CPMenuItemView/_CPMenuItemViewMenuBarArrowActivated.png create mode 100644 AppKit/Resources/_CPMenuWindow/_CPMenuWindow1.png create mode 100644 AppKit/Resources/_CPMenuWindow/_CPMenuWindow3.png create mode 100644 AppKit/Resources/_CPMenuWindow/_CPMenuWindow4.png create mode 100644 AppKit/Resources/_CPMenuWindow/_CPMenuWindow5.png create mode 100644 AppKit/Resources/_CPMenuWindow/_CPMenuWindow7.png create mode 100644 AppKit/Resources/_CPMenuWindow/_CPMenuWindowMoreAbove.png create mode 100644 AppKit/Resources/_CPMenuWindow/_CPMenuWindowMoreBelow.png create mode 100644 AppKit/Resources/_CPMenuWindow/_CPMenuWindowRounded0.png create mode 100644 AppKit/Resources/_CPMenuWindow/_CPMenuWindowRounded2.png create mode 100644 AppKit/Resources/_CPMenuWindow/_CPMenuWindowRounded6.png create mode 100644 AppKit/Resources/_CPMenuWindow/_CPMenuWindowRounded8.png create mode 100644 AppKit/Resources/_CPToolbarView/_CPToolbarViewBackground.png create mode 100644 AppKit/Resources/_CPToolbarView/_CPToolbarViewExtraItemsAlternateImage.png create mode 100644 AppKit/Resources/_CPToolbarView/_CPToolbarViewExtraItemsImage.png create mode 100644 AppKit/Resources/_CPWindowView/_CPWindowViewResizeIndicator.png create mode 100644 AppKit/Resources/brightness_bar.png create mode 100644 AppKit/Resources/color_well.png create mode 100644 AppKit/Resources/kuler_button.png create mode 100644 AppKit/Resources/kuler_button_h.png create mode 100644 AppKit/Resources/slider_button.png create mode 100644 AppKit/Resources/slider_button_h.png create mode 100644 AppKit/Resources/wheel.png create mode 100644 AppKit/Resources/wheel_black.png create mode 100644 AppKit/Resources/wheel_button.png create mode 100644 AppKit/Resources/wheel_button_h.png create mode 100644 AppKit/_CPImageAndTitleView.j create mode 100644 AppKit/_CPWindowView.j create mode 100644 AppKit/build.xml create mode 100755 Foundation/CPArray.j create mode 100644 Foundation/CPBundle.j create mode 100644 Foundation/CPCoder.j create mode 100644 Foundation/CPData.j create mode 100755 Foundation/CPDictionary.j create mode 100755 Foundation/CPEnumerator.j create mode 100755 Foundation/CPException.j create mode 100644 Foundation/CPIndexSet.j create mode 100644 Foundation/CPInvocation.j create mode 100644 Foundation/CPJSONPConnection.j create mode 100644 Foundation/CPKeyValueCoding.j create mode 100644 Foundation/CPKeyedArchiver.j create mode 100644 Foundation/CPKeyedUnarchiver.j create mode 100644 Foundation/CPLog.j create mode 100644 Foundation/CPNotification.j create mode 100644 Foundation/CPNotificationCenter.j create mode 100644 Foundation/CPNull.j create mode 100644 Foundation/CPNumber.j create mode 100644 Foundation/CPObjJRuntime.j create mode 100644 Foundation/CPObject.j create mode 100644 Foundation/CPPropertyListSerialization.j create mode 100755 Foundation/CPRange.j create mode 100644 Foundation/CPRunLoop.j create mode 100755 Foundation/CPSortDescriptor.j create mode 100644 Foundation/CPString.j create mode 100644 Foundation/CPURLConnection.j create mode 100644 Foundation/CPURLRequest.j create mode 100644 Foundation/CPURLResponse.j create mode 100644 Foundation/CPUndoManager.j create mode 100644 Foundation/CPUserSessionManager.j create mode 100644 Foundation/CPValue.j create mode 100755 Foundation/Foundation.j create mode 100644 Foundation/Foundation.steam create mode 100644 Foundation/Info.plist create mode 100644 Foundation/Resources/log.css create mode 100644 Foundation/build.xml create mode 100644 LICENSE create mode 100644 Objective-J/Object.j create mode 100644 Objective-J/build.xml create mode 100644 Objective-J/constants.js create mode 100644 Objective-J/dictionary.js create mode 100644 Objective-J/evaluate.js create mode 100644 Objective-J/exception.js create mode 100644 Objective-J/file.js create mode 100644 Objective-J/license.txt create mode 100644 Objective-J/plist.js create mode 100644 Objective-J/preprocess.js create mode 100644 Objective-J/runtime.js create mode 100644 Objective-J/static.js create mode 100644 README create mode 100644 Tools/Install/build.xml create mode 100755 Tools/Install/install-tools create mode 100644 Tools/Jars/ant-apache-bsf-1.7.0.jar create mode 100644 Tools/Jars/bsf.jar create mode 100644 Tools/Jars/commons-logging-1.1.jar create mode 100644 Tools/Jars/js.jar create mode 100644 Tools/NewApplication/AppController.j create mode 100644 Tools/NewApplication/Info.plist create mode 100644 Tools/NewApplication/build.xml create mode 100644 Tools/NewApplication/index.html create mode 100755 Tools/NewApplication/main.j create mode 100644 Tools/NibApp/Info.plist create mode 100644 Tools/NibApp/MyDocument.j create mode 100644 Tools/NibApp/Resources/spinner.gif create mode 100644 Tools/NibApp/index.html create mode 100755 Tools/NibApp/main.j create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Info.plist create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/ChangeLog.txt create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/English.lproj/InfoPlist.strings create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/English.lproj/Localizable.strings create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/German.lproj/InfoPlist.strings create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/German.lproj/Localizable.strings create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/ModeSettings.xml create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/RegexSymbols.xml create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/10-InsertNSLogWithFunctionCall.scpt create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/20-InsertCallToSuper.scpt create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/30-OpenCounterpart.scpt create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/40-OpenFileInProject.scpt create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/45-OpenXcodeProject.scpt create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/50-CompileUsingXcode.scpt create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/60-un_comment_lines.scpt create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/Lookup in AppKiDo.scpt create mode 100755 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/shell/insert_super.py create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/SyntaxDefinition.xml create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/ToolbarAppKiDo.png create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/ToolbarBuild.tiff create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/ToolbarCounterpart.png create mode 100644 Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/ToolbarXcodeProject.png create mode 100644 Tools/TextMate/Objective-J.tmbundle.zip create mode 100644 Tools/Utilities/bridge.js create mode 100644 Tools/Utilities/build.xml create mode 100755 Tools/Utilities/cat create mode 100644 Tools/Utilities/regex-bridge.js create mode 100644 Tools/bake/bake create mode 100644 Tools/bake/bake.j create mode 100644 Tools/bake/bake_template.html create mode 100644 Tools/bake/build.xml create mode 100644 Tools/bake/example.bakefile create mode 100644 Tools/build.xml create mode 100644 Tools/nib2cib/HelloWorld.nib/classes.nib create mode 100644 Tools/nib2cib/HelloWorld.nib/info.nib create mode 100644 Tools/nib2cib/HelloWorld.nib/keyedobjects.nib create mode 100644 Tools/nib2cib/NSAppKit.j create mode 100644 Tools/nib2cib/NSArray.j create mode 100644 Tools/nib2cib/NSButton.j create mode 100644 Tools/nib2cib/NSCell.j create mode 100644 Tools/nib2cib/NSControl.j create mode 100644 Tools/nib2cib/NSCustomView.j create mode 100644 Tools/nib2cib/NSFont.j create mode 100644 Tools/nib2cib/NSFoundation.j create mode 100644 Tools/nib2cib/NSIBObjectData.j create mode 100644 Tools/nib2cib/NSResponder.j create mode 100644 Tools/nib2cib/NSSlider.j create mode 100644 Tools/nib2cib/NSView.j create mode 100755 Tools/nib2cib/nib2cib create mode 100644 Tools/nib2cib/nib2cib.j create mode 100644 Tools/nib2cib/project.properties create mode 100644 Tools/objj/build.xml create mode 100644 Tools/objj/objj create mode 100644 Tools/objj/objj.js create mode 100644 Tools/objjc/build.xml create mode 100644 Tools/objjc/objjc create mode 100644 Tools/objjc/objjc.js create mode 100644 Tools/steam/build.xml create mode 100644 Tools/steam/sjheader.txt create mode 100644 Tools/steam/steam create mode 100644 Tools/steam/steam.js create mode 100644 Tools/steam/steam.xml create mode 100644 build.xml create mode 100644 common.xml diff --git a/AppKit/AppKit.j b/AppKit/AppKit.j new file mode 100644 index 000000000..4567fdf1d --- /dev/null +++ b/AppKit/AppKit.j @@ -0,0 +1,60 @@ +/* + * AppKit.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CALayer.j" +import "CPAnimation.j" +import "CPApplication.j" +import "CPButton.j" +import "CPClipView.j" +import "CPCollectionView.j" +import "CPColor.j" +import "CPColorPanel.j" +import "CPColorWell.j" +import "CPCompatibility.j" +import "CPControl.j" +import "CPCookie.j" +import "CPDocument.j" +import "CPDocumentController.j" +import "CPEvent.j" +import "CPFont.j" +import "CPFontManager.j" +import "CPGeometry.j" +import "CPImage.j" +import "CPImageView.j" +import "CPMenu.j" +import "CPMenuItem.j" +import "CPPanel.j" +import "CPPasteboard.j" +import "CPPopUpButton.j" +import "CPProgressIndicator.j" +import "CPResponder.j" +import "CPScroller.j" +import "CPScrollView.j" +import "CPSegmentedControl.j" +import "CPShadow.j" +import "CPSlider.j" +import "CPTextField.j" +import "CPToolbar.j" +import "CPToolbarItem.j" +import "CPView.j" +import "CPWindow.j" +import "CPWindowController.j" diff --git a/AppKit/AppKit.steam b/AppKit/AppKit.steam new file mode 100644 index 000000000..14e67d8d0 --- /dev/null +++ b/AppKit/AppKit.steam @@ -0,0 +1,46 @@ + + + + + name + AppKit + Targets + + + name + AppKit + Excluded + + CPOutlineView.j + CPTableColumn.j + CPTableView.j + + + + Configurations + + + name + Debug + Settings + + PREPROCESS + + FLAGS + -DDEBUG + + + + name + Release + Settings + + PREPROCESS + + PREINTERPRET + + + + + + diff --git a/AppKit/CPAnimation.j b/AppKit/CPAnimation.j new file mode 100644 index 000000000..b3a10f93f --- /dev/null +++ b/AppKit/CPAnimation.j @@ -0,0 +1,191 @@ +/* + * CPAnimation.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + +import "CAMediaTimingFunction.j" + + +CPAnimationEaseInOut = 0, +CPAnimationEaseIn = 1, +CPAnimationEaseOut = 2, +CPAnimationLinear = 3; + +ACTUAL_FRAME_RATE = 0; + +@implementation CPAnimation : CPObject +{ + CPTimeInterval _startTime; + CPTimeInterval _duration; + + CPAnimationCurve _animationCurve; + CAMediaTimingFunction _timingFunction; + + float _frameRate; + CPAnimationProgress _progress; + + id _delegate; + CPTimer _timer; +} + +- (id)initWithDuration:(float)aDuration animationCurve:(CPAnimationCurve)anAnimationCurve +{ + self = [super init]; + + if (self) + { + _duration = aDuration; + _animationCurve = anAnimationCurve; + _frameRate = 60.0; + } + + return self; +} + +- (void)setAnimationCurve:(CPAnimationCurve)anAnimationCurve +{ + _animationCurve = anAnimationCurve; + + var timingFunctionName = kCAMediaTimingFunctionLinear; + + switch (_animationCurve) + { + case CPAnimationEaseInOut: timingFunctionName = kCAMediaTimingFunctionEaseInEaseOut; + break; + + case CPAnimationEaseIn: timingFunctionName = kCAMediaTimingFunctionEaseIn; + break; + + case CPAnimationEaseOut: timingFunctionName = kCAMediaTimingFunctionEaseOut; + break; + } + + _timingFunction = [CAMediaTimingFunction functionWithName:timingFunctionName]; +} + +- (CPAnimationCurve)animationCurve +{ + return _animationCurve; +} + +- (void)setDuration:(CPTimeInterval)aDuration +{ + _duration = aDuration; +} + +- (CPTimeInterval)duration +{ + return _duration; +} + +- (void)setFramesPerSecond:(float)framesPerSecond +{ + _frameRate = framesPerSecond; +} + +- (float)frameRate +{ + return _frameRate; +} + +- (id)delegate +{ + return _delegate; +} + +- (void)setDelegate:(id)aDelegate +{ + _delegate = aDelegate; +} + +- (void)startAnimation +{ + // If we're already animating, or our delegate stops us, animate. + if (_timer || _delegate && ![_delegate animationShouldStart:self]) + return; + + _progress = 0.0; + ACTUAL_FRAME_RATE = 0; + _startTime = new Date(); + // FIXME: THIS SHOULD BE A CPTIMER!!! + _timer = window.setInterval(function() { + [self animationTimerDidFire:_timer]; + [[CPRunLoop currentRunLoop] performSelectors]; + }, 1); // must be 1ms not 0 for IE. //_duration * 1000 / _frameRate); +} + +- (void)animationTimerDidFire:(CPTimer)aTimer +{ + var elapsed = new Date() - _startTime, + progress = MIN(1.0, 1.0 - (_duration - elapsed / 1000.0) / _duration); +++ACTUAL_FRAME_RATE; + [self setCurrentProgress:progress]; + + if (progress == 1.0) + { + window.clearTimeout(_timer); + _timer = nil; + + if ([_delegate respondsToSelector:@selector(animationDidEnd:)]) + [_delegate animationDidEnd:self]; + } + +} + +- (void)stopAnimation +{ + if (!_timer) + return; + + window.clearTimeout(_timer); + _timer = nil; + + [_delegate animationDidStop:self]; +} + +- (BOOL)isAnimating +{ + return _timer; +} + +- (void)setCurrentProgress:(CPAnimationProgress)aProgress +{ + _progress = aProgress; +} + +- (CPAnimationProgress)currentProgress +{ + return _progress; +} + +- (float)currentValue +{ + if ([_delegate respondsToSelector:@selector(animation:valueForProgress:)]) + return [_delegate animation:self valueForProgress:_progress]; + + if (_animationCurve == CPAnimationLinear) + return _progress; + + alert("IMPLEMENT ANIMATION CURVES!!!"); +} + +@end diff --git a/AppKit/CPApplication.j b/AppKit/CPApplication.j new file mode 100644 index 000000000..63b12bbaa --- /dev/null +++ b/AppKit/CPApplication.j @@ -0,0 +1,552 @@ +/* + * CPApplication.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + +import "CPCompatibility.j" +import "CPEvent.j" +import "CPMenu.j" +import "CPResponder.j" +import "CPDocumentController.j" + +CPApp = nil; + +CPApplicationWillFinishLaunchingNotification = @"CPApplicationWillFinishLaunchingNotification"; +CPApplicationDidFinishLaunchingNotification = @"CPApplicationDidFinishLaunchingNotification"; + +CPRunStoppedResponse = -1000; +CPRunAbortedResponse = -1001; +CPRunContinuesResponse = -1002; + +@implementation CPApplication : CPResponder +{ + CPArray _eventListeners; + + CPEvent _currentEvent; + + CPArray _windows; + CPWindow _keyWindow; + CPWindow _mainWindow; + + CPMenu _mainMenu; + CPDocumentController _documentController; + + CPModalSession _currentSession; + + // + id _delegate; + + CPDictionary _namedArgs; + CPArray _args; +} + ++ (CPApplication)sharedApplication +{ + if (!CPApp) + CPApp = [[CPApplication alloc] init]; + + return CPApp; +} + +- (id)init +{ + self = [super init]; + + if (self) + { + _eventListeners = []; + + _windows = []; + + [_windows addObject:nil]; + + // FIXME: This should be read from the cib. + _mainMenu = [[CPMenu alloc] initWithTitle:@"MainMenu"]; + + // FIXME: We should implement autoenabling. + [_mainMenu setAutoenablesItems:NO]; + + var bundle = [CPBundle bundleForClass:[CPApplication class]], + newMenuItem = [[CPMenuItem alloc] initWithTitle:@"New" action:@selector(newDocument:) keyEquivalent:@"N"]; + + [newMenuItem setImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/New.png"] size:CGSizeMake(16.0, 16.0)]]; + [newMenuItem setAlternateImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/NewHighlighted.png"] size:CGSizeMake(16.0, 16.0)]]; + + [_mainMenu addItem:newMenuItem]; + + var openMenuItem = [[CPMenuItem alloc] initWithTitle:@"Open" action:@selector(openDocument:) keyEquivalent:@"O"]; + + [openMenuItem setImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/Open.png"] size:CGSizeMake(16.0, 16.0)]]; + [openMenuItem setAlternateImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/OpenHighlighted.png"] size:CGSizeMake(16.0, 16.0)]]; + + [_mainMenu addItem:openMenuItem]; + + var saveMenu = [[CPMenu alloc] initWithTitle:@"Save"], + saveMenuItem = [[CPMenuItem alloc] initWithTitle:@"Save" action:@selector(saveDocument:) keyEquivalent:@""]; + + [saveMenuItem setImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/Save.png"] size:CGSizeMake(16.0, 16.0)]]; + [saveMenuItem setAlternateImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/SaveHighlighted.png"] size:CGSizeMake(16.0, 16.0)]]; + + [saveMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Save" action:@selector(saveDocument:) keyEquivalent:@"S"]]; + [saveMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Save As" action:@selector(saveDocumentAs:) keyEquivalent:@""]]; + + [saveMenuItem setSubmenu:saveMenu]; + + [_mainMenu addItem:saveMenuItem]; + + var editMenuItem = [[CPMenuItem alloc] initWithTitle:@"Edit" action:nil keyEquivalent:@""], + editMenu = [[CPMenu alloc] initWithTitle:@"Edit"], + + undoMenuItem = [[CPMenuItem alloc] initWithTitle:@"Undo" action:@selector(undo:) keyEquivalent:CPUndoKeyEquivalent], + redoMenuItem = [[CPMenuItem alloc] initWithTitle:@"Redo" action:@selector(redo:) keyEquivalent:CPRedoKeyEquivalent]; + + [undoMenuItem setKeyEquivalentModifierMask:CPUndoKeyEquivalentModifierMask]; + [redoMenuItem setKeyEquivalentModifierMask:CPRedoKeyEquivalentModifierMask]; + + [editMenu addItem:undoMenuItem]; + [editMenu addItem:redoMenuItem]; + + [editMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Cut" action:@selector(cut:) keyEquivalent:@"X"]], + [editMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Copy" action:@selector(copy:) keyEquivalent:@"C"]], + [editMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Paste" action:@selector(paste:) keyEquivalent:@"V"]]; + + [editMenuItem setSubmenu:editMenu]; + [editMenuItem setHidden:YES]; + + [_mainMenu addItem:editMenuItem]; + + [_mainMenu addItem:[CPMenuItem separatorItem]]; + } + + return self; +} + +// Configuring Applications + +- (void)setDelegate:(id)aDelegate +{ + if (_delegate == aDelegate) + return; + + var defaultCenter = [CPNotificationCenter defaultCenter]; + + if (_delegate) + { + [defaultCenter + removeObesrver:_delegate + name:CPApplicationWillFinishLaunchingNotification + object:self]; + + [defaultCenter + removeObesrver:_delegate + name:CPApplicationDidFinishLaunchingNotification + object:self]; + } + + _delegate = aDelegate; + + if ([_delegate respondsToSelector:@selector(applicationWillFinishLaunching:)]) + [defaultCenter + addObserver:_delegate + selector:@selector(applicationWillFinishLaunching:) + name:CPApplicationWillFinishLaunchingNotification + object:self]; + + if ([_delegate respondsToSelector:@selector(applicationDidFinishLaunching:)]) + [defaultCenter + addObserver:_delegate + selector:@selector(applicationDidFinishLaunching:) + name:CPApplicationDidFinishLaunchingNotification + object:self]; +} + +- (id)delegate +{ + return _delegate; +} + +- (void)finishLaunching +{ + var bundle = [CPBundle mainBundle], + types = [bundle objectForInfoDictionaryKey:@"CPBundleDocumentTypes"]; + + if ([types count] > 0) + _documentController = [CPDocumentController sharedDocumentController]; + + var delegateClassName = [bundle objectForInfoDictionaryKey:@"CPApplicationDelegateClass"]; + + if (delegateClassName) + { + var delegateClass = objj_getClass(delegateClassName); + + if (delegateClass) + if ([_documentController class] == delegateClass) + [self setDelegate:_documentController]; + else + [self setDelegate:[[delegateClass alloc] init]]; + } + + var defaultCenter = [CPNotificationCenter defaultCenter]; + + [defaultCenter + postNotificationName:CPApplicationWillFinishLaunchingNotification + object:self]; + + if (_documentController) + [_documentController newDocument:self]; + + [defaultCenter + postNotificationName:CPApplicationDidFinishLaunchingNotification + object:self]; + + [[CPRunLoop currentRunLoop] performSelectors]; +} + +- (void)run +{ + [self finishLaunching]; +} + +// Managing the Event Loop + +- (void)runModalForWindow:(CPWindow)aWindow +{ + [self runModalSession:[self beginModalSessionForWindow:aWindow]]; +} + +- (void)stopModalWithCode:(int)aCode +{ + if (!_currentSession) + { + return; + // raise exception; + } + + _currentSession._state = aCode; + _currentSession = _currentSession._previous; + + if (aCode == CPRunAbortedResponse) + [self _removeRunModalLoop]; +} + +- (void)_removeRunModalLoop +{ + var count = _eventListeners.length; + + while (count--) + if (_eventListeners[count]._callback == _CPRunModalLoop) + { + _eventListeners.splice(count, 1); + + return; + } +} + +- (void)stopModal +{ + [self stopModalWithCode:CPRunStoppedResponse] +} + +- (void)abortModal +{ + [self stopModalWithCode:CPRunAbortedResponse]; +} + +- (CPModalSession)beginModalSessionForWindow:(CPWindow)aWindow +{ + return _CPModalSessionMake(aWindow, 0); +} + +- (void)runModalSession:(CPModalSession)aModalSession +{ + aModalSession._previous = _currentSession; + _currentSession = aModalSession; + + var theWindow = aModalSession._window; + + [theWindow center]; + [theWindow makeKeyAndOrderFront:self]; + +// [theWindow._bridge _obscureWindowsBelowModalWindow]; + + [CPApp setCallback:_CPRunModalLoop forNextEventMatchingMask:CPAnyEventMask untilDate:nil inMode:0 dequeue:NO]; +} + +- (CPWindow)modalWindow +{ + if (!_currentSession) + return nil; + + return _currentSession._window; +} + +- (BOOL)_handleKeyEquivalent:(CPEvent)anEvent +{ + if ([_mainMenu performKeyEquivalent:anEvent]) + return YES; + + return NO; +} + +- (void)sendEvent:(CPEvent)anEvent +{ + // Check if this is a candidate for key equivalent... + if ([anEvent type] == CPKeyDown && + [anEvent modifierFlags] & (CPCommandKeyMask | CPControlKeyMask) && + [[anEvent characters] length] > 0 && + [self _handleKeyEquivalent:anEvent]) + return; + + if (_eventListeners.length) + { + if (_eventListeners[_eventListeners.length - 1]._mask & (1 << [anEvent type])) + _eventListeners.pop()._callback(anEvent); + + return; + } + + [[anEvent window] sendEvent:anEvent]; +} + +- (void)doCommandBySelector:(SEL)aSelector +{ + if ([_delegate respondsToSelector:aSelector]) + [_delegate performSelector:aSelector]; + else + [super doCommandBySelector:aSelector]; +} + +- (CPWindow)keyWindow +{ + return _keyWindow; +} + +- (CPWindow)mainWindow +{ + return _mainWindow; +} + +- (CPWindow)windowWithWindowNumber:(int)aWindowNumber +{ + return _windows[aWindowNumber]; +} + +- (CPArray)windows +{ + return _windows; +} + +// Accessing the Main Menu + +- (CPMenu)mainMenu +{ + return _mainMenu; +} + +- (void)setMainMenu:(CPMenu)aMenu +{ + _mainMenu = aMenu; +} + +// Posting Actions + +- (BOOL)tryToPerform:(SEL)anAction with:(id)anObject +{ + if (!anAction) + return NO; + + if ([self tryToPerform:anAction with:anObject]) + return YES; + + if([_delegate respondsToSelector:aSelector]) + { + [_delegate performSelector:aSelector withObject:anObject]; + + return YES; + } + + return NO; +} + +- (BOOL)sendAction:(SEL)anAction to:(id)aTarget from:(id)aSender +{ + var target = [self targetForAction:anAction to:aTarget from:aSender]; + + if (!target) + return NO; + + [target performSelector:anAction withObject:aSender]; + + return YES; +} + +- (id)targetForAction:(SEL)anAction to:(id)aTarget from:(id)aSender +{ + if (!anAction) + return nil; + + if (aTarget) + return aTarget; + + return [self targetForAction:anAction]; +} + +- (id)_targetForWindow:(CPWindow)aWindow action:(SEL)anAction +{ + var responder = [aWindow firstResponder], + checkWindow = YES; + + while (responder) + { + if ([responder respondsToSelector:anAction]) + return responder; + + if (responder == aWindow) + checkWindow = NO; + + responder = [responder nextResponder]; + } + + if (checkWindow && [aWindow respondsToSelector:anAction]) + return aWindow; + + var delegate = [aWindow delegate]; + + if ([aWindow respondsToSelector:anAction]) + return delegate; + + var windowController = [aWindow windowController]; + + if ([windowController respondsToSelector:anAction]) + return windowController; + + var theDocument = [windowController document]; + + if (theDocument != delegate && [theDocument respondsToSelector:anAction]) + return theDocument; + + return nil; +} + +- (id)targetForAction:(SEL)anAction +{ + if (!anAction) + return nil; + + var target = [self _targetForWindow:[self keyWindow] action:anAction]; + + if (target) + return target; + + target = [self _targetForWindow:[self mainWindow] action:anAction]; + + if (target) + return target; + + if ([self respondsToSelector:anAction]) + return self; + + if ([_delegate respondsToSelector:anAction]) + return _delegate; + + if ([_documentController respondsToSelector:anAction]) + return _documentController; + + return nil; +} + +- (void)setCallback:(Function)aCallback forNextEventMatchingMask:(unsigned int)aMask untilDate:(CPDate)anExpiration inMode:(CPString)aMode dequeue:(BOOL)shouldDequeue +{ + _eventListeners.push(_CPEventListenerMake(aMask, aCallback)); + + if (_eventListeners.length == 3) objj_debug_print_backtrace(); +} + +- (CPEvent)setTarget:(id)aTarget selector:(SEL)aSelector forNextEventMatchingMask:(unsigned int)aMask untilDate:(CPDate)anExpiration inMode:(CPString)aMode dequeue:(BOOL)shouldDequeue +{ + _eventListeners.push(_CPEventListenerMake(aMask, function (anEvent) { objj_msgSend(aTarget, aSelector, anEvent); })); +} + +// Managing Sheets + +- (void)beginSheet:(CPWindow)aSheet modalForWindow:(CPWindow)aWindow modalDelegate:(id)aModalDelegate didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo +{ + [aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:aDidEndSelector contextInfo:aContextInfo]; +} + +- (CPArray)arguments +{ + return _args; +} + +- (CPDictionary)namedArguments +{ + return _namedArgs; +} + +@end + +var _CPModalSessionMake = function(aWindow, aStopCode) +{ + return { _window:aWindow, _state:CPRunContinuesResponse , _previous:nil }; +} + +var _CPEventListenerMake = function(anEventMask, aCallback) +{ + return { _mask:anEventMask, _callback:aCallback }; +} + +var _CPRunModalLoop = function(anEvent) +{ + [CPApp setCallback:_CPRunModalLoop forNextEventMatchingMask:CPAnyEventMask untilDate:nil inMode:0 dequeue:NO]; + + // FIXME: abortModal from event loop? + var theWindow = [anEvent window], + modalSession = CPApp._currentSession; + + if (theWindow == modalSession._window || [theWindow worksWhenModal]) + [theWindow sendEvent:anEvent]; + /*else + [[session modalWindow] makeKeyAndOrderFront:]*/ + + if (modalSession._state != CPRunContinuesResponse) + [CPApp _removeRunModalLoop]; +} + +function CPApplicationMain(args, namedArgs) +{ + var mainBundle = [CPBundle mainBundle], + principalClass = [mainBundle principalClass]; + + if (!principalClass) + principalClass = [CPApplication class]; + + [principalClass sharedApplication]; + + //[NSBundle loadNibNamed:@"myMain" owner:NSApp]; + + //FIXME? + CPApp._args = args; + CPApp._namedArgs = namedArgs; + + [CPApp run]; +} diff --git a/AppKit/CPButton.j b/AppKit/CPButton.j new file mode 100644 index 000000000..5a4f1ed91 --- /dev/null +++ b/AppKit/CPButton.j @@ -0,0 +1,604 @@ +/* + * CPButton.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "_CPImageAndTitleView.j" +import "CGGeometry.j" + +import "CPControl.j" + +#include "CoreGraphics/CGGeometry.h" + + +CPScaleProportionally = 0; +CPScaleToFit = 1; +CPScaleNone = 2; + +CPNoImage = 0; +CPImageOnly = 1; +CPImageLeft = 2; +CPImageRight = 3; +CPImageBelow = 4; +CPImageAbove = 5; +CPImageOverlaps = 6; + +CPOnState = 1; +CPOffState = 0; +CPMixedState = -1; + +CPRoundedBezelStyle = 1; +CPRegularSquareBezelStyle = 2; +CPThickSquareBezelStyle = 3; +CPThickerSquareBezelStyle = 4; +CPDisclosureBezelStyle = 5; +CPShadowlessSquareBezelStyle = 6; +CPCircularBezelStyle = 7; +CPTexturedSquareBezelStyle = 8; +CPHelpButtonBezelStyle = 9; +CPSmallSquareBezelStyle = 10; +CPTexturedRoundedBezelStyle = 11; +CPRoundRectBezelStyle = 12; +CPRecessedBezelStyle = 13; +CPRoundedDisclosureBezelStyle = 14; +CPHUDBezelStyle = -1; + +CPMomentaryLightButton = 0; +CPPushOnPushOffButton = 1; +CPToggleButton = 2; +CPSwitchButton = 3; +CPRadioButton = 4; +CPMomentaryChangeButton = 5; +CPOnOffButton = 6; +CPMomentaryPushInButton = 7; +CPMomentaryPushButton = 0; +CPMomentaryLight = 7; + + +var CPHUDBezelStyleTextColor = nil; + +var _CPButtonClassName = nil, + _CPButtonBezelStyleSizes = {}, + _CPButtonBezelStyleIdentifiers = {}, + _CPButtonBezelStyleHighlightedIdentifier = @"Highlighted"; + +@implementation CPButton : CPControl +{ + int _tag; + int _state; + BOOL _allowsMixedState; + BOOL _isHighlighted; + + CPImage _image; + CPImage _alternateImage; + + CPCellImagePosition _imagePosition; + CPImageScaling _imageScalng; + + CPString _title; + CPString _alternateTitle; + + CPBezelStyle _bezelStyle; + BOOL _isBordered; + CPControlSize _controlSize; + + BOOL _bezelBorderNeedsUpdate; + + _CPImageAndTitleView _imageAndTitleView; +} + ++ (void)initialize +{ + if (self != [CPButton class]) + return; + + _CPButtonClassName = [CPButton className]; + + // Textured Rounded + _CPButtonBezelStyleIdentifiers[CPRoundedBezelStyle] = @"Rounded"; + _CPButtonBezelStyleIdentifiers[CPRegularSquareBezelStyle] = @"RegularSquare"; + _CPButtonBezelStyleIdentifiers[CPThickSquareBezelStyle] = @"ThickSquare"; + _CPButtonBezelStyleIdentifiers[CPThickerSquareBezelStyle] = @"ThickerSquare"; + _CPButtonBezelStyleIdentifiers[CPDisclosureBezelStyle] = @"Disclosure"; + _CPButtonBezelStyleIdentifiers[CPShadowlessSquareBezelStyle] = @"ShadowlessSquare"; + _CPButtonBezelStyleIdentifiers[CPCircularBezelStyle] = @"Circular"; + _CPButtonBezelStyleIdentifiers[CPTexturedSquareBezelStyle] = @"TexturedSquare"; + _CPButtonBezelStyleIdentifiers[CPHelpButtonBezelStyle] = @"HelpButton"; + _CPButtonBezelStyleIdentifiers[CPSmallSquareBezelStyle] = @"SmallSquare"; + _CPButtonBezelStyleIdentifiers[CPTexturedRoundedBezelStyle] = @"TexturedRounded"; + _CPButtonBezelStyleIdentifiers[CPRoundRectBezelStyle] = @"RoundRect"; + _CPButtonBezelStyleIdentifiers[CPRecessedBezelStyle] = @"Recessed"; + _CPButtonBezelStyleIdentifiers[CPRoundedDisclosureBezelStyle] = @"RoundedDisclosure"; + _CPButtonBezelStyleIdentifiers[CPHUDBezelStyle] = @"HUD"; + + var regularIdentifier = _CPControlIdentifierForControlSize(CPRegularControlSize), + smallIdentifier = _CPControlIdentifierForControlSize(CPSmallControlSize), + miniIdentifier = _CPControlIdentifierForControlSize(CPMiniControlSize); + + // Rounded Rect + var prefix = _CPButtonClassName + _CPButtonBezelStyleIdentifiers[CPRoundRectBezelStyle]; + + _CPButtonBezelStyleSizes[prefix + regularIdentifier] = [_CGSizeMake(10.0, 18.0), _CGSizeMake(1.0, 18.0), _CGSizeMake(10.0, 18.0)]; + _CPButtonBezelStyleSizes[prefix + regularIdentifier + _CPButtonBezelStyleHighlightedIdentifier] = [_CGSizeMake(10.0, 18.0), _CGSizeMake(1.0, 18.0), _CGSizeMake(10.0, 18.0)]; + + // HUD + var prefix = _CPButtonClassName + _CPButtonBezelStyleIdentifiers[CPHUDBezelStyle]; + + _CPButtonBezelStyleSizes[prefix + regularIdentifier] = [_CGSizeMake(13.0, 20.0), _CGSizeMake(1.0, 20.0), _CGSizeMake(13.0, 20.0)]; + _CPButtonBezelStyleSizes[prefix + regularIdentifier + _CPButtonBezelStyleHighlightedIdentifier] = [_CGSizeMake(13.0, 20.0), _CGSizeMake(1.0, 20.0), _CGSizeMake(13.0, 20.0)]; + + CPHUDBezelStyleTextColor = [CPColor whiteColor]; + + // Textured Rounded + var prefix = _CPButtonClassName + _CPButtonBezelStyleIdentifiers[CPTexturedRoundedBezelStyle]; + + _CPButtonBezelStyleSizes[prefix + regularIdentifier] = [_CGSizeMake(7.0, 20.0), _CGSizeMake(1.0, 20.0), _CGSizeMake(7.0, 20.0)]; + _CPButtonBezelStyleSizes[prefix + regularIdentifier + _CPButtonBezelStyleHighlightedIdentifier] = [_CGSizeMake(7.0, 20.0), _CGSizeMake(1.0, 20.0), _CGSizeMake(7.0, 20.0)]; +} + +// Configuring Buttons + +- (void)setButtonType:(CPButtonType)aButtonType +{ + if (aButtonType == CPSwitchButton) + { + [self setBordered:NO]; + [self setImage:nil]; + [self setAlternateImage:nil]; + [self setAlignment:CPLeftTextAlignment]; + } +} + +- (id)initWithFrame:(CPRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _imagePosition = CPNoImage; + _imageScaling = CPScaleNone; + + _controlSize = CPRegularControlSize; + + [self setBezelStyle:CPRoundRectBezelStyle]; + [self setBordered:YES]; + + [self setAlignment:CPCenterTextAlignment]; + } + + return self; +} + +- (void)setImagePosition:(CPCellImagePosition)anImagePosition +{ + if (_imagePosition == anImagePosition) + return; + + _imagePosition = anImagePosition; + + [self drawContentsWithHighlight:_isHighlighted]; +} + +- (CPCellImagePosition)imagePosition +{ + return _imagePosition; +} + +- (void)setImageScaling:(CPImageScaling)anImageScaling +{ + if (_imageScaling == anImageScaling) + return; + + _imageScaling = anImageScaling; + + [self drawContentsWithHighlight:_isHighlighted]; +} + +- (CPImageScaling)imageScaling +{ + return _imageScaling; +} + +- (void)setTextColor:(CPColor)aColor +{ + [super setTextColor:aColor]; + + [self drawContentsWithHighlight:_isHighlighted]; +} + +- (void)setFont:(CPFont)aFont +{ + [super setFont:aFont]; + + [self drawContentsWithHighlight:_isHighlighted]; +} + +// Setting the state + +- (BOOL)allowsMixedState +{ + return _allowsMixedState; +} + +- (void)setAllowsMixedState:(BOOL)aFlag +{ + _allowsMixedState = aFlag; +} + +- (void)setNextState +{ + if (_state == CPOffState) + _state = CPOnState; + else + _state = (_state >= CPOnState && _allowsMixedState) ? CPMixedState : CPOffState; +} + +- (void)setState:(int)aState +{ + _state = aState; +} + +- (int)state +{ + return _state; +} + +- (void)setAlignment:(CPTextAlignment)anAlignment +{ + [super setAlignment:anAlignment]; + + [self drawContentsWithHighlight:_isHighlighted]; +} + +- (void)setImage:(CPImage)anImage +{ + if (_image == anImage) + return; + + _image = anImage; + + [self drawContentsWithHighlight:_isHighlighted]; +} + +- (CPImage)image +{ + return _image; +} + +- (void)setAlternateImage:(CPImage)anImage +{ + _alternateImage = anImage; +} + +- (CPImage)alternateImage +{ + return _alternateImage; +} + +- (void)setTitle:(CPString)aTitle +{ + if (_title == aTitle) + return; + + _title = aTitle; + + [self drawContentsWithHighlight:_isHighlighted]; +} + +- (CPString)title +{ + return _title; +} + +- (void)tile +{ + var size = [self bounds].size; + + if (_isBordered) + { + var imageAndTitleSize = CGSizeMakeCopy(size); + + if (_bezelStyle == CPHUDBezelStyle) + imageAndTitleSize.height -= 4.0; + else if (_bezelStyle == CPRoundRectBezelStyle) + imageAndTitleSize.height -= 2.0; + else if (_bezelStyle == CPTexturedRoundedBezelStyle) + imageAndTitleSize.height -= 2.0; + + [_imageAndTitleView setFrameSize:imageAndTitleSize]; + } + else + [_imageAndTitleView setFrameSize:size]; +} + +- (void)sizeToFit +{ + [_imageAndTitleView sizeToFit]; + + var frame = [_imageAndTitleView frame], + height = CGRectGetHeight(frame); + /* + if (_isBordered) + if (_bezelStyle == CPHUDBezelStyle) + height += 2.0; + else if (_bezelStyle == CPRoundRectBezelStyle) + height += 1.0; + else if (_bezelStyle == CPTexturedRoundedBezelStyle) + height += 2.0; + */ + [self setFrameSize:CGSizeMake(CGRectGetWidth(frame), height)]; +} + +- (void)setFrameSize:(CPSize)aSize +{ + [super setFrameSize:aSize]; + + [self tile]; +} + +- (void)highlight:(BOOL)aFlag +{ + [self drawBezelWithHighlight:aFlag]; + [self drawContentsWithHighlight:aFlag]; +} + +- (void)setTag:(int)aTag +{ + _tag = aTag; +} + +- (int)tag +{ + return _tag; +} + +- (void)mouseDown:(CPEvent)anEvent +{ + _isHighlighted = YES; + + [self highlight:_isHighlighted]; +} + +- (void)mouseDragged:(CPEvent)anEvent +{ + _isHighlighted = CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil]); + + [self highlight:_isHighlighted]; +} + +- (void)mouseUp:(CPEvent)anEvent +{ + _isHighlighted = NO; + + [self highlight:_isHighlighted]; + + [super mouseUp:anEvent]; +} + +// FIXME: This probably belongs in CPControl. +- (void)setControlSize:(CPControlSize)aControlSize +{ + if (_controlSize == aControlSize) + return; + + _controlSize = aControlSize; + + [self drawBezelWithHighlight:_isHighlighted]; + [self _updateTextAttributes]; +} + +- (CPControlSize)controlSize +{ + return _controlSize; +} + +- (void)setBordered:(BOOL)isBordered +{ + if (_isBordered == isBordered) + return; + + _isBordered = isBordered; + + [self updateBackgroundColors]; + [self drawBezelWithHighlight:_isHighlighted]; + + [self tile]; +} + +- (BOOL)isBordered +{ + return _isBordered; +} + +- (void)setBezelStyle:(CPBezelStyle)aBezelStyle +{ + // FIXME: We need real support for these: + if (aBezelStyle == CPRoundedBezelStyle || + aBezelStyle == CPRoundedBezelStyle || + aBezelStyle == CPRegularSquareBezelStyle || + aBezelStyle == CPThickSquareBezelStyle || + aBezelStyle == CPThickerSquareBezelStyle || + aBezelStyle == CPDisclosureBezelStyle || + aBezelStyle == CPShadowlessSquareBezelStyle || + aBezelStyle == CPCircularBezelStyle || + aBezelStyle == CPTexturedSquareBezelStyle || + aBezelStyle == CPHelpButtonBezelStyle || + aBezelStyle == CPSmallSquareBezelStyle || + aBezelStyle == CPRecessedBezelStyle || + aBezelStyle == CPRoundedDisclosureBezelStyle) + aBezelStyle = CPRoundRectBezelStyle; + + if (_bezelStyle == aBezelStyle) + return; + + _bezelStyle = aBezelStyle; + + [self updateBackgroundColors]; + [self drawBezelWithHighlight:_isHighlighted]; + + [self _updateTextAttributes]; + [self tile]; +} + +- (int)bezelStyle +{ + return _bezelStyle; +} + +- (void)updateBackgroundColors +{ + if (_isBordered) + { + [self setBackgroundColor:_CPControlThreePartImagePattern( + NO, + _CPButtonBezelStyleSizes, + _CPButtonClassName, + _CPButtonBezelStyleIdentifiers[_bezelStyle], + _CPControlIdentifierForControlSize(_controlSize)) forName:CPControlNormalBackgroundColor]; + + [self setBackgroundColor:_CPControlThreePartImagePattern( + NO, + _CPButtonBezelStyleSizes, + _CPButtonClassName, + _CPButtonBezelStyleIdentifiers[_bezelStyle], + _CPControlIdentifierForControlSize(_controlSize), + _CPButtonBezelStyleHighlightedIdentifier) forName:CPControlHighlightedBackgroundColor]; + } + else + { + [self setBackgroundColor:nil forName:CPControlNormalBackgroundColor]; + [self setBackgroundColor:nil forName:CPControlHighlightedBackgroundColor]; + } +} + +- (void)drawBezelWithHighlight:(BOOL)shouldHighlight +{ + _bezelBorderNeedsUpdate = ![self window]; + + if (_bezelBorderNeedsUpdate) + return; + + [self setBackgroundColorWithName:shouldHighlight ? CPControlHighlightedBackgroundColor : CPControlNormalBackgroundColor]; +} + +- (void)drawContentsWithHighlight:(BOOL)isHighlighted +{ + if (!_title && !_image && !_alternateTitle && !_alternateImage && !_imageAndTitleView) + return; + + if (!_imageAndTitleView) + { + _imageAndTitleView = [[_CPImageAndTitleView alloc] initWithFrame:[self bounds]]; + + [self addSubview:_imageAndTitleView]; + + [self tile]; + } + + [_imageAndTitleView setFont:[self font]]; + [_imageAndTitleView setTextColor:[self textColor]]; + [_imageAndTitleView setAlignment:[self alignment]]; + [_imageAndTitleView setImagePosition:_imagePosition]; + [_imageAndTitleView setImageScaling:_imageScaling]; + + [_imageAndTitleView setTitle:isHighlighted && _alternateTitle ? _alternateTitle : _title]; + [_imageAndTitleView setImage:isHighlighted && _alternateImage ? _alternateImage : _image]; +} + +- (void)viewDidMoveToWindow +{ + if (_bezelBorderNeedsUpdate) + [self drawBezelWithHighlight:_isHighlighted]; +} + +- (void)_updateTextAttributes +{ + if (_bezelStyle == CPHUDBezelStyle) + [self setTextColor:CPHUDBezelStyleTextColor]; + + if (_controlSize == CPRegularControlSize) + [self setFont:[CPFont systemFontOfSize:11.0]]; +} + +@end + + +var CPButtonImageKey = @"CPButtonImageKey", + CPButtonAlternateImageKey = @"CPButtonAlternateImageKey", + CPButtonTitleKey = @"CPButtonTitleKey", + CPButtonAlteranteTitleKey = @"CPButtonAlternateTitleKey", + CPButtonImageAndTitleViewKey = @"CPButtonImageAndTitleViewKey", + CPButtonImagePositionKey = @"CPButtonImagePositionKey", + CPButtonImageScalingKey = @"CPButtonImageScalingKey", + CPButtonIsBorderedKey = @"CPButtonIsBorderedKey", + CPButtonBezelStyleKey = @"CPButtonBezelStyleKey", + CPButtonImageAndTitleViewKey = @"CPButtonImageAndTitleViewKey"; + +@implementation CPButton (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super initWithCoder:aCoder]; + + if (self) + { + _controlSize = CPRegularControlSize; + + [self setImage:[aCoder decodeObjectForKey:CPButtonImageKey]]; + [self setAlternateImage:[aCoder decodeObjectForKey:CPButtonAlternateImageKey]]; + + [self setTitle:[aCoder decodeObjectForKey:CPButtonTitleKey]]; + + [self setImagePosition:[aCoder decodeIntForKey:CPButtonImagePositionKey]]; + [self setImageScaling:[aCoder decodeIntForKey:CPButtonImageScalingKey]]; + + [self setBezelStyle:[aCoder decodeIntForKey:CPButtonBezelStyleKey]]; + [self setBordered:[aCoder decodeBoolForKey:CPButtonIsBorderedKey]]; + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + // We do this in order to avoid encoding the _imageAndTitleView, which + // should just automatically be created programmatically as needed. + var actualSubviews = _subviews; + + _subviews = [_subviews copy]; + [_subviews removeObjectIdenticalTo:_imageAndTitleView]; + + [super encodeWithCoder:aCoder]; + + _subviews = actualSubviews; + + [aCoder encodeObject:_image forKey:CPButtonImageKey]; + [aCoder encodeObject:_alternateImage forKey:CPButtonAlternateImageKey]; + + [aCoder encodeObject:_title forKey:CPButtonTitleKey]; + + [aCoder encodeInt:_imagePosition forKey:CPButtonImagePositionKey]; + [aCoder encodeInt:_imageScaling forKey:CPButtonImageScalingKey]; + + [aCoder encodeBool:_isBordered forKey:CPButtonIsBorderedKey]; + [aCoder encodeInt:_bezelStyle forKey:CPButtonBezelStyleKey]; +} + +@end diff --git a/AppKit/CPClipView.j b/AppKit/CPClipView.j new file mode 100644 index 000000000..f32acecd8 --- /dev/null +++ b/AppKit/CPClipView.j @@ -0,0 +1,130 @@ +/* + * CPClipView.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPView.j" + +#include "CoreGraphics/CGGeometry.h" + + +@implementation CPClipView : CPView +{ + CPView _documentView; +} + +- (void)setDocumentView:(CPView)aView +{ + if (_documentView == aView) + return; + + var defaultCenter = [CPNotificationCenter defaultCenter]; + + if (_documentView) + { + [defaultCenter + removeObserver:self + name:CPViewFrameDidChangeNotification + object:_documentView]; + + [defaultCenter + removeObserver:self + name:CPViewBoundsDidChangeNotification + object:_documentView]; + + [_documentView removeFromSuperview]; + } + + _documentView = aView; + + if (_documentView) + { + // FIXME: remove when bounds. + [_documentView setFrameOrigin:CGPointMake(0.0, 0.0)]; + + [self addSubview:_documentView]; + + [_documentView setPostsFrameChangedNotifications:YES]; + [_documentView setPostsBoundsChangedNotifications:YES]; + + [defaultCenter + addObserver:self + selector:@selector(viewFrameChanged:) + name:CPViewFrameDidChangeNotification + object:_documentView]; + + [defaultCenter + addObserver:self + selector:@selector(viewBoundsChanged:) + name:CPViewBoundsDidChangeNotification + object:_documentView]; + } +} + +- (id)documentView +{ + return _documentView; +} + +- (CGPoint)constrainScrollPoint:(CGPoint)aPoint +{ + var documentFrame = [_documentView frame]; + + aPoint.x = MAX(0.0, MIN(aPoint.x, MAX(_CGRectGetWidth(documentFrame) - _CGRectGetWidth(_bounds), 0.0))); + aPoint.y = MAX(0.0, MIN(aPoint.y, MAX(_CGRectGetHeight(documentFrame) - _CGRectGetHeight(_bounds), 0.0))); + + return aPoint; +} + +- (void)setBoundsOrigin:(CGPoint)aPoint +{ + if (_CGPointEqualToPoint(_bounds.origin, aPoint)) + return; + + [super setBoundsOrigin:aPoint]; + + var superview = [self superview]; + + if([superview isKindOfClass:[CPScrollView class]]) + [superview reflectScrolledClipView:self]; +} + +- (void)scrollToPoint:(CPPoint)aPoint +{ + [self setBoundsOrigin:[self constrainScrollPoint:aPoint]]; +} + +- (void)viewBoundsChanged:(CPNotification)aNotification +{ + var superview = [self superview]; + + if([superview isKindOfClass:[CPScrollView class]]) + [superview reflectScrolledClipView:self]; +} + +- (void)viewFrameChanged:(CPNotification)aNotification +{ + var superview = [self superview]; + + if([superview isKindOfClass:[CPScrollView class]]) + [superview reflectScrolledClipView:self]; +} + +@end diff --git a/AppKit/CPCollectionView.j b/AppKit/CPCollectionView.j new file mode 100644 index 000000000..111369a75 --- /dev/null +++ b/AppKit/CPCollectionView.j @@ -0,0 +1,546 @@ +/* + * CPCollectionView.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import +import +import +import + +import + + +@implementation CPCollectionView : CPView +{ + CPArray _content; + CPArray _items; + + CPData _itemData; + CPCollectionViewItem _itemPrototype; + CPCollectionViewItem _itemForDragging; + CPMutableArray _cachedItems; + + unsigned _maxNumberOfRows; + unsigned _maxNumberOfColumns; + + CGSize _minItemSize; + CGSize _maxItemSize; + + float _tileWidth; + + BOOL _isSelectable; + BOOL _allowsMultipleSelection; + CPIndexSet _selectionIndexes; + + CGSize _itemSize; + + float _horizontalMargin; + float _verticalMargin; + + unsigned _numberOfRows; + unsigned _numberOfColumns; + + id _delegate; +} + +- (id)initWithFrame:(CGRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _items = []; + _content = []; + + _cachedItems = []; + + _itemSize = CGSizeMakeZero(); + _minItemSize = CGSizeMakeZero(); + _maxItemSize = CGSizeMakeZero(); + + _verticalMargin = 5.0; + _tileWidth = -1.0; + + _selectionIndexes = [CPIndexSet indexSet]; + } + + return self; +} + +- (void)setItemPrototype:(CPCollectionViewItem)anItem +{ + _itemData = [CPKeyedArchiver archivedDataWithRootObject:anItem]; + _itemForDragging = anItem//[CPKeyedUnarchiver unarchiveObjectWithData:_itemData]; + + [self reloadContent]; +} + +- (CPCollectionViewItem)itemPrototype +{ + return _itemPrototype; +} + +- (CPCollectionViewItem)newItemForRepresentedObject:(id)anObject +{ + var item = nil; + + if (_cachedItems.length) + item = _cachedItems.pop(); + else + item = [CPKeyedUnarchiver unarchiveObjectWithData:_itemData]; + + [item setRepresentedObject:anObject]; + [[item view] setFrameSize:_itemSize]; + + return item; +} + +// Working with the Responder Chain + +- (BOOL)acceptsFirstResponder +{ + return YES; +} + +- (BOOL)isFirstResponder +{ + return [[self window] firstResponder] == self; +} + +// Setting the Content + +- (void)setContent:(CPArray)anArray +{ + if (_content == anArray) + return; + + _content = anArray; + + [self reloadContent]; +} + +- (CPArray)content +{ + return _content; +} + +- (CPArray)items +{ + return _items; +} + +// Setting the Selection Mode + +- (void)setSelectable:(BOOL)isSelectable +{ + if (_isSelectable == isSelectable) + return; + + _isSelectable = isSelectable; + + if (!_isSelectable) + { + var index = CPNotFound; + + while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound) + [_items[index] setSelected:NO]; + } +} + +- (BOOL)isSelected +{ + return _isSelected; +} + +- (void)setAllowsMultipleSelection:(BOOL)shouldAllowMultipleSelection +{ + _allowsMultipleSelection = shouldAllowsMultipleSelection; +} + +- (BOOL)allowsMultipleSelection +{ + return _allowsMultipleSelection; +} + +- (void)setSelectionIndexes:(CPIndexSet)anIndexSet +{ + if (_selectionIndexes == anIndexSet) + return; + + var index = CPNotFound; + + while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound) + [_items[index] setSelected:NO]; + + _selectionIndexes = anIndexSet; + + var index = CPNotFound; + + while ((index = [_selectionIndexes indexGreaterThanIndex:index]) != CPNotFound) + [_items[index] setSelected:YES]; + + if ([_delegate respondsToSelector:@selector(collectionViewDidChangeSelection:)]) + [_delegate collectionViewDidChangeSelection:self] +} + +- (CPIndexSet)selectionIndexes +{ + return _selectionIndexes; +} + +- (void)reloadContent +{ + // Remove current views + var count = _items.length; + + while (count--) + { + [[_items[count] view] removeFromSuperview]; + _cachedItems.push(_items[count]); + } + + _items = []; + + if (!_itemData || !_content) + return; + + var index = 0; + + count = _content.length; + + for (; index < count; ++index) + { + _items.push([self newItemForRepresentedObject:_content[index]]); + + [self addSubview:[_items[index] view]]; + } + + [self tile]; +} + +- (void)tile +{ + var width = CGRectGetWidth([self bounds]); + + if (![_content count] || width == _tileWidth) + return; + + // We try to fit as many views per row as possible. Any remaining space is then + // either proportioned out to the views (if their minSize != maxSize) or used as + // margin + var itemSize = CGSizeMakeCopy(_minItemSize); + + _numberOfColumns = MAX(1.0, FLOOR(width / itemSize.width)); + + if (_maxNumberOfColumns > 0) + _numberOfColumns = MIN(_maxNumberOfColumns, _numberOfColumns); + + var remaining = width - _numberOfColumns * itemSize.width, + itemsNeedSizeUpdate = NO; + + if (remaining > 0 && itemSize.width < _maxItemSize.width) + itemSize.width = MIN(_maxItemSize.width, itemSize.width + FLOOR(remaining / _numberOfColumns)); + + if (!CGSizeEqualToSize(_itemSize, itemSize)) + { + _itemSize = itemSize; + itemsNeedSizeUpdate = YES; + } + + var index = 0, + count = _items.length; + + if (_maxNumberOfColumns > 0 && _maxNumberOfRows > 0) + count = MIN(count, _maxNumberOfColumns * _maxNumberOfRows); + + _numberOfRows = CEIL(count / _numberOfColumns); + + _horizontalMargin = FLOOR((width - _numberOfColumns * itemSize.width) / (_numberOfColumns + 1)); + + var x = _horizontalMargin, + y = -itemSize.height; + + for (; index < count; ++index) + { + if (index % _numberOfColumns == 0) + { + x = _horizontalMargin; + y += _verticalMargin + itemSize.height; + } + + var view = [_items[index] view]; + + [view setFrameOrigin:CGPointMake(x, y)]; + + if (itemsNeedSizeUpdate) + [view setFrameSize:_itemSize]; + + x += itemSize.width + _horizontalMargin; + } + + _tileWidth = width; + [self setFrameSize:CGSizeMake(width, y + itemSize.height + _verticalMargin)]; + _tileWidth = -1.0; +} + +- (void)resizeSubviewsWithOldSize:(CGSize)aSize +{ + [self tile]; +} + +// Laying Out the Collection View + +- (void)setMaxNumberOfRows:(unsigned)aMaxNumberOfRows +{ + if (_maxNumberOfRows == aMaxNumberOfRows) + return; + + _maxNumberOfRows = aMaxNumberOfRows; + + [self tile]; +} + +- (unsigned)maxNumberOfRows +{ + return _maxNumberOfRows; +} + +- (void)setMaxNumberOfColumns:(unsigned)aMaxNumberOfColumns +{ + if (_maxNumberOfColumns == aMaxNumberOfColumns) + return; + + _maxNumberOfColumns = aMaxNumberOfColumns; + + [self tile]; +} + +- (unsigned)maxNumberOfColumns +{ + return _maxNumberOfColumns; +} + +- (void)setMinItemSize:(CGSize)aSize +{ + if (CGSizeEqualToSize(_minItemSize, aSize)) + return; + + _minItemSize = CGSizeMakeCopy(aSize); + + [self tile]; +} + +- (CGSize)minItemSize +{ + return _minItemSize; +} + +- (void)setMaxItemSize:(CGSize)aSize +{ + if (CGSizeEqualToSize(_maxItemSize, aSize)) + return; + + _maxItemSize = CGSizeMakeCopy(aSize); + + [self tile]; +} + +- (CGSize)maxItemSize +{ + return _maxItemSize; +} + +- (void)mouseUp:(CPEvent)anEvent +{ + if ([_selectionIndexes count] && [anEvent clickCount] == 2 && [_delegate respondsToSelector:@selector(collectionView:didDoubleClickOnItemAtIndex:)]) + [_delegate collectionView:self didDoubleClickOnItemAtIndex:[_selectionIndexes firstIndex]]; +} + +- (void)mouseDown:(CPEvent)anEvent +{ + var location = [self convertPoint:[anEvent locationInWindow] fromView:nil], + row = FLOOR(location.y / (_itemSize.height + _verticalMargin)), + column = FLOOR(location.x / (_itemSize.width + _horizontalMargin)), + index = row * _numberOfColumns + column; + + if (index >= 0 && index < _items.length) + [self setSelectionIndexes:[CPIndexSet indexSetWithIndex:index]]; +} + +- (void)mouseDragged:(CPEvent)anEvent +{ + if (![_delegate respondsToSelector:@selector(collectionView:dragTypesForItemsAtIndexes:)]) + return; + + // If we don't have any selected items, we've clicked away, and thus the drag is meaningless. + if (![_selectionIndexes count]) + return; + + // Set up the pasteboard + var dragTypes = [_delegate collectionView:self dragTypesForItemsAtIndexes:_selectionIndexes]; + + [[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:dragTypes owner:self]; + + var point = [self convertPoint:[anEvent locationInWindow] fromView:nil]; + + [_itemForDragging setRepresentedObject:_content[[_selectionIndexes firstIndex]]]; + + var view = [_itemForDragging view], + frame = [view frame]; + + [view setFrameSize:_itemSize]; + + [self dragView:view + at:[[_items[[_selectionIndexes firstIndex]] view] frame].origin + offset:CGPointMakeZero() + event:anEvent + pasteboard:nil + source:self + slideBack:YES]; +} + +- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType +{ + [aPasteboard setData:[_delegate collectionView:self dataForItemsAtIndexes:_selectionIndexes forType:aType] forType:aType]; +} + +// Cappuccino Additions + +- (void)setVerticalMargin:(float)aVerticalMargin +{ + if (_verticalMargin == aVerticalMargin) + return; + + _verticalMargin = aVerticalMargin; + + [self tile]; +} + +- (void)setDelegate:(id)aDelegate +{ + _delegate = aDelegate; +} + +- (id)delegate +{ + return _delegate; +} + +@end + +@implementation CPCollectionViewItem : CPObject +{ + id _representedObject; + + CPView _view; + + BOOL _isSelected; +} + +// Setting the Represented Object + +- (void)setRepresentedObject:(id)anObject +{ + if (_representedObject == anObject) + return; + + _representedObject = anObject; + + // FIXME: This should be set up by bindings + [_view setRepresentedObject:anObject]; +} + +- (id)representedObject +{ + return _representedObject; +} + +// Modifying the View + +- (void)setView:(CPView)aView +{ + _view = aView; +} + +- (CPView)view +{ + return _view; +} + +// Modifying the Selection + +- (void)setSelected:(BOOL)shouldBeSelected +{ + if (_isSelected == shouldBeSelected) + return; + + _isSelected = shouldBeSelected; + + // FIXME: This should be set up by bindings + [_view setSelected:_isSelected]; +} + +- (BOOL)isSelected +{ + return _isSelected; +} + +// Parent Collection View + +- (CPCollectionView)collectionView +{ + return [_view superview]; +} + +@end + +var CPCollectionViewItemViewKey = @"CPCollectionViewItemViewKey"; + +@implementation CPCollectionViewItem (CPCoding) + +- (id)copy +{ + +} + +@end + +var CPCollectionViewItemViewKey = @"CPCollectionViewItemViewKey"; + +@implementation CPCollectionViewItem (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super init]; + + if (self) + _view = [aCoder decodeObjectForKey:CPCollectionViewItemViewKey]; + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeObject:_view forKey:CPCollectionViewItemViewKey]; +} + +@end diff --git a/AppKit/CPColor.j b/AppKit/CPColor.j new file mode 100644 index 000000000..dd8894192 --- /dev/null +++ b/AppKit/CPColor.j @@ -0,0 +1,394 @@ +/* + * CPColor.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + +import "CGColor.j" + +import "CPCompatibility.j" +import "CPImage.j" + +var _redComponent = 0, + _greenComponent = 1, + _blueComponent = 2, + _alphaCompnent = 3; + +var _hueComponent = 0, + _saturationComponent = 1, + _brightnessComponent = 2; + +@implementation CPColor : CPObject +{ + CPArray _components; + + CPImage _patternImage; + CPString _cssString; +} + ++ (CPColor)colorWithCalibratedRed:(float)red green:(float)green blue:(float)blue alpha:(float)alpha +{ + return [[CPColor alloc] _initWithRGBA:[red, green, blue, alpha]]; +} + ++ (CPColor)colorWithCalibratedWhite:(float)white alpha:(float)alpha +{ + return [[CPColor alloc] _initWithRGBA:[white, white, white, alpha]]; +} + ++ (CPColor)colorWithHue:(float)hue saturation:(float)saturation brightness:(float)brightness +{ + if(saturation == 0.0) + return [CPColor colorWithCalibratedWhite: brightness/100.0 alpha: 1.0]; + + var f = hue % 60, + p = (brightness * (100 - saturation)) / 10000, + q = (brightness * (6000 - saturation * f)) / 600000, + t = (brightness * (6000 - saturation * (60 -f))) / 600000, + b = brightness / 100.0; + + switch(FLOOR(hue / 60)) + { + case 0: return [CPColor colorWithCalibratedRed: b green: t blue: p alpha: 1.0]; + case 1: return [CPColor colorWithCalibratedRed: q green: b blue: p alpha: 1.0]; + case 2: return [CPColor colorWithCalibratedRed: p green: b blue: t alpha: 1.0]; + case 3: return [CPColor colorWithCalibratedRed: p green: q blue: b alpha: 1.0]; + case 4: return [CPColor colorWithCalibratedRed: t green: p blue: b alpha: 1.0]; + case 5: return [CPColor colorWithCalibratedRed: b green: p blue: q alpha: 1.0]; + } +} + ++ (CPColor)colorWithHexString:(string)hex +{ + return [[CPColor alloc] _initWithRGBA: hexToRGB(hex)]; +} + ++ (CPColor)blackColor +{ + return [[CPColor alloc] _initWithRGBA:[0.0, 0.0, 0.0, 1.0]]; +} + ++ (CPColor)blueColor +{ + return [[CPColor alloc] _initWithRGBA:[0.0, 0.0, 1.0, 1.0]]; +} + ++ (CPColor)darkGrayColor +{ + return [CPColor colorWithCalibratedWhite:1.0 / 3.0 alpha:1.0]; +} + ++ (CPColor)grayColor +{ + return [CPColor colorWithCalibratedWhite:0.5 alpha: 1.0]; +} + ++ (CPColor)greenColor +{ + return [[CPColor alloc] _initWithRGBA:[0.0, 1.0, 0.0, 1.0]]; +} + ++ (CPColor)lightGrayColor +{ + return [CPColor colorWithCalibratedWhite:2.0 / 3.0 alpha:1.0]; +} + ++ (CPColor)redColor +{ + return [[CPColor alloc] _initWithRGBA:[1.0, 0.0, 0.0, 1.0]]; +} + ++ (CPColor)whiteColor +{ + return [[CPColor alloc] _initWithRGBA:[1.0, 1.0, 1.0, 1.0]]; +} + ++ (CPColor)yellowColor +{ + return [[CPColor alloc] _initWithRGBA:[1.0, 1.0, 0.0, 1.0]]; +} + ++ (CPColor)shadowColor +{ + return [[CPColor alloc] _initWithRGBA:[0.0, 0.0, 0.0, 1.0 / 3.0]]; +} + ++ (CPColor)colorWithPatternImage:(CPImage)anImage +{ + return [[CPColor alloc] _initWithPatternImage:anImage]; +} + ++ (CPColor)colorWithCSSString:(CPString)aString +{ + return [[CPColor alloc] _initWithCSSString: aString]; +} + +- (id)_initWithCSSString:(CPString)aString +{ + if(aString.indexOf("rgb") == CPNotFound) + return nil; + + self = [super init]; + + var startingIndex = aString.indexOf("("); + var parts = aString.substring(startingIndex+1).split(','); + + _components = [ + parseInt(parts[0], 10) / 255.0, + parseInt(parts[1], 10) / 255.0, + parseInt(parts[2], 10) / 255.0, + parts[3] ? parseInt(parts[3], 10) / 255.0 : 1.0 + ] + + _cssString = aString; + + return self; +} + +- (id)_initWithRGBA:(CPArray)components +{ + self = [super init]; + + if (self) + { + _components = components; + + if (!CPFeatureIsCompatible(CPCSSRGBAFeature) && _components[3] != 1.0 && window.Base64 && window.CRC32) + { + var bytes = [0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,0x8,0x3,0x0,0x0,0x0,0x28,0xcb,0x34,0xbb,0x0,0x0,0x3,0x0,0x50,0x4c,0x54,0x45,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x17,0x89,0x99,0x55,0x0,0x0,0x0,0x1,0x74,0x52,0x4e,0x53,0x0,0x40,0xe6,0xd8,0x66,0x0,0x0,0x0,0x10,0x49,0x44,0x41,0x54,0x78,0xda,0x62,0x60,0x0,0x0,0x0,0x0,0xff,0xff,0x3,0x0,0x0,0x2,0x0,0x1,0x24,0x7f,0x24,0xf1,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82,0xff]; + var r_off = 41; + var g_off = 42; + var b_off = 43; + var a_off = 821; + var plte_crc_off = 809; + var trns_crc_off = 822; + var plte_type_off = 37; + var trns_type_off = 817; + + bytes[r_off] = Math.round(_components[0]*255); + bytes[g_off] = Math.round(_components[1]*255); + bytes[b_off] = Math.round(_components[2]*255); + bytes[a_off] = Math.round(_components[3]*255); + + // calculate new CRCs + var new_plte_crc = integerToBytes(CRC32.getCRC(bytes, plte_type_off, 4+768), 4); + var new_trns_crc = integerToBytes(CRC32.getCRC(bytes, trns_type_off, 4+1), 4); + + // overwrite old CRCs with new ones + for (var i = 0; i < 4; i++) + { + bytes[plte_crc_off+i] = new_plte_crc[i]; + bytes[trns_crc_off+i] = new_trns_crc[i]; + } + + // Base64 encode, strip whitespace and build data URL + var base64image = Base64.encode(bytes); //.replace(/[\s]/g, ""); + + _cssString = "url(\"data:image/png;base64," + base64image + "\")"; + } + else + { + var hasAlpha = CPFeatureIsCompatible(CPCSSRGBAFeature) && _components[3] != 1.0; + + _cssString = (hasAlpha ? "rgba(" : "rgb(") + + parseInt(_components[0] * 255.0) + ", " + + parseInt(_components[1] * 255.0) + ", " + + parseInt(_components[2] * 255.0) + + (hasAlpha ? (", " + _components[3]) : "") + ")"; + } + } + return self; +} + +- (id)_initWithPatternImage:(CPImage)anImage +{ + self = [super init]; + + if (self) + { + _patternImage = anImage; + _cssString = "url(\"" + _patternImage._filename + "\")"; + } + + return self; +} + +- (CPImage)patternImage +{ + return _patternImage; +} + +- (float)alphaComponent +{ + return _components[3]; +} + +- (float)blueComponent +{ + return _components[2]; +} + +- (float)greenComponent +{ + return _components[1]; +} + +- (float)redComponent +{ + return _components[0]; +} + +- (CPArray)components +{ + return _components; +} + +- (CPColor)colorWithAlphaComponent:(float)anAlphaComponent +{ + var components = _components.slice(); + + components[components.length - 1] = anAlphaComponent; + + return [[[self class] alloc] _initWithRGBA:components]; +} + +- (CPArray)hsbComponents +{ + var red = ROUND(_components[_redComponent] * 255.0), + green = ROUND(_components[_greenComponent] * 255.0), + blue = ROUND(_components[_blueComponent] * 255.0); + + var max = MAX(red, green, blue), + min = MIN(red, green, blue), + delta = max - min; + + var brightness = max / 255.0, + saturation = (max != 0) ? delta / max : 0; + + var hue; + if(saturation == 0) + hue = 0; + else + { + var rr = (max - red) / delta; + var gr = (max - green) / delta; + var br = (max - blue) / delta; + + if (red == max) + hue = br - gr; + else if (green == max) + hue = 2 + rr - br; + else + hue = 4 + gr - rr; + + hue /= 6; + if (hue < 0) + hue++; + } + + return [ + ROUND(hue * 360.0), + ROUND(saturation * 100.0), + ROUND(brightness * 100.0) + ]; +} + +- (CPString)cssString +{ + return _cssString; +} + +- (CPString)hexString +{ + return rgbToHex([self redComponent], [self greenComponent], [self blueComponent]) +} + +@end + +var CPColorComponentsKey = @"CPColorComponentsKey", + CPColorPatternImageKey = @"CPColorPatternImageKey"; + +@implementation CPColor (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + if ([aCoder containsValueForKey:CPColorPatternImageKey]) + return [self _initWithPatternImage:[aCoder decodeObjectForKey:CPColorPatternImageKey]]; + + return [self _initWithRGBA:[aCoder decodeObjectForKey:CPColorComponentsKey]]; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + if (_patternImage) + [aCoder encodeObject:_patternImage forKey:CPColorPatternImageKey]; + else + [aCoder encodeObject:_components forKey:CPColorComponentsKey]; +} + +@end + +var hexCharacters = "0123456789ABCDEF"; + +function hexToRGB(hex) +{ + if(hex.length != 6) + return null; + + for(var i=0; i= 0; i--) { + bytes[i] = integer & 255; + integer = integer >> 8 + } + return bytes; +} + +function rgbToHex(r,g,b) { + return byteToHex(r) + byteToHex(g) + byteToHex(b); +} + +function byteToHex(n) { + if (!n || isNaN(n)) return "00"; + n = ROUND(MIN(255,MAX(0,256*n))); + return hexCharacters.charAt((n - n % 16) / 16) + + hexCharacters.charAt(n % 16); +} + +// Toll-Free bridge CPColor to CGColor. +//CGColor.prototype.isa = CPColor; +//[CPColor initialize]; + +//http://dev.mootools.net/browser/trunk/Source/Utilities/Color.js?rev=1184 diff --git a/AppKit/CPColorPanel.j b/AppKit/CPColorPanel.j new file mode 100644 index 000000000..7d088aa95 --- /dev/null +++ b/AppKit/CPColorPanel.j @@ -0,0 +1,614 @@ +/* + * CPColorPanel.j + * AppKit + * + * Created by Ross Boucher. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPButton.j" +import "CPColorPicker.j" +import "CPCookie.j" +import "CPKulerColorPicker.j" +import "CPPanel.j" +import "CPSliderColorPicker.j" +import "CPView.j" + + +CPColorPanelColorDidChangeNotification = @"CPColorPanelColorDidChangeNotification"; + +var PREVIEW_HEIGHT = 20.0, + TOOLBAR_HEIGHT = 32.0, + SWATCH_HEIGHT = 14.0; + +var SharedColorPanel = nil; + +CPWheelColorPickerMode = 1, +CPKulerColorPickerMode = 2, +CPSliderColorPickerMode = 3; + +CPColorPickerViewWidth = 265, +CPColorPickerViewHeight = 370; + +@implementation CPColorPanel : CPPanel +{ + _CPColorPanelToolbar _toolbar; + _CPColorPanelSwatches _swatchView; + _CPColorPanelPreview _previewView; + + CPTextField _previewLabel; + CPTextField _swatchLabel; + + CPView _activeView; + + CPColorPicker _activePicker; + CPColorPicker _wheelPicker; + CPColorPicker _kulerPicker; + CPColorPicker _sliderPicker; + + CPColor _color; + + id _target; + SEL _action; + + int _mode; +} + ++ (CPColorPanel)sharedColorPanel +{ + if (!SharedColorPanel) + SharedColorPanel = [[CPColorPanel alloc] init]; + + return SharedColorPanel; +} + ++ (void)setPickerMode:(int)mode +{ + var panel = [CPColorPanel sharedColorPanel]; + [panel setMode: mode]; +} + +- (id)init +{ + self = [super initWithContentRect:CGRectMake(500.0, 50.0, 218.0, 360.0) + styleMask:(CPHUDBackgroundWindowMask | CPTitledWindowMask | CPClosableWindowMask | CPResizableWindowMask)]; + + if (self) + { + [self setTitle:@"Color Panel"]; + [self setLevel:CPFloatingWindowLevel]; + + [self setBecomesKeyOnlyIfNeeded:YES]; + + [self setMinSize:CGSizeMake(218.0, 360.0)]; + [self setMaxSize:CGSizeMake(327.0, 540.0)]; + } + + return self; +} + +- (void)setColor:(CPColor)aColor +{ + _color = aColor; + [_previewView setBackgroundColor: _color]; + + [CPApp sendAction:@selector(changeColor:) to:nil from:self]; + + if (_target && _action) + objj_msgSend(_target, _action, self); + + [[CPNotificationCenter defaultCenter] + postNotificationName:CPColorPanelColorDidChangeNotification + object:self]; +} + + -(void)setColor:(CPColor)aColor updatePicker:(BOOL)bool + { + [self setColor: aColor]; + + if(bool) + [_activePicker setColor: _color]; + } + + +- (CPColor)color +{ + return _color; +} + +- (void)setTarget:(id)aTarget +{ + _target = aTarget; +} + +- (id)target +{ + return _target; +} + +- (void)setAction:(selector)anAction +{ + _action = anAction; +} + +- (selector)action +{ + return _action; +} + +- (void)setMode:(int)mode +{ + if(mode == _mode) + return; + + var frame = CPRectCreateCopy([_currentView frame]); + [_currentView removeFromSuperview]; + + switch(mode) + { + case CPWheelColorPickerMode: _activePicker = _wheelPicker; break; + case CPKulerColorPickerMode: _activePicker = _kulerPicker; break; + case CPSliderColorPickerMode: _activePicker = _sliderPicker; break; + } + + _currentView = [_activePicker provideNewView: NO]; + [_activePicker setColor: _color]; + + _mode = mode; + + [_currentView setFrame: frame]; + [_currentView setAutoresizingMask: (CPViewWidthSizable | CPViewHeightSizable)]; + [[self contentView] addSubview: _currentView]; +} + +- (int)mode +{ + return _mode; +} + +- (void)orderFront:(id)aSender +{ + [self _loadContentsIfNecessary]; + + [super orderFront:aSender]; +} + +- (void)_loadContentsIfNecessary +{ + if (_toolbar) + return; + + var contentView = [self contentView], + bounds = [contentView bounds]; + + _toolbar = [[_CPColorPanelToolbar alloc] initWithFrame: CPRectMake(0, 0, CGRectGetWidth(bounds), TOOLBAR_HEIGHT)]; + [_toolbar setAutoresizingMask: CPViewWidthSizable]; + + // FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox + var previewBox = [[CPView alloc] initWithFrame:CGRectMake(76, TOOLBAR_HEIGHT + 10, CGRectGetWidth(bounds) - 86, PREVIEW_HEIGHT)]; + + _previewView = [[_CPColorPanelPreview alloc] initWithFrame:CGRectInset([previewBox bounds], 2.0, 2.0)]; + + [_previewView setColorPanel:self]; + [_previewView setAutoresizingMask:CPViewWidthSizable]; + + [previewBox setBackgroundColor:[CPColor grayColor]]; + [previewBox setAutoresizingMask:CPViewWidthSizable]; + + [previewBox addSubview:_previewView]; + + _previewLabel = [[CPTextField alloc] initWithFrame: CPRectMake(10, TOOLBAR_HEIGHT + 14, 60, 15)]; + [_previewLabel setStringValue: "Preview:"]; + [_previewLabel setTextColor:[CPColor whiteColor]]; + [_previewLabel setAlignment:CPRightTextAlignment]; + + // FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox + var swatchBox = [[CPView alloc] initWithFrame:CGRectMake(76, TOOLBAR_HEIGHT + 10 + PREVIEW_HEIGHT + 5, CGRectGetWidth(bounds) - 86, SWATCH_HEIGHT + 2.0)]; + + [swatchBox setBackgroundColor:[CPColor grayColor]]; + [swatchBox setAutoresizingMask:CPViewWidthSizable]; + + _swatchView = [[_CPColorPanelSwatches alloc] initWithFrame:CGRectInset([swatchBox bounds], 1.0, 1.0)]; + + [_swatchView setColorPanel: self]; + [_swatchView setAutoresizingMask: CPViewWidthSizable]; + + [swatchBox addSubview:_swatchView]; + + _swatchLabel = [[CPTextField alloc] initWithFrame: CPRectMake(10, TOOLBAR_HEIGHT + 8 + PREVIEW_HEIGHT + 5, 60, 15)]; + [_swatchLabel setStringValue: "Swatches:"]; + [_swatchLabel setTextColor:[CPColor whiteColor]]; + [_swatchLabel setAlignment:CPRightTextAlignment]; + + _wheelPicker = [[CPColorWheelColorPicker alloc] initWithPickerMask: 1|2|3 colorPanel: self]; + _currentView = [_wheelPicker provideNewView: YES]; + + var height = (TOOLBAR_HEIGHT+10+PREVIEW_HEIGHT+5+SWATCH_HEIGHT+10); + [_currentView setFrameSize: CPSizeMake(bounds.size.width - 10, bounds.size.height - height)]; + [_currentView setFrameOrigin: CPPointMake(5, TOOLBAR_HEIGHT+10+PREVIEW_HEIGHT+5+SWATCH_HEIGHT+10)]; + [_currentView setAutoresizingMask: (CPViewWidthSizable | CPViewHeightSizable)]; + + _kulerPicker = [[CPKulerColorPicker alloc] initWithPickerMask: 1|2|3 colorPanel: self]; + [_kulerPicker provideNewView: YES]; + + _sliderPicker = [[CPSliderColorPicker alloc] initWithPickerMask: 1|2|3 colorPanel: self]; + [_sliderPicker provideNewView: YES]; + + [contentView addSubview: _toolbar]; + [contentView addSubview: previewBox]; + [contentView addSubview: _previewLabel]; + [contentView addSubview: swatchBox]; + [contentView addSubview: _swatchLabel]; + [contentView addSubview: _currentView]; + + _target = nil; + _action = nil; + + _activePicker = _wheelPicker; + + [self setColor:[CPColor whiteColor]]; + [_activePicker setColor:[CPColor whiteColor]]; +} + +@end + +var iconSize = 32, + totalIcons = 3; + +@implementation _CPColorPanelToolbar : CPView +{ + CPImage _wheelImage; + CPImage _wheelAlternateImage; + CPButton _wheelButton; + + CPImage _sliderImage; + CPImage _sliderAlternateImage; + CPButton _sliderButton; + + CPImage _kulerImage; + CPImage _kulerAlternateImage; + CPButton _kulerButton; +} + +- (id)initWithFrame:(CPRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + var width = aFrame.size.width; + var center = width / 2.0; + var start = center - ((totalIcons * iconSize) + (totalIcons - 1) * 8.0) / 2.0; + + _wheelButton = [[CPButton alloc] initWithFrame:CPRectMake(start, 0, iconSize, iconSize)]; + + start += iconSize + 8; + + var path = [[CPBundle bundleForClass: _CPColorPanelToolbar] pathForResource:@"wheel_button.png"]; + _wheelImage = [[CPImage alloc] initWithContentsOfFile:path size: CPSizeMake(iconSize, iconSize)]; + + path = [[CPBundle bundleForClass: _CPColorPanelToolbar] pathForResource:@"wheel_button_h.png"]; + _wheelAlternateImage = [[CPImage alloc] initWithContentsOfFile:path size: CPSizeMake(iconSize, iconSize)]; + + [_wheelButton setBordered:NO]; + [_wheelButton setImage: _wheelImage]; + [_wheelButton setAlternateImage: _wheelAlternateImage]; + [_wheelButton setTarget: self]; + [_wheelButton setAction: @selector(setMode:)]; + [_wheelButton setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin]; + + [self addSubview: _wheelButton]; + + _sliderButton = [[CPButton alloc] initWithFrame:CPRectMake(start, 0, iconSize, iconSize)]; + + start += iconSize + 8; + + path = [[CPBundle bundleForClass: _CPColorPanelToolbar] pathForResource:@"slider_button.png"]; + _sliderImage = [[CPImage alloc] initWithContentsOfFile:path size: CPSizeMake(iconSize, iconSize)]; + + path = [[CPBundle bundleForClass: _CPColorPanelToolbar] pathForResource:@"slider_button_h.png"]; + _sliderAlternateImage = [[CPImage alloc] initWithContentsOfFile:path size: CPSizeMake(iconSize, iconSize)]; + + [_sliderButton setBordered:NO]; + [_sliderButton setImage: _sliderImage]; + [_sliderButton setAlternateImage: _sliderAlternateImage]; + [_sliderButton setTarget: self]; + [_sliderButton setAction: @selector(setMode:)]; + [_sliderButton setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin]; + + [self addSubview: _sliderButton]; + + _kulerButton = [[CPButton alloc] initWithFrame:CPRectMake(start, 0, iconSize, iconSize)]; + start += iconSize + 8; + + path = [[CPBundle bundleForClass: _CPColorPanelToolbar] pathForResource:@"kuler_button.png"]; + _kulerImage = [[CPImage alloc] initWithContentsOfFile:path size: CPSizeMake(iconSize, iconSize)]; + + path = [[CPBundle bundleForClass: _CPColorPanelToolbar] pathForResource:@"kuler_button_h.png"]; + _kulerAlternateImage = [[CPImage alloc] initWithContentsOfFile:path size: CPSizeMake(iconSize, iconSize)]; + + [_kulerButton setBordered:NO]; + [_kulerButton setImage: _kulerImage]; + [_kulerButton setAlternateImage: _kulerAlternateImage]; + [_kulerButton setTarget: self]; + [_kulerButton setAction: @selector(setMode:)]; + [_kulerButton setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin]; + + [self addSubview: _kulerButton]; + + return self; +} + +- (void)setMode:(id)sender +{ + if(sender == _kulerButton) + [[CPColorPanel sharedColorPanel] setMode: CPKulerColorPickerMode]; + else if(sender == _wheelButton) + [[CPColorPanel sharedColorPanel] setMode: CPWheelColorPickerMode]; + else + [[CPColorPanel sharedColorPanel] setMode: CPSliderColorPickerMode]; +} + +@end + +CPColorDragType = "CPColorDragType"; +var CPColorPanelSwatchesCookie = "CPColorPanelSwatchesCookie"; + +@implementation _CPColorPanelSwatches : CPView +{ + CPView[] _swatches; + CPColor _dragColor; + CPColorPanel _colorPanel; + CPCookie _swatchCookie; +} + +-(id)initWithFrame:(CPRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + [self setBackgroundColor: [CPColor grayColor]]; + + [self registerForDraggedTypes:[CPArray arrayWithObjects:CPColorDragType]]; + + var whiteColor = [CPColor whiteColor]; + + _swatchCookie = [[CPCookie alloc] initWithName: CPColorPanelSwatchesCookie]; + var colorList = [self startingColorList]; + + _swatches = []; + + for(var i=0; i < 50; i++) + { + // FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox + var view = [[CPView alloc] initWithFrame: CPRectMake(13*i+1, 1, 12, 12)], + fillView = [[CPView alloc] initWithFrame:CGRectInset([view bounds], 1.0, 1.0)]; + + [view setBackgroundColor:whiteColor]; + [fillView setBackgroundColor: (i < colorList.length) ? colorList[i] : whiteColor]; + + [view addSubview:fillView]; + + [self addSubview: view]; + + _swatches.push(view); + } + + return self; +} + +- (BOOL)isOpaque +{ + return YES; +} + +- (CPArray)startingColorList +{ + var cookieValue = [_swatchCookie value]; + if(cookieValue == "") + { + return [ + [CPColor blackColor], + [CPColor darkGrayColor], + [CPColor grayColor], + [CPColor lightGrayColor], + [CPColor whiteColor], + [CPColor redColor], + [CPColor greenColor], + [CPColor blueColor], + [CPColor yellowColor] + ]; + } + + var cookieValue = eval(cookieValue); + var result = []; + + for(var i=0; i [self bounds].size.width - 1 || point.x < 1) + return NO; + + [_colorPanel setColor: [self colorAtIndex:FLOOR(point.x / 13)] updatePicker: YES]; +} + +- (void)mouseDragged:(CPEvent)anEvent +{ + var point = [self convertPoint:[anEvent locationInWindow] fromView:nil]; + + if(point.x > [self bounds].size.width - 1 || point.x < 1) + return NO; + + [[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:[CPArray arrayWithObject:CPColorDragType] owner:self]; + + var swatch = _swatches[FLOOR(point.x / 13)]; + + // FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox + _dragColor = [[swatch subviews][0] backgroundColor]; + + var bounds = CPRectCreateCopy([swatch bounds]); + + // FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox + var dragView = [[CPView alloc] initWithFrame: bounds]; + dragFillView = [[CPView alloc] initWithFrame:CGRectInset(bounds, 1.0, 1.0)]; + + [dragView setBackgroundColor:[CPColor blackColor]]; + [dragFillView setBackgroundColor:_dragColor]; + + [dragView addSubview:dragFillView]; + + [self dragView: dragView + at: CPPointMake(point.x - bounds.size.width / 2.0, point.y - bounds.size.height / 2.0) + offset: CPPointMake(0.0, 0.0) + event: anEvent + pasteboard: nil + source: self + slideBack: YES]; +} + +- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType +{ + if(aType == CPColorDragType) + [aPasteboard setData:_dragColor forType:aType]; +} + +- (void)performDragOperation:(id )aSender +{ + var location = [self convertPoint:[aSender draggingLocation] fromView:nil], + pasteboard = [aSender draggingPasteboard], + swatch = nil; + + if(![pasteboard availableTypeFromArray:[CPColorDragType]] || location.x > [self bounds].size.width - 1 || location.x < 1) + return NO; + + [self setColor:[pasteboard dataForType:CPColorDragType] atIndex: FLOOR(location.x / 13)]; +} + +@end + +@implementation _CPColorPanelPreview : CPView +{ + CPColorPanel _colorPanel; +} + +- (id)initWithFrame:(CPRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + [self registerForDraggedTypes:[CPArray arrayWithObjects:CPColorDragType]]; + + return self; +} + +- (void)setColorPanel:(CPColorPanel)aPanel +{ + _colorPanel = aPanel; +} + +- (CPColorPanel)colorPanel +{ + return _colorPanel; +} + +- (void)performDragOperation:(id )aSender +{ + var pasteboard = [aSender draggingPasteboard]; + + if(![pasteboard availableTypeFromArray:[CPColorDragType]]) + return NO; + + var color = [pasteboard dataForType:CPColorDragType]; + [_colorPanel setColor: color updatePicker: YES]; +} + +- (BOOL)isOpaque +{ + return YES; +} + +- (void)mouseDragged:(CPEvent)anEvent +{ + var point = [self convertPoint:[anEvent locationInWindow] fromView:nil]; + + [[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:[CPArray arrayWithObject:CPColorDragType] owner:self]; + + var bounds = CPRectMake(0, 0, 15, 15); + + // FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/25-implement-cpbox + var dragView = [[CPView alloc] initWithFrame: bounds]; + dragFillView = [[CPView alloc] initWithFrame:CGRectInset(bounds, 1.0, 1.0)]; + + [dragView setBackgroundColor:[CPColor blackColor]]; + [dragFillView setBackgroundColor:[self backgroundColor]]; + + [dragView addSubview:dragFillView]; + + [self dragView: dragView + at: CPPointMake(point.x - bounds.size.width / 2.0, point.y - bounds.size.height / 2.0) + offset: CPPointMake(0.0, 0.0) + event: anEvent + pasteboard: nil + source: self + slideBack: YES]; +} + +- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType +{ + if(aType == CPColorDragType) + [aPasteboard setData:[self backgroundColor] forType:aType]; +} + +@end diff --git a/AppKit/CPColorPicker.j b/AppKit/CPColorPicker.j new file mode 100644 index 000000000..343df45c9 --- /dev/null +++ b/AppKit/CPColorPicker.j @@ -0,0 +1,336 @@ +/* + * CPColorPicker.j + * AppKit + * + * Created by Ross Boucher. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import +import +import + + +@implementation CPColorPicker : CPObject +{ + CPColorPanel _panel; + int _mask; +} + +- (id)initWithPickerMask:(int)aMask colorPanel:(CPColorPanel)aPanel +{ + self = [super init]; + + _panel = aPanel; + _mask = aMask; + + return self; +} + +- (CPColorPanel)colorPanel +{ + return _panel; +} + +- (CPImage)provideNewButtonImage +{ + return nil; +} + +- (void)setMode:(int)mode +{ + return; +} + +- (void)setColor:(CPColor)aColor +{ + return; +} + +@end + +@implementation CPColorWheelColorPicker : CPColorPicker +{ + CPView _pickerView; + CPView _brightnessSlider; + DOMElement _brightnessBarImage; + __CPColorWheel _hueSaturationView; +} + +- (id)initWithPickerMask:(int)mask colorPanel:(CPColorPanel)owningColorPanel +{ + return [super initWithPickerMask:mask colorPanel: owningColorPanel]; +} + +-(id)initView +{ + aFrame = CPRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight); + _pickerView = [[CPView alloc] initWithFrame:aFrame]; + + var path = [[CPBundle bundleForClass: CPColorPicker] pathForResource:@"brightness_bar.png"]; + + _brightnessBarImage = new Image(); + _brightnessBarImage.src = path; + _brightnessBarImage.style.width = "100%"; + _brightnessBarImage.style.height = "100%"; + _brightnessBarImage.style.position = "absolute"; + _brightnessBarImage.style.top = "0px"; + _brightnessBarImage.style.left = "0px"; + + var brightnessBarView = [[CPView alloc] initWithFrame: CPRectMake(0, (aFrame.size.height - 34), aFrame.size.width, 15)]; + [brightnessBarView setAutoresizingMask: (CPViewWidthSizable | CPViewMinYMargin)]; + brightnessBarView._DOMElement.appendChild(_brightnessBarImage); + + _brightnessSlider = [[CPSlider alloc] initWithFrame: CPRectMake(0, aFrame.size.height - 22, aFrame.size.width, 12)]; + [_brightnessSlider setMaxValue: 100.0]; + [_brightnessSlider setMinValue: 0.0]; + [_brightnessSlider setValue: 100.0]; + + [_brightnessSlider setTarget: self]; + [_brightnessSlider setAction: @selector(brightnessSliderDidChange:)]; + [_brightnessSlider setAutoresizingMask: (CPViewWidthSizable | CPViewMinYMargin)]; + + _hueSaturationView = [[__CPColorWheel alloc] initWithFrame: CPRectMake(0, 0, aFrame.size.width, aFrame.size.height - 38)]; + [_hueSaturationView setDelegate: self]; + [_hueSaturationView setAutoresizingMask: (CPViewWidthSizable | CPViewHeightSizable)]; + + [_pickerView addSubview: brightnessBarView]; + [_pickerView addSubview: _hueSaturationView]; + [_pickerView addSubview: _brightnessSlider]; +} + +-(void)brightnessSliderDidChange:(id)sender +{ + [self updateColor]; +} + +-(void)colorWheelDidChange:(id)sender +{ + [self updateColor]; +} + +-(void)updateColor +{ + var hue = [_hueSaturationView angle], + saturation = [_hueSaturationView distance], + brightness = [_brightnessSlider value]; + + [_hueSaturationView setWheelBrightness: brightness / 100.0]; + _brightnessBarImage.style.backgroundColor = "#"+[[CPColor colorWithHue: hue saturation: saturation brightness: 100] hexString]; + + [[self colorPanel] setColor:[CPColor colorWithHue: hue saturation: saturation brightness: brightness]]; +} + +- (BOOL)supportsMode:(int)mode +{ + return (mode == CPWheelColorPickerMode) ? YES : NO; +} + +- (int)currentMode +{ + return CPWheelColorPickerMode; +} + +- (CPView)provideNewView:(BOOL)initialRequest +{ + if (initialRequest) + [self initView]; + + return _pickerView; +} + +- (void)setColor:(CPColor)newColor +{ + var hsb = [newColor hsbComponents]; + + [_hueSaturationView setPositionToColor: newColor]; + [_brightnessSlider setValue: hsb[2]]; + [_hueSaturationView setWheelBrightness: hsb[2] / 100.0]; + + _brightnessBarImage.style.backgroundColor = "#"+[[CPColor colorWithHue: hsb[0] saturation: hsb[1] brightness: 100] hexString]; +} + +@end + +@implementation __CPColorWheel : CPView +{ + DOMElement _wheelImage; + DOMElement _blackWheelImage; + + CPView _crosshair; + + id _delegate; + + float _angle; + float _distance; + + float _radius; +} + +-(id)initWithFrame:(CPRect)aFrame +{ + self = [super initWithFrame: aFrame]; + + var path = [[CPBundle bundleForClass: CPColorPicker] pathForResource:@"wheel.png"]; + + _wheelImage = new Image(); + _wheelImage.src = path; + _wheelImage.style.position = "absolute"; + + path = [[CPBundle bundleForClass: CPColorPicker] pathForResource:@"wheel_black.png"]; + + _blackWheelImage = new Image(); + _blackWheelImage.src = path; + _blackWheelImage.style.opacity = "0"; + _blackWheelImage.style.filter = "alpha(opacity=0)" + _blackWheelImage.style.position = "absolute"; + + _DOMElement.appendChild(_wheelImage); + _DOMElement.appendChild(_blackWheelImage); + + [self setWheelSize: aFrame.size]; + + _crosshair = [[CPView alloc] initWithFrame:CPRectMake(_radius - 2, _radius - 2, 4, 4)]; + [_crosshair setBackgroundColor:[CPColor blackColor]]; + + var view = [[CPView alloc] initWithFrame:CGRectInset([_crosshair bounds], 1.0, 1.0)]; + [view setBackgroundColor:[CPColor whiteColor]]; + + [_crosshair addSubview:view]; + + [self addSubview: _crosshair]; + + return self; +} + +-(void)setWheelBrightness:(float)brightness +{ + _blackWheelImage.style.opacity = 1.0 - brightness; + _blackWheelImage.style.filter = "alpha(opacity=" + (1.0 - brightness)*100 + ")" +} + +-(void)setFrameSize:(CPSize)aSize +{ + [super setFrameSize: aSize]; + [self setWheelSize: aSize]; +} + +-(void)setWheelSize:(CPSize)aSize +{ + var min = MIN(aSize.width, aSize.height); + + _blackWheelImage.style.width = min; + _blackWheelImage.style.height = min; + _blackWheelImage.width = min; + _blackWheelImage.height = min; + _blackWheelImage.style.top = (aSize.height - min) / 2.0 + "px"; + _blackWheelImage.style.left = (aSize.width - min) / 2.0 + "px"; + + _wheelImage.style.width = min; + _wheelImage.style.height = min; + _wheelImage.width = min; + _wheelImage.height = min; + _wheelImage.style.top = (aSize.height - min) / 2.0 + "px"; + _wheelImage.style.left = (aSize.width - min) / 2.0 + "px"; + + _radius = min / 2.0; + + [self setAngle: [self degreesToRadians: _angle] distance: (_distance / 100.0) * _radius]; +} + +-(void)setDelegate:(id)aDelegate +{ + _delegate = aDelegate; +} + +-(id)delegate +{ + return _delegate; +} + +-(float)angle +{ + return _angle; +} + +-(float)distance +{ + return _distance; +} + +-(void)mouseDown:(CPEvent)anEvent +{ + [self reposition: anEvent]; +} + +-(void)mouseDragged:(CPEvent)anEvent +{ + [self reposition: anEvent]; +} + +-(void)reposition:(CPEvent)anEvent +{ + var bounds = [self bounds], + location = [self convertPoint: [anEvent locationInWindow] fromView: nil]; + + var midX = CGRectGetMidX(bounds); + var midY = CGRectGetMidY(bounds); + + var distance = MIN(SQRT((location.x - midX)*(location.x - midX) + (location.y - midY)*(location.y - midY)), _radius); + var angle = ATAN2(location.y - midY, location.x - midX); + + [self setAngle: angle distance: distance]; + + if(_delegate) + [_delegate colorWheelDidChange: self]; +} + +-(void)setAngle:(int)angle distance:(float)distance +{ + var bounds = [self bounds]; + var midX = CGRectGetMidX(bounds); + var midY = CGRectGetMidY(bounds); + + _angle = [self radiansToDegrees: angle]; + _distance = (distance / _radius) * 100.0; + + [_crosshair setFrameOrigin:CPPointMake(COS(angle) * distance + midX - 2.0, SIN(angle) * distance + midY - 2.0)]; +} + +-(void)setPositionToColor:(CPColor)aColor +{ + var hsb = [aColor hsbComponents], + bounds = [self bounds]; + + var angle = [self degreesToRadians: hsb[0]], + distance = (hsb[1] / 100.0) * _radius; + + [self setAngle: angle distance: distance]; +} + +-(int)radiansToDegrees:(float)radians +{ + return ((-radians / PI) * 180 + 360) % 360; +} + +-(float)degreesToRadians:(float)degrees +{ + return -(((degrees - 360) / 180) * PI); +} + +@end \ No newline at end of file diff --git a/AppKit/CPColorWell.j b/AppKit/CPColorWell.j new file mode 100644 index 000000000..bcca91233 --- /dev/null +++ b/AppKit/CPColorWell.j @@ -0,0 +1,198 @@ +/* + * CPColorWell.j + * AppKit + * + * Created by Ross Boucher. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + +import "CPView.j" +import "CPColor.j" +import "CPColorPanel.j" + + +var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiveNotification"; + +@implementation CPColorWell : CPControl +{ + BOOL _active; + + CPColor _color; + CPView _wellView; +} + +- (id)initWithFrame:(CGRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _active = NO; + + _color = [CPColor whiteColor]; + + [self drawBezelWithHighlight:NO]; + [self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)]; + + var defaultCenter = [CPNotificationCenter defaultCenter]; + + [defaultCenter + addObserver:self + selector:@selector(colorWellDidBecomeExclusive:) + name:_CPColorWellDidBecomeExclusiveNotification + object:nil]; + + [defaultCenter + addObserver:self + selector:@selector(colorPanelWillClose:) + name:CPWindowWillCloseNotification + object:[CPColorPanel sharedColorPanel]]; + } + + return self; +} + +// Managing Color From Color Wells + +- (CPColor)color +{ + return _color; +} + +- (void)setColor:(CPColor)aColor +{ + if (_color == aColor) + return; + + _color = aColor; + + [self drawWellInside:CGRectInset([self bounds], 3.0, 3.0)]; +} + +- (void)takeColorFrom:(id)aSender +{ + [self setColor:[aSender color]]; +} + +// Activating and Deactivating Color Wells + +- (void)activate:(BOOL)shouldBeExclusive +{ + if (shouldBeExclusive) + // FIXME: make this queue! + [[CPNotificationCenter defaultCenter] + postNotificationName:_CPColorWellDidBecomeExclusiveNotification + object:self]; + + + if ([self isActive]) + return; + + _active = YES; + + [[CPNotificationCenter defaultCenter] + addObserver:self + selector:@selector(colorPanelDidChangeColor:) + name:CPColorPanelColorDidChangeNotification + object:[CPColorPanel sharedColorPanel]]; +} + +- (void)deactivate +{ + if (![self isActive]) + return; + + _active = NO; + + [[CPNotificationCenter defaultCenter] + removeObserver:self + name:CPColorPanelColorDidChangeNotification + object:[CPColorPanel sharedColorPanel]]; +} + +- (BOOL)isActive +{ + return _active; +} + +// Drawing a Color Well + +- (void)drawBezelWithHighlight:(BOOL)shouldHighlight +{ +} + +- (void)drawWellInside:(CGRect)aRect +{ + if (!_wellView) + { + _wellView = [[CPView alloc] initWithFrame:aRect]; + + [self addSubview:_wellView]; + } + else + [_wellView setFrame:aRect]; + + [_wellView setBackgroundColor:_color]; +} + +- (void)colorPanelDidChangeColor:(CPNotification)aNotification +{ + [self takeColorFrom:[aNotification object]]; + + [self sendAction:[self action] to:[self target]]; +} + +- (void)colorWellDidBecomeExclusive:(CPNotification)aNotification +{ + if (self != [aNotification object]) + [self deactivate]; +} + +- (void)colorPanelWillClose:(CPNotification)aNotification +{ + [self deactivate]; +} + +- (void)mouseDown:(CPEvent)anEvent +{ + [self drawBezelWithHighlight:YES]; +} + +- (void)mouseDragged:(CPEvent)anEvent +{ + [self drawBezelWithHighlight:CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil])]; +} + +-(void)mouseUp:(CPEvent)anEvent +{ + [self drawBezelWithHighlight:NO]; + + if (!CGRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil])) + return; + + [self activate:YES]; + + var colorPanel = [CPColorPanel sharedColorPanel]; + + [colorPanel setColor:_color]; + + [colorPanel orderFront:self]; +} + +@end diff --git a/AppKit/CPCompatibility.j b/AppKit/CPCompatibility.j new file mode 100644 index 000000000..981769fcc --- /dev/null +++ b/AppKit/CPCompatibility.j @@ -0,0 +1,162 @@ +/* + * CPCompatibility.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPEvent.j" + +// Browser Engines +CPUnknownBrowserEngine = 0; +CPGeckoBrowserEngine = 1; +CPInternetExplorerBrowserEngine = 2; +CPKHTMLBrowserEngine = 3; +CPOperaBrowserEngine = 4; +CPWebKitBrowserEngine = 5; + +// Features +CPCSSRGBAFeature = 1 << 5; + +CPHTMLCanvasFeature = 1 << 6; +CPHTMLContentEditableFeature = 1 << 7; + +CPJavascriptInnerTextFeature = 1 << 8; +CPJavascriptTextContentFeature = 1 << 9; +CPJavascriptClipboardEventsFeature = 1 << 10; +CPJavascriptClipboardAccessFeature = 1 << 11; +CPJavaScriptCanvasDrawFeature = 1 << 12; + +CPVMLFeature = 1 << 14; + +CPJavascriptRemedialKeySupport = 1 << 15; +CPJavaScriptShadowFeature = 1 << 20; + +CPJavaScriptNegativeMouseWheelValues = 1 << 22; + +var USER_AGENT = ""; + + PLATFORM_ENGINE = CPUnknownBrowserEngine, + PLATFORM_FEATURES = 0; + +if (typeof window != "undfined" && typeof window.navigator != "undefined") + USER_AGENT = window.navigator.userAgent; + +// Opera +if (window.opera) +{ + PLATFORM_ENGINE = CPOperaBrowserEngine; + + PLATFORM_FEATURES |= CPJavaScriptCanvasDrawFeature; +} + +// Internet Explorer +else if (window.attachEvent) // Must follow Opera check. +{ + PLATFORM_ENGINE = CPInternetExplorerBrowserEngine; + + // Features we can only be sure of with IE (no known independent tests) + PLATFORM_FEATURES |= CPVMLFeature; + PLATFORM_FEATURES |= CPJavascriptRemedialKeySupport; + PLATFORM_FEATURES |= CPJavaScriptShadowFeature; +} + +// WebKit +else if (USER_AGENT.indexOf("AppleWebKit/") != -1) +{ + PLATFORM_ENGINE = CPWebKitBrowserEngine; + + // Features we can only be sure of with WebKit (no known independent tests) + PLATFORM_FEATURES |= CPCSSRGBAFeature; + PLATFORM_FEATURES |= CPHTMLContentEditableFeature; + PLATFORM_FEATURES |= CPJavascriptClipboardEventsFeature; + PLATFORM_FEATURES |= CPJavascriptClipboardAccessFeature; + PLATFORM_FEATURES |= CPJavaScriptShadowFeature; + + if(USER_AGENT.indexOf("AppleWebKit/") != -1) + { + var versionStart = USER_AGENT.indexOf("AppleWebKit/") + "AppleWebKit/".length, + versionEnd = USER_AGENT.indexOf(" ", versionStart), + version = parseFloat(USER_AGENT.substring(versionStart, versionEnd), 10); + + if(version >= 525.13) + PLATFORM_FEATURES |= CPJavascriptRemedialKeySupport; + } +} + +// KHTML +else if (USER_AGENT.indexOf('KHTML') != -1) // Must follow WebKit check. +{ + PLATFORM_ENGINE = CPKHTMLBrowserEngine; +} + +// Gecko +else if (USER_AGENT.indexOf('Gecko') != -1) // Must follow KHTML check. +{ + PLATFORM_ENGINE = CPGeckoBrowserEngine; + + PLATFORM_FEATURES |= CPJavaScriptCanvasDrawFeature; + + var index = USER_AGENT.indexOf("Firefox"), + version = (index == -1) ? 2.0 : parseFloat(USER_AGENT.substring(index+"Firefox".length+1)); + + if (version >= 3.0) + PLATFORM_FEATURES |= CPCSSRGBAFeature; +} + +// Feature Specific Checks +if (typeof document != "undefined") +{ + // Detect Canvas Support + if (document.createElement("canvas").getContext) + PLATFORM_FEATURES |= CPHTMLCanvasFeature; + + var DOMElement = document.createElement("div"); + + // Detect whether we have innerText or textContent (or neither) + if (DOMElement.innerText != undefined) + PLATFORM_FEATURES |= CPJavascriptInnerTextFeature; + else if (DOMElement.textContent != undefined) + PLATFORM_FEATURES |= CPJavascriptTextContentFeature; +} + +function CPFeatureIsCompatible(aFeature) +{ + return PLATFORM_FEATURES & aFeature; +} + +if (USER_AGENT.indexOf("Mac") != -1) +{ + CPPlatformActionKeyMask = CPCommandKeyMask; + + CPUndoKeyEquivalent = @"Z"; + CPRedoKeyEquivalent = @"Z"; + + CPUndoKeyEquivalentModifierMask = CPCommandKeyMask; + CPRedoKeyEquivalentModifierMask = CPCommandKeyMask | CPShiftKeyMask; +} +else +{ + CPPlatformActionKeyMask = CPControlKeyMask; + + CPUndoKeyEquivalent = @"Z"; + CPRedoKeyEquivalent = @"Y"; + + CPUndoKeyEquivalentModifierMask = CPControlKeyMask; + CPRedoKeyEquivalentModifierMask = CPControlKeyMask; +} diff --git a/AppKit/CPControl.j b/AppKit/CPControl.j new file mode 100644 index 000000000..29b87774a --- /dev/null +++ b/AppKit/CPControl.j @@ -0,0 +1,391 @@ +/* + * CPControl.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPFont.j" +import "CPShadow.j" +import "CPView.j" + +#include "Platform/Platform.h" + + +CPLeftTextAlignment = 0; +CPRightTextAlignment = 1; +CPCenterTextAlignment = 2; +CPJustifiedTextAlignment = 3; +CPNaturalTextAlignment = 4; + +CPRegularControlSize = 0; +CPSmallControlSize = 1; +CPMiniControlSize = 2; + +CPControlNormalBackgroundColor = @"CPControlNormalBackgroundColor"; +CPControlSelectedBackgroundColor = @"CPControlSelectedBackgroundColor"; +CPControlHighlightedBackgroundColor = @"CPControlHighlightedBackgroundColor"; +CPControlDisabledBackgroundColor = @"CPControlDisabledBackgroundColor"; + +var CPControlBlackColor = [CPColor blackColor]; + +@implementation CPControl : CPView +{ + id _value; + + BOOL _isEnabled; + + int _alignment; + CPFont _font; + CPColor _textColor; + CPShadow _textShadow; + + id _target; + SEL _action; + int _sendActionOn; + + CPColor _backgroundColor; + CPColor _highlightedBackgroundColor; + + CPDictionary _backgroundColors; + CPString _currentBackgroundColorName; +} + +- (id)initWithFrame:(CPRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _sendActionOn = CPLeftMouseUpMask; + _isEnabled = YES; + + [self setFont:[CPFont systemFontOfSize:12.0]]; + [self setTextColor:CPControlBlackColor]; + + _backgroundColors = [CPDictionary dictionary]; + } + + return self; +} + +- (void)setEnabled:(BOOL)isEnabled +{ + [self setAlphaValue:(_isEnabled = isEnabled) ? 1.0 : 0.3]; +} + +- (BOOL)isEnabled +{ + return _isEnabled; +} + +- (void)setTextColor:(CPColor)aColor +{ + if (_textColor == aColor) + return; + + _textColor = aColor; + +#if PLATFORM(DOM) + _DOMElement.style.color = [aColor cssString]; +#endif +} + +- (CPColor)textColor +{ + return _textColor; +} + +- (int)alignment +{ + return _alignment; +} + +- (void)setAlignment:(int)anAlignment +{ + _alignment = anAlignment; +} + +- (void)setFont:(CPFont)aFont +{ + if (_font == aFont) + return; + + _font = aFont; + +#if PLATFORM(DOM) + _DOMElement.style.font = [_font ? _font : [CPFont systemFontOfSize:12.0] cssString]; +#endif +} + +- (CPFont)font +{ + return _font; +} + +- (void)setTextShadow:(CPShadow)aTextShadow +{ + _DOMElement.style.textShadow = [_textShadow = aTextShadow cssString]; +} + +- (CPShadow)textShadow +{ + return _textShadow; +} + +- (SEL)action +{ + return _action; +} + +- (void)setAction:(SEL)anAction +{ + _action = anAction; +} + +- (id)target +{ + return _target; +} + +- (void)setTarget:(id)aTarget +{ + _target = aTarget; +} + +- (void)mouseUp:(CPEvent)anEvent +{ + if (_sendActionOn & CPLeftMouseUpMask && CPRectContainsPoint([self bounds], [self convertPoint:[anEvent locationInWindow] fromView:nil])) + [self sendAction:_action to:_target]; + + [super mouseUp:anEvent]; +} + +- (void)sendAction:(SEL)anAction to:(id)anObject +{ + [CPApp sendAction:anAction to:anObject from:self]; +} + +- (float)floatValue +{ + return _value ? parseFloat(_value) : 0.0; +} + +- (void)setFloatValue:(float)aValue +{ + _value = aValue; +} + +- (void)setBackgroundColor:(CPColor)aColor +{ + _backgroundColors = [CPDictionary dictionary]; + + [self setBackgroundColor:aColor forName:CPControlNormalBackgroundColor]; + + [super setBackgroundColor:aColor]; +} + +- (void)setBackgroundColor:(CPColor)aColor forName:(CPString)aName +{ + if (!aColor) + [_backgroundColors removeObjectForKey:aName]; + else + [_backgroundColors setObject:aColor forKey:aName]; + + if (_currentBackgroundColorName == aName) + [self setBackgroundColorWithName:_currentBackgroundColorName]; +} + +- (CPColor)backgroundColorForName:(CPString)aName +{ + var backgroundColor = [_backgroundColors objectForKey:aName]; + + if (!backgroundColor && aName != CPControlNormalBackgroundColor) + return [_backgroundColors objectForKey:CPControlNormalBackgroundColor]; + + return backgroundColor; +} + +- (void)setBackgroundColorWithName:(CPString)aName +{ + _currentBackgroundColorName = aName; + + [super setBackgroundColor:[self backgroundColorForName:aName]]; +} + +/* +Ð doubleValue +Ð setDoubleValue: +Ð intValue +Ð setIntValue: +Ð objectValue +Ð setObjectValue: +Ð stringValue +Ð setStringValue: +Ð setNeedsDisplay +Ð attributedStringValue +Ð setAttributedStringValue: */ + +@end + +var CPControlIsEnabledKey = @"CPControlIsEnabledKey", + CPControlAlignmentKey = @"CPControlAlignmentKey", + CPControlFontKey = @"CPControlFontKey", + CPControlTextColorKey = @"CPControlTextColorKey", + CPControlTargetKey = @"CPControlTargetKey", + CPControlActionKey = @"CPControlActionKey", + CPControlSendActionOnKey = @"CPControlSendActionOnKey"; + +@implementation CPControl (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super initWithCoder:aCoder]; + + if (self) + { + [self setEnabled:[aCoder decodeIntForKey:CPControlIsEnabledKey]]; + + [self setAlignment:[aCoder decodeIntForKey:CPControlAlignmentKey]]; + [self setFont:[aCoder decodeObjectForKey:CPControlFontKey]]; + [self setTextColor:[aCoder decodeObjectForKey:CPControlTextColorKey]]; + + [self setTarget:[aCoder decodeObjectForKey:CPControlTargetKey]]; + [self setAction:[aCoder decodeObjectForKey:CPControlActionKey]]; + + _sendActionOn = [aCoder decodeIntForKey:CPControlSendActionOnKey]; + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [super encodeWithCoder:aCoder]; + + [aCoder encodeInt:_isEnabled forKey:CPControlIsEnabledKey]; + + [aCoder encodeInt:_alignment forKey:CPControlAlignmentKey]; + [aCoder encodeObject:_font forKey:CPControlFontKey]; + [aCoder encodeObject:_textColor forKey:CPControlTextColorKey]; + + [aCoder encodeConditionalObject:_target forKey:CPControlTargetKey]; + [aCoder encodeObject:_action forKey:CPControlActionKey]; + + [aCoder encodeInt:_sendActionOn forKey:CPControlSendActionOnKey]; +} + +@end + +var _CPControlSizeIdentifiers = [], + _CPControlCachedThreePartImages = {}, + _CPControlCachedColorWithPatternImages = {}, + _CPControlCachedThreePartImagePattern = {}; + +_CPControlSizeIdentifiers[CPRegularControlSize] = @"Regular"; +_CPControlSizeIdentifiers[CPSmallControlSize] = @"Small"; +_CPControlSizeIdentifiers[CPMiniControlSize] = @"Mini"; + +function _CPControlIdentifierForControlSize(aControlSize) +{ + return _CPControlSizeIdentifiers[aControlSize]; +} + +function _CPControlColorWithPatternImage(sizes, aClassName) +{ + var index = 1, + count = arguments.length, + identifier = @""; + + for (; index < count; ++index) + identifier += arguments[index]; + + var color = _CPControlCachedColorWithPatternImages[identifier]; + + if (!color) + { + var bundle = [CPBundle bundleForClass:[CPControl class]]; + + color = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:aClassName + "/" + identifier + @".png"] size:sizes[identifier]]]; + + _CPControlCachedColorWithPatternImages[identifier] = color; + } + + return color; +} + +function _CPControlThreePartImages(sizes, aClassName) +{ + var index = 1, + count = arguments.length, + identifier = @""; + + for (; index < count; ++index) + identifier += arguments[index]; + + var images = _CPControlCachedThreePartImages[identifier]; + + if (!images) + { + var bundle = [CPBundle bundleForClass:[CPControl class]], + path = aClassName + "/" + identifier; + + sizes = sizes[identifier]; + + images = [ + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + @"0.png"] size:sizes[0]], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + @"1.png"] size:sizes[1]], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + @"2.png"] size:sizes[2]] + ]; + + _CPControlCachedThreePartImages[identifier] = images; + } + + return images; +} + +function _CPControlThreePartImagePattern(isVertical, sizes, aClassName) +{ + var index = 2, + count = arguments.length, + identifier = @""; + + for (; index < count; ++index) + identifier += arguments[index]; + + var color = _CPControlCachedThreePartImagePattern[identifier]; + + if (!color) + { + var bundle = [CPBundle bundleForClass:[CPControl class]], + path = aClassName + "/" + identifier; + + sizes = sizes[identifier]; + + color = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices:[ + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + @"0.png"] size:sizes[0]], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + @"1.png"] size:sizes[1]], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:path + @"2.png"] size:sizes[2]] + ] isVertical:isVertical]]; + + _CPControlCachedThreePartImagePattern[identifier] = color; + } + + return color; +} + diff --git a/AppKit/CPCookie.j b/AppKit/CPCookie.j new file mode 100644 index 000000000..33adb1fcf --- /dev/null +++ b/AppKit/CPCookie.j @@ -0,0 +1,89 @@ +/* + * CPCookie.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import + + +@implementation CPCookie : CPObject +{ + CPString _cookieName; + CPString _cookieValue; + + CPString _expires; +} + +- (id)initWithName:(CPString)aName +{ + self = [super init]; + + _cookieName = aName; + _cookieValue = [self _readCookieValue]; + + return self; +} + +- (CPString)value +{ + return _cookieValue; +} + +- (CPString)name +{ + return _cookieName; +} + +- (CPString)expires +{ + return _expires; +} + +- (void)setValue:(CPString)value expires:(CPDate)date domain:(CPString)domain +{ + if(date) + var expires = "; expires="+date.toGMTString(); + else + var expires = ""; + + if(domain) + domain = "; domain="+domain; + else + domain = ""; + + document.cookie = _cookieName+"="+value+expires+"; path=/"+domain; +} + +- (CPString)_readCookieValue +{ + var nameEQ = _cookieName + "="; + var ca = document.cookie.split(';'); + for(var i=0;i < ca.length;i++) { + var c = ca[i]; + while (c.charAt(0)==' ') c = c.substring(1,c.length); + if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); + } + return ""; +} + +@end + +//http://www.quirksmode.org/js/cookies.html diff --git a/AppKit/CPDocument.j b/AppKit/CPDocument.j new file mode 100644 index 000000000..ccb52e878 --- /dev/null +++ b/AppKit/CPDocument.j @@ -0,0 +1,514 @@ +/* + * CPDocument.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import + +import "CPResponder.j" +import "CPWindowController.j" + + +CPSaveOperation = 0; +CPSaveAsOperation = 1; +CPSaveToOperation = 2; +CPAutosaveOperation = 3; + +CPChangeDone = 0; +CPChangeUndone = 1; +CPChangeCleared = 2; +CPChangeReadOtherContents = 3; +CPChangeAutosaved = 4; + +CPDocumentWillSaveNotification = @"CPDocumentWillSaveNotification"; +CPDocumentDidSaveNotification = @"CPDocumentDidSaveNotification"; +CPDocumentDidFailToSaveNotification = @"CPDocumentDidFailToSaveNotification"; + +var CPDocumentUntitledCount = 0; + +@implementation CPDocument : CPResponder +{ + CPURL _fileURL; + CPString _fileType; + CPArray _windowControllers; + unsigned _untitledDocumentIndex; + + BOOL _hasUndoManager; + CPUndoManager _undoManager; + + int _changeCount; + + CPURLConnection _readConnection; + CPURLRequest _writeRequest; +} + +- (id)init +{ + self = [super init]; + + if (self) + { + _windowControllers = []; + + _hasUndoManager = YES; + _changeCount = 0; + + [self setNextResponder:CPApp]; + } + + return self; +} + +- (id)initWithType:(CPString)aType error:({CPError})anError +{ + self = [self init]; + + if (self) + [self setFileType:aType]; + + return self; +} + +- (id)initWithContentsOfURL:(CPURL)anAbsoluteURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aDidReadSelector contextInfo:(id)aContextInfo +{ + self = [self init]; + + if (self) + { + [self readFromURL:anAbsoluteURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo]; + + [self setFileURL:anAbsoluteURL]; + [self setFileType:aType]; + } + + return self; +} + +- (id)initForURL:(CPURL)anAbsoluteURL withContentsOfURL:(CPURL)absoluteContentsURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aDidReadSelector contextInfo:(id)aContextInfo +{ + self = [self init]; + + if (self) + { + [self readFromURL:absoluteContentsURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo]; + + [self setFileURL:anAbsoluteURL]; + [self setFileType:aType]; + } + + return self; +} + +- (CPData)dataOfType:(CPString)aType error:({CPError})anError +{ + // FIXME: Throw Exception. + return nil; +} + +- (void)readFromData:(CPData)aData ofType:(CPString)aType error:(CPError)anError +{ +} + +// Creating and managing window controllers + +- (void)makeWindowControllers +{ + var controller = [[CPWindowController alloc] initWithWindowCibName:nil]; + + [self addWindowController:controller]; +} + +- (CPArray)windowControllers +{ + return _windowControllers; +} + +- (void)addWindowController:(CPWindowController)aWindowController +{ + [_windowControllers addObject:aWindowController]; + + if ([aWindowController document] != self) + { + [aWindowController setNextResponder:self]; + [aWindowController setDocument:self]; + } +} + +// Managing Document Windows + +- (void)showWindows +{ + [_windowControllers makeObjectsPerformSelector:@selector(showWindow:) withObject:self]; +} + +- (CPString)displayName +{ + // FIXME: By default, return last path component of fileURL + if (!_untitledDocumentIndex) + _untitledDocumentIndex = ++CPDocumentUntitledCount; + + if (_untitledDocumentIndex == 1) + return @"Untitled"; + + return @"Untitled " + _untitledDocumentIndex; +} + +- (CPString)windowCibName +{ + return nil; +} + +- (void)windowControllerDidLoadNib:(CPWindowController)aWindowController +{ +} + +- (void)windowControllerWillLoadNib:(CPWindowController)aWindowController +{ +} + +// Reading from and Writing to URLs + +- (void)readFromURL:(CPURL)anAbsoluteURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aDidReadSelector contextInfo:(id)aContextInfo +{ + [_readConnection cancel]; + + // FIXME: Oh man is this every looking for trouble, we need to handle login at the Cappuccino level, with HTTP Errors. + _readConnection = [CPURLConnection connectionWithRequest:[CPURLRequest requestWithURL:anAbsoluteURL] delegate:self]; + + _readConnection.session = _CPReadSessionMake(aType, aDelegate, aDidReadSelector, aContextInfo); +} + +- (CPURL)fileURL +{ + return _fileURL; +} + +- (void)setFileURL:(CPURL)aFileURL +{ + if (_fileURL == aFileURL) + return; + + _fileURL = aFileURL; + + [_windowControllers makeObjectsPerformSelector:@selector(synchronizeWindowTitleWithDocumentName)]; +} + +- (void)saveToURL:(CPURL)anAbsoluteURL ofType:(CPString)aTypeName forSaveOperation:(CPSaveOperationType)aSaveOperation delegate:(id)aDelegate didSaveSelector:(SEL)aDidSaveSelector contextInfo:(id)aContextInfo +{ + var data = [self dataOfType:[self fileType] error:nil], + oldChangeCount = _changeCount; + + _writeRequest = [CPURLRequest requestWithURL:anAbsoluteURL]; + + [_writeRequest setHTTPMethod:@"POST"]; + [_writeRequest setHTTPBody:[data string]]; + + [_writeRequest setValue:@"close" forHTTPHeaderField:@"Connection"]; + + if (aSaveOperation == CPSaveOperation) + [_writeRequest setValue:@"true" forHTTPHeaderField:@"x-cappuccino-overwrite"]; + + if (aSaveOperation != CPSaveToOperation) + [self updateChangeCount:CPChangeCleared]; + + // FIXME: Oh man is this every looking for trouble, we need to handle login at the Cappuccino level, with HTTP Errors. + var connection = [CPURLConnection connectionWithRequest:_writeRequest delegate:self]; + + connection.session = _CPSaveSessionMake(anAbsoluteURL, aSaveOperation, oldChangeCount, aDelegate, aDidSaveSelector, aContextInfo, connection); +} + +- (void)connection:(CPURLConnection)aConnection didReceiveResponse:(CPURLResponse)aResponse +{ + var statusCode = [aResponse statusCode]; + + // Nothing to do if everything is hunky dory. + if (statusCode == 200) + return; + + var session = aConnection.session; + + if (aConnection == _readConnection) + { + [aConnection cancel]; + + alert("There was an error retrieving the document."); + + objj_msgSend(session.delegate, session.didReadSelector, self, NO, session.contextInfo); + } + else + { + // 409: Conflict, in Cappuccino, overwrite protection for documents. + if (statusCode == 409) + { + [aConnection cancel]; + + if (confirm("There already exists a file with that name, would you like to overwrite it?")) + { + [_writeRequest setValue:@"true" forHTTPHeaderField:@"x-cappuccino-overwrite"]; + + [aConnection start]; + } + else + { + if (session.saveOperation != CPSaveToOperation) + { + _changeCount += session.changeCount; + [_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[self isDocumentEdited]]; + } + + _writeRequest = nil; + + objj_msgSend(session.delegate, session.didSaveSelector, self, NO, session.contextInfo); + } + } + } +} + +- (void)connection:(CPURLConnection)aConnection didReceiveData:(CPString)aData +{ + var session = aConnection.session; + + // READ + if (aConnection == _readConnection) + { + [self readFromData:[CPData dataWithString:aData] ofType:session.fileType error:nil]; + + objj_msgSend(session.delegate, session.didReadSelector, self, YES, session.contextInfo); + } + else + { + if (session.saveOperation != CPSaveToOperation) + [self setFileURL:session.absoluteURL]; + + _writeRequest = nil; + + objj_msgSend(session.delegate, session.didSaveSelector, self, YES, session.contextInfo); + } +} + +- (void)connection:(CPURLConnection)aConnection didFailWithError:(CPError)anError +{ + var session = aConnection.session; + + if (_readConnection == aConnection) + objj_msgSend(session.delegate, session.didReadSelector, self, NO, session.contextInfo); + + else + { + if (session.saveOperation != CPSaveToOperation) + { + _changeCount += session.changeCount; + [_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[self isDocumentEdited]]; + } + + _writeRequest = nil; + + alert("There was an error saving the document."); + + objj_msgSend(session.delegate, session.didSaveSelector, self, NO, session.contextInfo); + } +} + +- (void)connectionDidFinishLoading:(CPURLConnection)aConnection +{ + if (_readConnection == aConnection) + _readConnection = nil; +} + +// Managing Document Status + +- (BOOL)isDocumentEdited +{ + return _changeCount != 0; +} + +- (void)updateChangeCount:(CPDocumentChangeType)aChangeType +{ + if (aChangeType == CPChangeDone) + ++_changeCount; + else if (aChangeType == CPChangeUndone) + --_changeCount; + else if (aChangeType == CPChangeCleared) + _changeCount = 0; + /*else if (aChangeType == CPCHangeReadOtherContents) + + else if (aChangeType == CPChangeAutosaved)*/ + + [_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[self isDocumentEdited]]; +} + +// Managing File Types + +- (void)setFileType:(CPString)aType +{ + _fileType = aType; +} + +- (CPString)fileType +{ + return _fileType; +} + +// Working with Undo Manager + +- (BOOL)hasUndoManager +{ + return _hasUndoManager; +} + +- (void)setHashUndoManager:(BOOL)aFlag +{ + if (_hasUndoManager == aFlag) + return; + + _hasUndoManager = aFlag; + + if (!_hasUndoManager) + [self setUndoManager:nil]; +} + +- (void)_undoManagerWillCloseGroup:(CPNotification)aNotification +{ + var undoManager = [aNotification object]; + + if ([undoManager isUndoing] || [undoManager isRedoing]) + return; + + [self updateChangeCount:CPChangeDone]; +} + +- (void)_undoManagerDidUndoChange:(CPNotification)aNotification +{ + [self updateChangeCount:CPChangeUndone]; +} + +- (void)_undoManagerDidRedoChange:(CPNotification)aNotification +{ + [self updateChangeCount:CPChangeDone]; +} + +- (void)setUndoManager:(CPUndoManager)anUndoManager +{ + var defaultCenter = [CPNotificationCenter defaultCenter]; + + if (_undoManager) + { + [defaultCenter removeObserver:self + name:CPUndoManagerDidUndoChangeNotification + object:_undoManager]; + + [defaultCenter removeObserver:self + name:CPUndoManagerDidRedoChangeNotification + object:_undoManager]; + + [defaultCenter removeObserver:self + name:CPUndoManagerWillCloseUndoGroupNotification + object:_undoManager]; + } + + _undoManager = anUndoManager; + + if (_undoManager) + { + + [defaultCenter addObserver:self + selector:@selector(_undoManagerDidUndoChange:) + name:CPUndoManagerDidUndoChangeNotification + object:_undoManager]; + + [defaultCenter addObserver:self + selector:@selector(_undoManagerDidRedoChange:) + name:CPUndoManagerDidRedoChangeNotification + object:_undoManager]; + + [defaultCenter addObserver:self + selector:@selector(_undoManagerWillCloseGroup:) + name:CPUndoManagerWillCloseUndoGroupNotification + object:_undoManager]; + } +} + +- (CPUndoManager)undoManager +{ + if (_hasUndoManager && !_undoManager) + [self setUndoManager:[[CPUndoManager alloc] init]]; + + return _undoManager; +} + +- (CPUndoManager)windowWillReturnUndoManager:(CPWindow)aWindow +{ + return [self undoManager]; +} + +// Handling User Actions + +- (void)saveDocument:(id)aSender +{ + if (_fileURL) + { + [[CPNotificationCenter defaultCenter] + postNotificationName:CPDocumentWillSaveNotification + object:self]; + + [self saveToURL:_fileURL ofType:[self fileType] forSaveOperation:CPSaveOperation delegate:self didSaveSelector:@selector(document:didSave:contextInfo:) contextInfo:NULL]; + } + else + [self saveDocumentAs:self]; +} + +- (void)saveDocumentAs:(id)aSender +{ + _documentName = window.prompt("Document Name:"); + + if (!_documentName) + return; + + [[CPNotificationCenter defaultCenter] + postNotificationName:CPDocumentWillSaveNotification + object:self]; + + [self saveToURL:[self proposedFileURL] ofType:[self fileType] forSaveOperation:CPSaveAsOperation delegate:self didSaveSelector:@selector(document:didSave:contextInfo:) contextInfo:NULL]; +} + +- (void)document:(id)aDocument didSave:(BOOL)didSave contextInfo:(id)aContextInfo +{ + if (didSave) + [[CPNotificationCenter defaultCenter] + postNotificationName:CPDocumentDidSaveNotification + object:self]; + else + [[CPNotificationCenter defaultCenter] + postNotificationName:CPDocumentDidFailToSaveNotification + object:self]; +} + +@end + +var _CPReadSessionMake = function(aType, aDelegate, aDidReadSelector, aContextInfo) +{ + return { fileType:aType, delegate:aDelegate, didReadSelector:aDidReadSelector, contextInfo:aContextInfo }; +} + +var _CPSaveSessionMake = function(anAbsoluteURL, aSaveOperation, aChangeCount, aDelegate, aDidSaveSelector, aContextInfo, aConnection) +{ + return { absoluteURL:anAbsoluteURL, saveOperation:aSaveOperation, changeCount:aChangeCount, delegate:aDelegate, didSaveSelector:aDidSaveSelector, contextInfo:aContextInfo, connection:aConnection }; +} diff --git a/AppKit/CPDocumentController.j b/AppKit/CPDocumentController.j new file mode 100644 index 000000000..0445f96ca --- /dev/null +++ b/AppKit/CPDocumentController.j @@ -0,0 +1,184 @@ +/* + * CPDocumentController.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import + +import "CPDocument.j" + +var CPSharedDocumentController = nil; + +@implementation CPDocumentController : CPObject +{ + CPArray _documents; + CPArray _documentTypes; +} + ++ (id)sharedDocumentController +{ + if (!CPSharedDocumentController) + [[self alloc] init]; + + return CPSharedDocumentController; +} + +- (id)init +{ + self = [super init]; + + if (self) + { + _documents = [[CPArray alloc] init]; + + if (!CPSharedDocumentController) + CPSharedDocumentController = self; + + _documentTypes = [[[CPBundle mainBundle] infoDictionary] objectForKey:@"CPBundleDocumentTypes"]; + } + return self; +} + +// Creating and Opening Documents + +- (CPDocument)documentForURL:(CPURL)aURL +{ + var index = 0, + count = [_documents count]; + + for (; index < count; ++index) + { + var theDocument = _documents[index]; + + if ([[theDocument fileURL] isEqual:aURL]) + return theDocument; + } + + return nil; +} + +- (void)openUntitledDocumentOfType:(CPString)aType display:(BOOL)shouldDisplay +{ + var document = [self makeUntitledDocumentOfType:aType error:nil]; + + if (document) + [self addDocument:document]; + + if (shouldDisplay) + { + [document makeWindowControllers]; + [document showWindows]; + } + + return document; +} + +- (CPDocument)makeUntitledDocumentOfType:(CPString)aType error:({CPError})anError +{ + return [[[self documentClassForType:aType] alloc] initWithType:aType error:anError]; +} + +- (CPDocument)openDocumentWithContentsOfURL:(CPURL)anAbsoluteURL display:(BOOL)shouldDisplay error:(CPError)anError +{ + var result = [self documentForURL:anAbsoluteURL]; + + if (!result) + // FIXME: type(!) + result = [self makeDocumentWithContentsOfURL:anAbsoluteURL ofType:[[_documentTypes objectAtIndex:0] objectForKey:@"CPBundleTypeName"] delegate:self didReadSelector:@selector(document:didRead:contextInfo:) contextInfo:nil]; + + else if (shouldDisplay) + [result showWindows]; + + return result; +} + +- (CPDocument)reopenDocumentForURL:(CPURL)anAbsoluteURL withContentsOfURL:(CPURL)absoluteContentsURL error:(CPError)anError +{ + return [self makeDocumentForURL:anAbsoluteURL withContentsOfURL:absoluteContentsURL ofType:[[_documentTypes objectAtIndex:0] objectForKey:@"CPBundleTypeName"] delegate:self didReadSelector:@selector(document:didRead:contextInfo:) contextInfo:nil]; +} + +- (CPDocument)makeDocumentWithContentsOfURL:(CPURL)anAbsoluteURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aSelector contextInfo:(id)aContextInfo +{ + return [[[self documentClassForType:aType] alloc] initWithContentsOfURL:anAbsoluteURL ofType:aType delegate:aDelegate didReadSelector:aSelector contextInfo:aContextInfo]; +} + +- (CPDocument)makeDocumentForURL:(CPURL)anAbsoluteURL withContentsOfURL:(CPURL)absoluteContentsURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aSelector contextInfo:(id)aContextInfo +{ + return [[[self documentClassForType:aType] alloc] initForURL:anAbsoluteURL withContentsOfURL:absoluteContentsURL ofType:aType delegate:aDelegate didReadSelector:aSelector contextInfo:aContextInfo]; +} + +- (void)document:(CPDocument)aDocument didRead:(BOOL)didRead contextInfo:(id)aContextInfo +{ + if (!didRead) + return; + + [self addDocument:aDocument]; + [aDocument makeWindowControllers]; +} + +- (CFAction)newDocument:(id)aSender +{ + [self openUntitledDocumentOfType:[[_documentTypes objectAtIndex:0] objectForKey:@"CPBundleTypeName"] display:YES]; +} + +// Managing Documents + +- (CPArray)documents +{ + return _documents; +} + +- (void)addDocument:(CPDocument)aDocument +{ + [_documents addObject:aDocument]; +} + +- (void)removeDocument:(CPDocument)aDocument +{ + [_documents removeObjectIdenticalTo:aDocument]; +} + +// Managing Document Types + +- (CPDictionary)_infoForType:(CPString)aType +{ + var i = 0, + count = [_documentTypes count]; + + for (;i < count; ++i) + { + var documentType = _documentTypes[i]; + + if ([documentType objectForKey:@"CPBundleTypeName"] == aType) + return documentType; + } + + return nil; +} + +- (Class)documentClassForType:(CPString)aType +{ + var className = [[self _infoForType:aType] objectForKey:@"CPDocumentClass"]; + + return className ? CPClassFromString(className) : Nil; +} + +@end diff --git a/AppKit/CPDragServer.j b/AppKit/CPDragServer.j new file mode 100644 index 000000000..f9a0ca12b --- /dev/null +++ b/AppKit/CPDragServer.j @@ -0,0 +1,263 @@ +/* + * CPDragServer.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import +import +import + +var CPSharedDragServer = nil; + +var CPDragServerView = nil, + CPDragServerSource = nil, + CPDragServerWindow = nil, + CPDragServerOffset = nil, + CPDragServerLocation = nil, + CPDragServerPasteboard = nil, + CPDragServerDestination = nil, + CPDragServerDraggingInfo = nil; + +var CPDragServerIsDraggingImage = NO, + + CPDragServerShouldSendDraggedViewMovedTo = NO, + CPDragServerShouldSendDraggedImageMovedTo = NO, + + CPDragServerShouldSendDraggedViewEndedAtOperation = NO, + CPDragServerShouldSendDraggedImageEndedAtOperation = NO; + +var CPDragServerStartDragging = function(anEvent) +{ + CPDragServerUpdateDragging(anEvent); +} + +var CPDragServerUpdateDragging = function(anEvent) +{ + // If this is a mouse up, then complete the drag. + if([anEvent type] == CPLeftMouseUp) + { + CPDragServerLocation = [[CPDragServerDestination window] convertBridgeToBase:[[anEvent window] convertBaseToBridge:[anEvent locationInWindow]]]; + + [CPDragServerView removeFromSuperview]; + [CPSharedDragServer._dragWindow orderOut:nil]; + + if (CPDragServerDestination && + (![CPDragServerDestination respondsToSelector:@selector(prepareForDragOperation:)] || [CPDragServerDestination prepareForDragOperation:CPDragServerDraggingInfo]) && + (![CPDragServerDestination respondsToSelector:@selector(performDragOperation:)] || [CPDragServerDestination performDragOperation:CPDragServerDraggingInfo]) && + [CPDragServerDestination respondsToSelector:@selector(concludeDragOperation:)]) + [CPDragServerDestination concludeDragOperation:CPDragServerDraggingInfo]; + + if (CPDragServerShouldSendDraggedImageEndedAtOperation) + [CPDragServerSource draggedImage:[CPDragServerView image] endedAt:CPDragServerLocation operation:NO]; + else if (CPDragServerShouldSendDraggedViewEndedAtOperation) + [CPDragServerSource draggedView:CPDragServerView endedAt:CPDragServerLocation operation:NO]; + + CPDragServerIsDraggingImage = NO; + CPDragServerDestination = nil; + + return; + } + + // If we're not a mouse up, then we're going to want to grab the next event. + [CPApp setCallback:CPDragServerUpdateDragging + forNextEventMatchingMask:CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask + untilDate:nil inMode:0 dequeue:NO]; + + var location = [anEvent locationInWindow], + operation = + bridgeLocation = [[anEvent window] convertBaseToBridge:location]; + + // We have to convert base to bridge since the drag event comes from the source window, not the drag window. + var draggingDestination = [[CPDOMWindowBridge sharedDOMWindowBridge] _dragHitTest:bridgeLocation pasteboard:CPDragServerPasteboard]; + + CPDragServerLocation = [[CPDragServerDestination window] convertBridgeToBase:bridgeLocation]; + + if(draggingDestination != CPDragServerDestination) + { + if (CPDragServerDestination && [CPDragServerDestination respondsToSelector:@selector(draggingExited:)]) + [CPDragServerDestination draggingExited:CPDragServerDraggingInfo]; + + CPDragServerDestination = draggingDestination; + + if (CPDragServerDestination && [CPDragServerDestination respondsToSelector:@selector(draggingEntered:)]) + [CPDragServerDestination draggingEntered:CPDragServerDraggingInfo]; + } + else if (CPDragServerDestination && [CPDragServerDestination respondsToSelector:@selector(draggingUpdated:)]) + [CPDragServerDestination draggingUpdated:CPDragServerDraggingInfo]; + + location.x -= CPDragServerOffset.x; + location.y -= CPDragServerOffset.y; + + [CPDragServerView setFrameOrigin:location]; + + if (CPDragServerShouldSendDraggedImageMovedTo) + [CPDragServerSource draggedImage:[CPDragServerView image] movedTo:location]; + else if (CPDragServerShouldSendDraggedViewMovedTo) + [CPDragServerSource draggedView:CPDragServerView movedTo:location]; +} + +@implementation CPDraggingInfo : CPObject +{ + CPWindow _window; +} + +- (id)initWithWindow:(CPWindow)aWindow +{ + self = [super init]; + + if (self) + _window = aWindow; + + return this; +} + +- (id)draggingSource +{ + return CPDragServerSource; +} + +- (CPPoint)draggingLocation +{ + return CPDragServerLocation; +} + +- (CPPasteboard)draggingPasteboard +{ + return CPDragServerPasteboard; +} + +@end + +@implementation CPDragServer : CPObject +{ + CPWindow _dragWindow; + CPImageView _imageView; +} + ++ (void)initialize +{ + if (self != [CPDragServer class]) + return; + + CPDragServerDraggingInfo = [[CPDraggingInfo alloc] init]; +} + ++ (CPDragServer)sharedDragServer +{ + if (!CPSharedDragServer) + CPSharedDragServer = [[CPDragServer alloc] init]; + + return CPSharedDragServer; +} + +- (id)init +{ + self = [super init]; + + if (self) + { + _dragWindow = [[CPWindow alloc] initWithContentRect:CPRectMakeZero() styleMask:CPBorderlessWindowMask]; + [_dragWindow setLevel:CPDraggingWindowLevel]; + } + + return self; +} + +- (void)dragView:(CPView)aView fromWindow:(CPWindow)aWindow at:(CPPoint)viewLocation offset:(CPSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack +{ + var eventLocation = [anEvent locationInWindow]; + + CPDragServerView = aView; + CPDragServerSource = aSourceObject; + CPDragServerWindow = aWindow; + CPDragServerOffset = CPPointMake(eventLocation.x - viewLocation.x, eventLocation.y - viewLocation.y); + CPDragServerPasteboard = [CPPasteboard pasteboardWithName:CPDragPboard];//aPasteboard; + + [_dragWindow setFrameSize:CGSizeMakeCopy([[CPDOMWindowBridge sharedDOMWindowBridge] frame].size)]; + [_dragWindow orderFront:self]; + + [aView setFrameOrigin:viewLocation]; + [[_dragWindow contentView] addSubview:aView]; + + if (CPDragServerIsDraggingImage) + { + if ([CPDragServerSource respondsToSelector:@selector(draggedImage:beganAt:)]) + [CPDragServerSource draggedImage:[aView image] beganAt:viewLocation]; + + CPDragServerShouldSendDraggedImageMovedTo = [CPDragServerSource respondsToSelector:@selector(draggedImage:movedTo:)]; + CPDragServerShouldSendDraggedImageEndedAtOperation = [CPDragServerSource respondsToSelector:@selector(draggedImage:endAt:operation:)]; + + CPDragServerShouldSendDraggedViewMovedTo = NO; + CPDragServerShouldSendDraggedViewEndedAtOperation = NO; + } + else + { + if ([CPDragServerSource respondsToSelector:@selector(draggedView:beganAt:)]) + [CPDragServerSource draggedView:aView beganAt:viewLocation]; + + CPDragServerShouldSendDraggedViewMovedTo = [CPDragServerSource respondsToSelector:@selector(draggedView:movedTo:)]; + CPDragServerShouldSendDraggedViewEndedAtOperation = [CPDragServerSource respondsToSelector:@selector(draggedView:endedAt:operation:)]; + + + CPDragServerShouldSendDraggedImageMovedTo = NO; + CPDragServerShouldSendDraggedImageEndedAtOperation = NO; + } + + CPDragServerStartDragging(anEvent); +} + +- (void)dragImage:(CPImage)anImage fromWindow:(CPWindow)aWindow at:(CPPoint)imageLocation offset:(CPSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack +{ + CPDragServerIsDraggingImage = YES; + + if (!_imageView) + _imageView = [[CPImageView alloc] initWithFrame:CPRectMakeZero()]; + + [_imageView setImage:anImage]; + [_imageView setFrameSize:CGSizeMakeCopy([anImage size])]; + + [self dragView:_imageView fromWindow:aWindow at:imageLocation offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack]; +} + +@end + +@implementation CPView (CPDraggingAdditions) + +- (CPView)_dragHitTest:(CPPoint)aPoint pasteboard:(CPPasteboard)aPasteboard +{ + if(!CPRectContainsPoint(_frame, aPoint) || self == CPDragServerView) + return nil; + + var view = nil, + i = [_subviews count], + adjustedPoint = CPPointMake(aPoint.x - CPRectGetMinX(_frame), aPoint.y - CPRectGetMinY(_frame)); + + while (i--) + if (view = [_subviews[i] _dragHitTest:adjustedPoint pasteboard:aPasteboard]) + return view; + + if ([aPasteboard availableTypeFromArray:_registeredDraggedTypes]) + return self; + + return nil; +} + +@end diff --git a/AppKit/CPEvent.j b/AppKit/CPEvent.j new file mode 100644 index 000000000..56d5469cc --- /dev/null +++ b/AppKit/CPEvent.j @@ -0,0 +1,326 @@ +/* + * CPEvent.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + +#include "CoreGraphics/CGGeometry.h" + + +CPLeftMouseDown = 1; +CPLeftMouseUp = 2; +CPRightMouseDown = 3; +CPRightMouseUp = 4; +CPMouseMoved = 5; +CPLeftMouseDragged = 6; +CPRightMouseDragged = 7; +CPMouseEntered = 8; +CPMouseExited = 9; +CPKeyDown = 10; +CPKeyUp = 11; +CPFlagsChanged = 12; +CPAppKitDefined = 13; +CPSystemDefined = 14; +CPApplicationDefined = 15; +CPPeriodic = 16; +CPCursorUpdate = 17; +CPScrollWheel = 22; +CPOtherMouseDown = 25; +CPOtherMouseUp = 26; +CPOtherMouseDragged = 27; + +CPAlphaShiftKeyMask = 1 << 16; +CPShiftKeyMask = 1 << 17; +CPControlKeyMask = 1 << 18; +CPAlternateKeyMask = 1 << 19; +CPCommandKeyMask = 1 << 20; +CPNumericPadKeyMask = 1 << 21; +CPHelpKeyMask = 1 << 22; +CPFunctionKeyMask = 1 << 23; +CPDeviceIndependentModifierFlagsMask = 0xffff0000; + +CPLeftMouseDownMask = 1 << CPLeftMouseDown; +CPLeftMouseUpMask = 1 << CPLeftMouseUp; +CPRightMouseDownMask = 1 << CPRightMouseDown; +CPRightMouseUpMask = 1 << CPRightMouseUp; +CPOtherMouseDownMask = 1 << CPOtherMouseDown; +CPOtherMouseUpMask = 1 << CPOtherMouseUp; +CPMouseMovedMask = 1 << CPMouseMoved; +CPLeftMouseDraggedMask = 1 << CPLeftMouseDragged; +CPRightMouseDraggedMask = 1 << CPRightMouseDragged; +CPOtherMouseDragged = 1 << CPOtherMouseDragged; +CPMouseEnteredMask = 1 << CPMouseEntered; +CPMouseExitedMask = 1 << CPMouseExited; +CPCursorUpdateMask = 1 << CPCursorUpdate; +CPKeyDownMask = 1 << CPKeyDown; +CPKeyUpMask = 1 << CPKeyUp; +CPFlagsChangedMask = 1 << CPFlagsChanged; +CPAppKitDefinedMask = 1 << CPAppKitDefined; +CPSystemDefinedMask = 1 << CPSystemDefined; +CPApplicationDefinedMask = 1 << CPApplicationDefined; +CPPeriodicMask = 1 << CPPeriodic; +CPScrollWheelMask = 1 << CPScrollWheel; +CPAnyEventMask = 0xffffffff; + +CPDOMEventDoubleClick = "dblclick", +CPDOMEventMouseDown = "mousedown", +CPDOMEventMouseUp = "mouseup", +CPDOMEventMouseMoved = "mousemove", +CPDOMEventMouseDragged = "mousedrag", +CPDOMEventKeyUp = "keyup", +CPDOMEventKeyDown = "keydown", +CPDOMEventKeyPress = "keypress"; +CPDOMEventCopy = "copy"; +CPDOMEventPaste = "paste"; +CPDOMEventScrollWheel = "mousewheel"; + +var _CPEventPeriodicEventPeriod = 0, + _CPEventPeriodicEventTimer = nil; + +@implementation CPEvent : CPObject +{ + CPEventType _type; + CPPoint _location; + unsigned _modifierFlags; + CPTimeInterval _timestamp; + CPGraphicsContext _context; + int _eventNumber; + unsigned _clickCount; + float _pressure; + CPWindow _window; + CPString _characters; + CPString _charactersIgnoringModifiers + BOOL _isARepeat; + unsigned _keyCode; + DOMEvent _DOMEvent; + + float _deltaX; + float _deltaY; + float _deltaZ; +} + ++ (CPEvent)keyEventWithType:(CPEventType)anEventType location:(CPPoint)aPoint modifierFlags:(unsigned int)modifierFlags + timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext + characters:(CPString)characters charactersIgnoringModifiers:(CPString)unmodCharacters isARepeat:(BOOL)repeatKey keyCode:(unsigned short)code +{ + return [[self alloc] _initKeyEventWithType:anEventType location:aPoint modifierFlags:modifierFlags + timestamp:aTimestamp windowNumber:aWindowNumber context:aGraphicsContext + characters:characters charactersIgnoringModifiers:unmodCharacters isARepeat:repeatKey keyCode:code]; +} + ++ (id)mouseEventWithType:(CPEventType)anEventType location:(CPPoint)aPoint modifierFlags:(unsigned)modifierFlags + timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext + eventNumber:(int)anEventNumber clickCount:(int)aClickCount pressure:(float)aPressure +{ + return [[self alloc] _initMouseEventWithType:anEventType location:aPoint modifierFlags:modifierFlags + timestamp:aTimestamp windowNumber:aWindowNumber context:aGraphicsContext eventNumber:anEventNumber clickCount:aClickCount pressure:aPressure]; +} + ++ (CPEvent)otherEventWithType:(CPEventType)anEventType location:(CGPoint)aLocation modifierFlags:(unsigned)modifierFlags + timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext + subtype:(short)aSubtype data1:(int)aData1 data2:(int)aData2 +{ + return [[self alloc] _initOtherEventWithType:anEventType location:aLocation modifierFlags:modifierFlags + timestamp:aTimestamp windowNumber:aWindowNumber context:aGraphicsContext subtype:aSubtype data1:aData1 data2:aData2]; +} + +- (id)_initMouseEventWithType:(CPEventType)anEventType location:(CPPoint)aPoint modifierFlags:(unsigned)modifierFlags + timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext + eventNumber:(int)anEventNumber clickCount:(int)aClickCount pressure:(float)aPressure +{ + self = [super init]; + + if (self) + { + _type = anEventType; + _location = CPPointCreateCopy(aPoint); + _modifierFlags = modifierFlags; + _timestamp = aTimestamp; + _context = aGraphicsContext; + _eventNumber = anEventNumber; + _clickCount = aClickCount; + _pressure = aPressure; + _window = [CPApp windowWithWindowNumber:aWindowNumber]; + } + + return self; +} + +- (id)_initKeyEventWithType:(CPEventType)anEventType location:(CPPoint)aPoint modifierFlags:(unsigned int)modifierFlags + timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext + characters:(CPString)characters charactersIgnoringModifiers:(CPString)unmodCharacters isARepeat:(BOOL)isARepeat keyCode:(unsigned short)code +{ + self = [super init]; + + if (self) + { + _type = anEventType; + _location = CPPointCreateCopy(aPoint); + _modifierFlags = modifierFlags; + _timestamp = aTimestamp; + _context = aGraphicsContext; + _characters = characters; + _charactersIgnoringModifiers = unmodCharacters; + _isARepeat = isARepeat; + _keyCode = code; + _window = [CPApp windowWithWindowNumber:aWindowNumber]; + } + + return self; +} + +- (id)_initOtherEventWithType:(CPEventType)anEventType location:(CGPoint)aPoint modifierFlags:(unsigned)modifierFlags + timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext + subtype:(short)aSubtype data1:(int)aData1 data2:(int)aData2 +{ + self = [super init]; + + if (self) + { + _type = anEventType; + _location = CPPointCreateCopy(aPoint); + _modifierFlags = modifierFlags; + _timestamp = aTimestamp; + _context = aGraphicsContext; + _subtype = aSubtype; + _data1 = aData1; + _data2 = aData2; + } + + return self; +} + +- (CPPoint)locationInWindow +{ + return _location; +} + +- (unsigned)modifierFlags +{ + return _modifierFlags; +} + +- (CPTimeInterval)timestamp +{ + return _timestamp; +} + +- (CPEventType)type +{ + return _type; +} + +- (CPWindow)window +{ + return _window; +} + +- (int)windowNumber +{ + return _windowNumber; +} + +// Mouse Event Information + +- (int)buttonNumber +{ + return _buttonNumber; +} + +- (int)clickCount +{ + return _clickCount; +} + +- (CPString)characters +{ + return _characters; +} + +- (CPString)charactersIgnoringModifiers +{ + return _charactersIgnoringModifiers; +} + +- (BOOL)isARepeat +{ + return _isARepeat; +} + +- (unsigned short)keyCode +{ + return _keyCode; +} + +- (float)pressure +{ + return _pressure; +} + +- (DOMEvent)_DOMEvent +{ + return _DOMEvent; +} + +// Getting Scroll Wheel Event Infomration + +- (float)deltaX +{ + return _deltaX; +} + +- (float)deltaY +{ + return _deltaY; +} + +- (float)deltaZ +{ + return _deltaZ; +} + ++ (void)startPeriodicEventsAfterDelay:(CPTimeInterval)aDelay withPeriod:(CPTimeInterval)aPeriod +{ + _CPEventPeriodicEventPeriod = aPeriod; + + // FIXME: OH TIMERS!!! + _CPEventPeriodicEventTimer = window.setTimeout(function() { _CPEventPeriodicEventTimer = window.setInterval(_CPEventFirePeriodEvent, aPeriod * 1000.0); }, aDelay * 1000.0); +} + ++ (void)stopPeriodicEvents +{ + if (_CPEventPeriodicEventTimer === nil) + return; + + window.clearTimeout(_CPEventPeriodicEventTimer); + + _CPEventPeriodicEventTimer = nil; +} + +@end + +function _CPEventFirePeriodEvent() +{ + [CPApp sendEvent:[CPEvent otherEventWithType:CPPeriodic location:_CGPointMakeZero() modifierFlags:0 timestamp:0 windowNumber:0 context:nil subtype:0 data1:0 data2:0]]; + + [[CPRunLoop currentRunLoop] performSelectors]; +} + diff --git a/AppKit/CPFlashMovie.j b/AppKit/CPFlashMovie.j new file mode 100644 index 000000000..278d0664c --- /dev/null +++ b/AppKit/CPFlashMovie.j @@ -0,0 +1,46 @@ +/* + * CPFlashMovie.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + + +@implementation CPFlashMovie : CPObject +{ + CPString _fileName; +} + ++ (id)flashMovieWithFile:(CPString)aFileName +{ + return [[self alloc] initWithFile:aFileName]; +} + +- (id)initWithFile:(CPString)aFileName +{ + self = [super init]; + + if (self) + _fileName = aFileName; + + return self; +} + +@end \ No newline at end of file diff --git a/AppKit/CPFlashView.j b/AppKit/CPFlashView.j new file mode 100644 index 000000000..95db3b039 --- /dev/null +++ b/AppKit/CPFlashView.j @@ -0,0 +1,110 @@ +/* + * CPFlashView.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPDOMWindowBridge.j" +import "CPFlashMovie.j" +import "CPView.j" + + +@implementation CPFlashView : CPView +{ + CPFlashMovie _flashMovie; + + DOMElement _DOMEmbedElement; + DOMElement _DOMMParamElement; + DOMElement _DOMObjectElement; +} + +- (id)initWithFrame:(CGRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _DOMObjectElement = document.createElement("object"); + _DOMObjectElement.width = "100%"; + _DOMObjectElement.height = "100%"; + _DOMObjectElement.style.top = "0px"; + _DOMObjectElement.style.left = "0px"; + + _DOMParamElement = document.createElement("param"); + _DOMParamElement.name = "movie"; + + _DOMObjectElement.appendChild(_DOMParamElement); + + var param = document.createElement("param"); + + param.name = "wmode"; + param.value = "transparent"; + + _DOMObjectElement.appendChild(param); + + _DOMEmbedElement = document.createElement("embed"); + + _DOMEmbedElement.type = "application/x-shockwave-flash"; + _DOMEmbedElement.wmode = "transparent"; + _DOMEmbedElement.width = "100%"; + _DOMEmbedElement.height = "100%"; + + // IE requires this thing to be in the _DOMElement and not the _DOMObjectElement. + _DOMElement.appendChild(_DOMEmbedElement); + + _DOMElement.appendChild(_DOMObjectElement); + } + + return self; +} + +- (void)setFlashMovie:(CPFlashMovie)aFlashMovie +{ + if (_flashMovie == aFlashMovie) + return; + + _flashMovie = aFlashMovie; + + _DOMParamElement.value = aFlashMovie._fileName; + + if (_DOMEmbedElement) + _DOMEmbedElement.src = aFlashMovie._fileName; +} + +- (CPFlashMovie)flashMovie +{ + return _flashMovie; +} + +- (void)mouseDragged:(CPEvent)anEvent +{ + [[CPDOMWindowBridge sharedDOMWindowBridge] _propagateCurrentDOMEvent:YES]; +} + +- (void)mouseDown:(CPEvent)anEvent +{ + [[CPDOMWindowBridge sharedDOMWindowBridge] _propagateCurrentDOMEvent:YES]; +} + +- (void)mouseUp:(CPEvent)anEvent +{ + [[CPDOMWindowBridge sharedDOMWindowBridge] _propagateCurrentDOMEvent:YES]; +} + +@end diff --git a/AppKit/CPFont.j b/AppKit/CPFont.j new file mode 100644 index 000000000..fa247d67c --- /dev/null +++ b/AppKit/CPFont.j @@ -0,0 +1,112 @@ +/* + * CPFont.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +var _CPFonts = {}; + _CPFontSystemFontFace = @"Arial"; + +#define _CPCachedFont(aName, aSize, isBold) _CPFonts[(isBold ? @"bold " : @"") + ROUND(aSize) + @"px '" + aName + @"'"] + +@implementation CPFont : CPObject +{ + CPString _name; + float _size; + BOOL _isBold; + + CPString _cssString; +} + ++ (id)fontWithName:(CPString)aName size:(float)aSize +{ + return _CPCachedFont(aName, aSize, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:NO]; +} + ++ (id)boldFontWithName:(CPString)aName size:(float)aSize +{ + return _CPCachedFont(aName, aSize, YES) || [[CPFont alloc] _initWithName:aName size:aSize bold:YES]; +} + ++ (id)systemFontOfSize:(CPSize)aSize +{ + return _CPCachedFont(_CPFontSystemFontFace, aSize, NO) || [[CPFont alloc] _initWithName:_CPFontSystemFontFace size:aSize bold:NO]; +} + ++ (id)boldSystemFontOfSize:(CPSize)aSize +{ + return _CPCachedFont(_CPFontSystemFontFace, aSize, YES) || [[CPFont alloc] _initWithName:_CPFontSystemFontFace size:aSize bold:YES]; +} +// FIXME Font Descriptor +- (id)_initWithName:(CPString)aName size:(float)aSize bold:(BOOL)isBold +{ + self = [super init]; + + if (self) + { + _name = aName; + _size = aSize; + _isBold = isBold; + + _cssString = (_isBold ? @"bold " : @"") + ROUND(aSize) + @"px '" + aName + @"'"; + + _CPFonts[_cssString] = self; + } + + return self; +} + +- (float)size +{ + return _size; +} + +- (CPString)cssString +{ + return _cssString; +} + +- (CPString)familyName +{ + return _name; +} + +@end + +var CPFontNameKey = @"CPFontNameKey", + CPFontSizeKey = @"CPFontSizeKey", + CPFontIsBoldKey = @"CPFontIsBoldKey"; + +@implementation CPFont (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + return [self _initWithName:[aCoder decodeObjectForKey:CPFontNameKey] + size:[aCoder decodeFloatForKey:CPFontSizeKey] + bold:[aCoder decodeBoolForKey:CPFontIsBoldKey]]; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeObject:_name forKey:CPFontNameKey]; + [aCoder encodeFloat:_size forKey:CPFontSizeKey]; + [aCoder encodeBool:_isBold forKey:CPFontIsBoldKey]; +} + +@end diff --git a/AppKit/CPFontManager.j b/AppKit/CPFontManager.j new file mode 100644 index 000000000..0601129f5 --- /dev/null +++ b/AppKit/CPFontManager.j @@ -0,0 +1,158 @@ +/* + * CPFontManager.j + * AppKit + * + * Created by Tom Robinson. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + +import + + +var CPSharedFontManager = nil, + CPFontManagerFactory = Nil; + +@implementation CPFontManager : CPObject +{ + CPArray _availableFonts; +} + +// Getting the Shared Font Manager + ++ (id)sharedFontManager +{ + if (!CPSharedFontManager) + CPSharedFontManager = [[CPFontManagerFactory alloc] init]; + + return CPSharedFontManager; +} + +// Changing the Default Font Conversion Classes + ++ (void)setFontManagerFactory:(Class)aClass +{ + CPFontManagerFactory = aClass; +} + +- (CPArray)availableFonts +{ + if (!_availableFonts) + { + _CPFontDetectSpan = document.createElement("span"); + _CPFontDetectSpan.fontSize = "24px"; + _CPFontDetectSpan.appendChild(document.createTextNode("mmmmmmmmmml")); + var div = document.createElement("div"); + div.style.position = "absolute"; + div.style.top = "-1000px"; + div.appendChild(_CPFontDetectSpan); + document.getElementsByTagName("body")[0].appendChild(div); + + _CPFontDetectReferenceFonts = _CPFontDetectPickTwoDifferentFonts(["monospace", "serif", "sans-serif", "cursive"]); + + _availableFonts = []; + for (var i = 0; i < _CPFontDetectAllFonts.length; i++) { + var available = _CPFontDetectFontAvailable(_CPFontDetectAllFonts[i]); + if (available) + _availableFonts.push(_CPFontDetectAllFonts[i]); + } + } + return _availableFonts; +} + +- (CPArray)fontWithNameIsAvailable:(CPString)aFontName +{ + return _CPFontDetectFontAvailable(aFontName); +} + +@end + +var _CPFontDetectSpan, + _CPFontDetectReferenceFonts, + _CPFontDetectAllFonts = [ + /* "04b_21","A Charming Font","Abadi MT Condensed","Abadi MT Condensed Extra Bold","Abadi MT Condensed Light","Academy Engraved LET","Agency FB","Alba","Alba Matter","Alba Super","Algerian",*/ + "American Typewriter", + /* "Andale Mono","Andale Mono IPA","Andy", */ + "Apple Chancery","Arial","Arial Black","Arial Narrow","Arial Rounded MT Bold","Arial Unicode MS", + /* "Avant Garde","Avantgarde","Baby Kruffy","Base 02","Baskerville","Baskerville Old Face","Bauhaus 93","Beesknees ITC","Bell MT","Berlin Sans FB","Berlin Sans FB Demi","Bernard MT Condensed","Bickley Script",*/ + "Big Caslon","Bitstream Vera Sans","Bitstream Vera Sans Mono","Bitstream Vera Serif", + /* "Blackadder ITC","Blackletter686 BT","Bodoni MT","Bodoni MT Black","Bodoni MT Condensed","Bodoni MT Poster Compressed","Book Antiqua","Bookman","Bookman Old Style","Bradley Hand ITC","Braggadocio","Britannic Bold","Broadway","Broadway BT",*/ + "Brush Script MT", + /* "BudHand","CAMPBELL","Calibri","Californian FB","Calisto MT","Calligraph421 BT",*/ + "Cambria", + /* "Candara","Capitals",*/ + "Caslon","Castellar","Cataneo BT","Centaur","Century Gothic","Century Schoolbook","Century Schoolbook L", + /* "Champignon","Charcoal","Charter","Charter BT","Chicago","Chick","Chiller","ClearlyU","Colonna MT",*/ + "Comic Sans", "Comic Sans MS","Consolas","Constantia","Cooper Black","Copperplate","Copperplate Gothic Bold","Copperplate Gothic Light","Corbel","Courier","Courier New", + /* "Croobie","Curlz MT","Desdemona","Didot","DomBold BT","Edwardian Script ITC","Engravers MT","Eras Bold ITC","Eras Demi ITC","Eras Light ITC","Eras Medium ITC","Eurostile","FIRSTHOME","Fat","Felix Titling","Fine Hand","Fixed","Footlight MT Light","Forte","Franklin Gothic Book","Franklin Gothic Demi","Franklin Gothic Demi Cond","Franklin Gothic Heavy","Franklin Gothic Medium","Franklin Gothic Medium Cond","Freestyle Script","French Script MT","Freshbot","Frosty",*/ + "Futura", + /* "GENUINE","Gadget","Garamond",*/ + "Geneva","Georgia","Georgia Ref", "Geeza Pro", "Gigi","Gill Sans","Gill Sans MT","Gill Sans MT Condensed","Gill Sans MT Ext Condensed Bold","Gill Sans Ultra Bold","Gill Sans Ultra Bold Condensed", + /* "GlooGun","Gloucester MT Extra Condensed","Goudy Old Style","Goudy Stout","Haettenschweiler","Harlow Solid Italic","Harrington",*/ + "Helvetica","Helvetica Narrow","Helvetica Neue","Herculanum","High Tower Text","Highlight LET","Hoefler Text","Impact","Imprint MT Shadow", + /* "Informal Roman","Jenkins v2.0","John Handy LET","Jokerman","Jokerman LET","Jokewood","Juice ITC","Kabel Ult BT","Kartika","Kino MT","Kristen ITC","Kunstler Script","La Bamba LET", */ + "Lucida","Lucida Bright","Lucida Calligraphy","Lucida Console","Lucida Fax","Lucida Grande","Lucida Handwriting","Lucida Sans","Lucida Sans Typewriter","Lucida Sans Unicode", + /* "Luxi Mono","Luxi Sans","Luxi Serif","MARKETPRO","MS Reference Sans Serif","MS Reference Serif","Magneto","Maiandra GD", */ + "Marker Felt", + /* "Matisse ITC","Matura MT Script Capitals","Mead Bold","Mekanik LET","Mercurius Script MT Bold", */ + "Microsoft Sans Serif","Milano LET","Minion Web","MisterEarl BT","Mistral","Monaco","Monotype Corsiva","Monotype.com","New Century Schoolbook","New York","News Gothic MT", + /* "Niagara Engraved","Niagara Solid","Nimbus Mono L","Nimbus Roman No9 L","OCR A Extended","OCRB","Odessa LET","Old English Text MT","OldDreadfulNo7 BT","One Stroke Script LET","Onyx","Optima","Orange LET","Palace Script MT","Palatino","Palatino Linotype", */ + "Papyrus", + /* "ParkAvenue BT","Pepita MT","Perpetua","Perpetua Titling MT","Placard Condensed","Playbill","Poornut","Pristina","Pump Demi Bold LET","Pussycat","Quixley LET","Rage Italic","Rage Italic LET","Ravie","Rockwell","Rockwell Condensed","Rockwell Extra Bold","Ruach LET","Runic MT Condensed","Sand","Script MT Bold","Scruff LET","Segoe UI","Showcard Gothic","Skia","Smudger LET","Snap ITC","Square721 BT","Staccato222 BT","Stencil","Sylfaen", */ + "Tahoma","Techno","Tempus Sans ITC","Terminal","Textile","Times","Times New Roman","Tiranti Solid LET","Trebuchet MS", + /* "Tw Cen MT","Tw Cen MT Condensed","Tw Cen MT Condensed Extra Bold","URW Antiqua T","URW Bookman L","URW Chancery L","URW Gothic L","URW Palladio L","Univers","University Roman LET","Utopia", */ + "Verdana","Verdana Ref", /* "Victorian LET","Viner Hand ITC","Vivaldi","Vladimir Script","Vrinda","Weltron Urban","Westwood LET","Wide Latin","Zapf Chancery", */ + "Zapfino"]; + +// Compare against the reference fonts. Return true if it produces a different size than at least one of them. +var _CPFontDetectFontAvailable = function(font) { + for (var i = 0; i < _CPFontDetectReferenceFonts.length; i++) + if (_CPFontDetectCompareFonts(_CPFontDetectReferenceFonts[i], font)) + return true; + return false; +} + +var _CPFontDetectCache = {}; + +// Compares two given fonts. Returns true if they produce different sizes (i.e. fontA didn't fallback to fontB) +var _CPFontDetectCompareFonts = function(fontA, fontB) { + var a; + if (_CPFontDetectCache[fontA]) { + a = _CPFontDetectCache[fontA]; + } else { + _CPFontDetectSpan.style.fontFamily = '"' + fontA + '"'; + _CPFontDetectCache[fontA] = a = { w: _CPFontDetectSpan.offsetWidth, h: _CPFontDetectSpan.offsetHeight }; + } + + _CPFontDetectSpan.style.fontFamily= '"' + fontB + '", "' + fontA + '"'; + var bWidth = _CPFontDetectSpan.offsetWidth; + var bHeight = _CPFontDetectSpan.offsetHeight; + + return (a.w != bWidth || a.h != bHeight); +} + +// Test the candidate fonts pairwise until we find two that are different. Otherwise return the first. +var _CPFontDetectPickTwoDifferentFonts = function(candidates) { + for (var i = 0; i < candidates.length; i++) + for (var j = 0; j < i; j++) + if (_CPFontDetectCompareFonts(candidates[i], candidates[j])) + return [candidates[i], candidates[j]]; + return [candidates[0]]; +} + +[CPFontManager setFontManagerFactory:[CPFontManager class]]; diff --git a/AppKit/CPGeometry.j b/AppKit/CPGeometry.j new file mode 100644 index 000000000..74a6e8834 --- /dev/null +++ b/AppKit/CPGeometry.j @@ -0,0 +1,264 @@ +/* + * CPGeometry.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CGGeometry.j" + +CPMinXEdge = 0; +CPMinYEdge = 1; +CPMaxXEdge = 2; +CPMaxYEdge = 3; + +// FIXME: the rest! +CPMakePoint = CGPointMake; +CPMakeSize = CGSizeMake; +CPMakeRect = CGRectMake; + +function CPPointCreateCopy(aPoint) +{ + return { x: aPoint.x, y: aPoint.y }; +} + +function CPPointMake(x, y) +{ + return { x: x, y: y }; +} + +function CPRectInset(aRect, dX, dY) +{ + return CPRectMake( aRect.origin.x + dX, aRect.origin.y + dY, + aRect.size.width - 2 * dX, aRect.size.height - 2*dY); +} + +function CPRectIntegral(aRect) +{ + // FIXME!!! + alert("CPRectIntegral unimplemented"); +} + +function CPRectIntersection(lhsRect, rhsRect) +{ + var intersection = CPRectMake( + Math.max(CPRectGetMinX(lhsRect), CPRectGetMinX(rhsRect)), + Math.max(CPRectGetMinY(lhsRect), CPRectGetMinY(rhsRect)), + 0, 0); + + intersection.size.width = Math.min(CPRectGetMaxX(lhsRect), CPRectGetMaxX(rhsRect)) - CPRectGetMinX(intersection); + intersection.size.height = Math.min(CPRectGetMaxY(lhsRect), CPRectGetMaxY(rhsRect)) - CPRectGetMinY(intersection); + + return CPRectIsEmpty(intersection) ? CPRectMakeZero() : intersection; +} + +function CPRectCreateCopy(aRect) +{ + return { origin: CPPointCreateCopy(aRect.origin), size: CPSizeCreateCopy(aRect.size) }; +} + +function CPRectMake(x, y, width, height) +{ + return { origin: CPPointMake(x, y), size: CPSizeMake(width, height) }; +} + +function CPRectOffset(aRect, dX, dY) +{ + return CPRectMake(aRect.origin.x + dX, aRect.origin.y + dY, aRect.size.width, aRect.size.height); +} + +function CPRectStandardize(aRect) +{ + var width = CPRectGetWidth(aRect), + height = CPRectGetHeight(aRect), + standardized = CPRectCreateCopy(aRect); + + if (width < 0.0) + { + standardized.origin.x += width; + standardized.size.width = -width; + } + + if (height < 0.0) + { + standardized.origin.y += height; + standardized.size.height = -height; + } + + return standardized; +} + +function CPRectUnion(lhsRect, rhsRect) +{ + var minX = Math.min(CPRectGetMinX(lhsRect), CPRectGetMinX(rhsRect)), + minY = Math.min(CPRectGetMinY(lhsRect), CPRectGetMinY(rhsRect)), + maxX = Math.max(CPRectGetMaxX(lhsRect), CPRectGetMaxX(rhsRect)), + maxY = Math.max(CPRectGetMaxY(lhsRect), CPRectGetMaxY(rhsRect)); + + return CPRectMake(minX, minY, maxX - minX, maxY - minY); +} + +function CPSizeCreateCopy(aSize) +{ + return { width: aSize.width, height: aSize.height }; +} + +function CPSizeMake(width, height) +{ + return { width: width, height: height }; +} + +function CPRectContainsPoint(aRect, aPoint) +{ + return aPoint.x >= CPRectGetMinX(aRect) && + aPoint.y >= CPRectGetMinY(aRect) && + aPoint.x < CPRectGetMaxX(aRect) && + aPoint.y < CPRectGetMaxY(aRect); +} + +function CPRectContainsRect(lhsRect, rhsRect) +{ + return CPRectEqualToRect(CPUnionRect(lhsRect, rhsRect), rhsRect); +} + +function CPPointEqualToPoint(lhsPoint, rhsPoint) +{ + return lhsPoint.x == rhsPoint.x && lhsPoint.y == rhsPoint.y; +} + +function CPRectEqualToRect(lhsRect, rhsRect) +{ + return CPPointEqualToPoint(lhsRect.origin, rhsRect.origin) && + CPSizeEqualToSize(lhsRect.size, rhsRect.size); +} + +function CPRectGetHeight(aRect) +{ + return aRect.size.height; +} + +function CPRectGetMaxX(aRect) +{ + return aRect.origin.x + aRect.size.width; +} + +function CPRectGetMaxY(aRect) +{ + return aRect.origin.y + aRect.size.height; +} + +function CPRectGetMidX(aRect) +{ + return aRect.origin.x + (aRect.size.width) / 2.0; +} + +function CPRectGetMidY(aRect) +{ + return aRect.origin.y + (aRect.size.height) / 2.0; +} + +function CPRectGetMinX(aRect) +{ + return aRect.origin.x; +} + +function CPRectGetMinY(aRect) +{ + return aRect.origin.y; +} + +function CPRectGetWidth(aRect) +{ + return aRect.size.width; +} + +function CPRectIntersectsRect(lhsRect, rhsRect) +{ + return !CPRectIsEmpty(CPRectIntersection(lhsRect, rhsRect)); +} + +function CPRectIsEmpty(aRect) +{ + return aRect.size.width <= 0.0 || aRect.size.height <= 0.0; +} + +function CPRectIsNull(aRect) +{ + return aRect.size.width <= 0.0 || aRect.size.height <= 0.0; +} + +function CPSizeEqualToSize(lhsSize, rhsSize) +{ + return lhsSize.width == rhsSize.width && lhsSize.height == rhsSize.height; +} + +function CPStringFromPoint(aPoint) +{ + return "{" + aPoint.x + ", " + aPoint.y + "}"; +} + +function CPStringFromSize(aSize) +{ + return "{" + aSize.width + ", " + aSize.height + "}"; +} + +function CPStringFromRect(aRect) +{ + return "{" + CPStringFromPoint(aRect.origin) + ", " + CPStringFromSize(aRect.size) + "}"; +} + +function CPPointFromString(aString) +{ + var comma = aString.indexOf(','); + + return { x:parseInt(aString.substr(1, comma - 1)), y:parseInt(aString.substring(comma + 1, aString.length)) }; +} + +function CPSizeFromString(aString) +{ + var comma = aString.indexOf(','); + + return { width:parseInt(aString.substr(1, comma - 1)), height:parseInt(aString.substring(comma + 1, aString.length)) }; +} + +function CPRectFromString(aString) +{ + var comma = aString.indexOf(',', aString.indexOf(',') + 1); + + return { origin:CPPointFromString(aString.substr(1, comma - 1)), size:CPSizeFromString(aString.substring(comma + 2, aString.length)) }; +} + +function CPPointFromEvent(anEvent) +{ + return CPPointMake(anEvent.clientX, anEvent.clientY, 0); +} + +function CPSizeMakeZero() +{ + return CPSizeMake(0, 0); +} + +function CPRectMakeZero() +{ + return CPRectMake(0, 0, 0, 0); +} + +function CPPointMakeZero() +{ + return CPPointMake(0, 0, 0); +} diff --git a/AppKit/CPGraphicsContext.j b/AppKit/CPGraphicsContext.j new file mode 100644 index 000000000..6b4d77f1d --- /dev/null +++ b/AppKit/CPGraphicsContext.j @@ -0,0 +1,60 @@ +/* + * CPGraphicsContext.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +var CPGraphicsContextCurrent = nil; + +@implementation CPGraphicsContext : CPObject +{ + CPContext _graphicsPort; +} + ++ (void)currentContext +{ + return CPGraphicsContextCurrent; +} + ++ (void)setCurrentContext:(CPGraphicsContext)aGraphicsContext +{ + CPGraphicsContextCurrent = aGraphicsContext; +} + ++ (id)graphicsContextWithGraphicsPort:(CPContext)aContext flipped:(BOOL)aFlag +{ + return [[self alloc] initWithGraphicsPort:aContext]; +} + +- (id)initWithGraphicsPort:(CPContext)aGraphicsPort +{ + self = [super init]; + + if (self) + _graphicsPort = aGraphicsPort; + + return self; +} + +- (CPContext)graphicsPort +{ + return _graphicsPort; +} + +@end diff --git a/AppKit/CPImage.j b/AppKit/CPImage.j new file mode 100644 index 000000000..2089602a4 --- /dev/null +++ b/AppKit/CPImage.j @@ -0,0 +1,323 @@ +/* + * CPImage.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import +import +import + +import "CPGeometry.j" + +CPImageLoadStatusInitialized = 0; +CPImageLoadStatusLoading = 1; +CPImageLoadStatusCompleted = 2; +CPImageLoadStatusCancelled = 3; +CPImageLoadStatusInvalidData = 4; +CPImageLoadStatusUnexpectedEOF = 5; +CPImageLoadStatusReadError = 6; + +@implementation CPBundle (CPImageAdditions) + +- (CPString)pathForResource:(CPString)aFilename +{ + return [self bundlePath] + "Resources/" + aFilename; +} + +@end + +@implementation CPImage : CPObject +{ + CPSize _size; + CPString _filename; + + id _delegate; + unsigned _loadStatus; + + Image _image; +} + +- (CPImage)initByReferencingFile:(CPString)aFilename size:(CPSize)aSize +{ + self = [super init]; + + if (self) + { + _size = CPSizeCreateCopy(aSize); + _filename = aFilename; + _loadStatus = CPImageLoadStatusInitialized; + } + + return self; +} + +- (CPImage)initWithContentsOfFile:(CPString)aFilename size:(CPSize)aSize +{ + self = [self initByReferencingFile:aFilename size:aSize]; + + if (self) + [self load]; + + return self; +} + +- (CPImage)initWithContentsOfFile:(CPString)aFilename +{ + self = [self initByReferencingFile:aFilename size: CGSizeMake(-1, -1)]; + + if (self) + [self load]; + + return self; +} + +- (CPString)filename +{ + return _filename; +} + +- (void)setSize:(CPSize)aSize +{ + _size = CGSizeMakeCopy(aSize); +} + +- (CGSize)size +{ + return _size; +} + +- (void)setDelegate:(id)aDelegate +{ + _delegate = aDelegate; +} + +- (id)delegate +{ + return _delegate; +} + +- (BOOL)loadStatus +{ + return _loadStatus; +} + +- (void)load +{ + if (_loadStatus == CPImageLoadStatusLoading || _loadStatus == CPImageLoadStatusCompleted) + return; + + _loadStatus = CPImageLoadStatusLoading; + + _image = new Image(); + + var isSynchronous = YES; + + // FIXME: We need a better/performance way of doing this. + _image.onload = function () { if (isSynchronous) window.setTimeout(function() { [self _imageDidLoad] }, 0); else [self _imageDidLoad]; } + _image.onerror = function () { if (isSynchronous) window.setTimeout(function() { [self _imageDidError] }, 0); else [self _imageDidError]; } + _image.onabort = function () { if (isSynchronous) window.setTimeout(function() { [self _imageDidAbort] }, 0); else [self _imageDidAbort]; } + + _image.src = _filename; + + isSynchronous = NO; +} + +- (BOOL)isThreePartImage +{ + return NO; +} + +- (BOOL)isNinePartImage +{ + return NO; +} + +- (void)_imageDidLoad +{ + _loadStatus = CPImageLoadStatusCompleted; + + // FIXME: IE is wrong on image sizes???? + if (!_size || (_size.width == -1 && _size.height == -1)) + _size = CGSizeMake(_image.width, _image.height); + + if ([_delegate respondsToSelector:@selector(imageDidLoad:)]) + [_delegate imageDidLoad:self]; + + [[CPRunLoop currentRunLoop] performSelectors]; +} + +- (void)_imageDidError +{ + _loadStatus = CPImageLoadStatusReadError; + + if ([_delegate respondsToSelector:@selector(imageDidError:)]) + [_delegate imageDidError:self]; + + [[CPRunLoop currentRunLoop] performSelectors]; +} + +- (void)_imageDidAbort +{ + _loadStatus = CPImageLoadStatusCancelled; + + if ([_delegate respondsToSelector:@selector(imageDidAbort:)]) + [_delegate imageDidAbort:self]; + + [[CPRunLoop currentRunLoop] performSelectors]; +} + +@end + +@implementation CPImage (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + return [self initWithContentsOfFile:[aCoder decodeObjectForKey:@"CPFilename"] size:[aCoder decodeSizeForKey:@"CPSize"]]; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeObject:_filename forKey:@"CPFilename"]; + [aCoder encodeSize:_size forKey:@"CPSize"]; +} + +@end + +@implementation CPThreePartImage : CPObject +{ + CPArray _imageSlices; + BOOL _isVertical; +} + +- (id)initWithImageSlices:(CPArray)imageSlices isVertical:(BOOL)isVertical +{ + self = [super init]; + + if (self) + { + _imageSlices = imageSlices; + _isVertical = isVertical; + } + + return self; +} + +- (CPArray)imageSlices +{ + return _imageSlices; +} + +- (BOOL)isVertical +{ + return _isVertical; +} + +- (BOOL)isThreePartImage +{ + return YES; +} + +- (BOOL)isNinePartImage +{ + return NO; +} + +@end + +var CPThreePartImageImageSlicesKey = @"CPThreePartImageImageSlicesKey", + CPThreePartImageIsVerticalKey = @"CPThreePartImageIsVerticalKey"; + +@implementation CPThreePartImage (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super init]; + + if (self) + { + _imageSlices = [aCoder decodeObjectForKey:CPThreePartImageImageSlicesKey]; + _isVertical = [aCoder decodeBoolForKey:CPThreePartImageIsVerticalKey]; + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeObject:_imageSlices forKey:CPThreePartImageImageSlicesKey]; + [aCoder encodeBool:_isVertical forKey:CPThreePartImageIsVerticalKey]; +} + +@end + + +@implementation CPNinePartImage : CPObject +{ + CPArray _imageSlices; +} + +- (id)initWithImageSlices:(CPArray)imageSlices +{ + self = [super init]; + + if (self) + _imageSlices = imageSlices; + + return self; +} + +- (CPArray)imageSlices +{ + return _imageSlices; +} + +- (BOOL)isThreePartImage +{ + return NO; +} + +- (BOOL)isNinePartImage +{ + return YES; +} + +@end + +var CPNinePartImageImageSlicesKey = @"CPNinePartImageImageSlicesKey"; + +@implementation CPNinePartImage (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super init]; + + if (self) + _imageSlices = [aCoder decodeObjectForKey:CPNinePartImageImageSlicesKey]; + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeObject:_imageSlices forKey:CPNinePartImageImageSlicesKey]; +} + +@end diff --git a/AppKit/CPImageView.j b/AppKit/CPImageView.j new file mode 100644 index 000000000..d39f3f4b1 --- /dev/null +++ b/AppKit/CPImageView.j @@ -0,0 +1,307 @@ +/* + * CPImageView.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPImage.j" +import "CPControl.j" +import "CPShadowView.j" + +#include "Platform/Platform.h" +#include "Platform/DOM/CPDOMDisplayServer.h" + +#include "CoreGraphics/CGGeometry.h" + + +CPScaleProportionally = 0; +CPScaleToFit = 1; +CPScaleNone = 2; + + +var CPImageViewShadowBackgroundColor = nil; + +var LEFT_SHADOW_INSET = 3.0, + RIGHT_SHADOW_INSET = 3.0, + TOP_SHADOW_INSET = 3.0, + BOTTOM_SHADOW_INSET = 5.0, + VERTICAL_SHADOW_INSET = TOP_SHADOW_INSET + BOTTOM_SHADOW_INSET, + HORIZONTAL_SHADOW_INSET = LEFT_SHADOW_INSET + RIGHT_SHADOW_INSET; + +@implementation CPImageView : CPControl +{ + CPImage _image; + DOMElement _DOMImageElement; + + CPImageScaling _imageScaling; + + BOOL _hasShadow; + CPView _shadowView; + + CGRect _imageRect; +} + +- (id)initWithFrame:(CGRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { +#if PLATFORM(DOM) + _DOMImageElement = document.createElement("img"); + _DOMImageElement.style.position = "absolute"; + _DOMImageElement.style.left = "0px"; + _DOMImageElement.style.top = "0px"; + + CPDOMDisplayServerAppendChild(_DOMElement, _DOMImageElement); + + _DOMImageElement.style.visibility = "hidden"; +#endif + } + + return self; +} + +- (CPImage)image +{ + return _image; +} + +- (void)setImage:(CPImage)anImage +{ + if (_image == anImage) + return; + + _image = anImage; + + _DOMImageElement.src = [anImage filename]; + + if (_imageScaling == CPScaleNone && _image) + { + var size = [_image size]; + + _DOMImageElement.width = ROUND(size.width); + _DOMImageElement.height = ROUND(size.height); + } + + [self hideOrDisplayContents]; + + [self tile]; +} + +- (void)setHasShadow:(BOOL)shouldHaveShadow +{ + if (_hasShadow == shouldHaveShadow) + return; + + _hasShadow = shouldHaveShadow; + + if (_hasShadow) + { + _shadowView = [[CPShadowView alloc] initWithFrame:[self bounds]]; + + [self addSubview:_shadowView]; + + [self tile]; + } + else + { + [_shadowView removeFromSuperview]; + + _shadowView = nil; + } + + [self hideOrDisplayContents]; +} + +- (void)setImageScaling:(CPImageScaling)anImageScaling +{ + if (_imageScaling == anImageScaling) + return; + + _imageScaling = anImageScaling; + + if (_imageScaling == CPScaleToFit) + { + CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, 0.0, 0.0); + } + else if (_imageScaling == CPScaleNone && _image) + { + var size = [_image size]; + + _DOMImageElement.width = ROUND(size.width); + _DOMImageElement.height = ROUND(size.height); + } + + [self tile]; +} + +- (CPImageScaling)imageScaling +{ + return _imageScaling; +} + +- (void)setFrameSize:(CGSize)aSize +{ + [super setFrameSize:aSize]; + + [self tile]; +} + +- (void)hideOrDisplayContents +{ + if (!_image) + { + _DOMImageElement.style.visibility = "hidden"; + [_shadowView setHidden:YES]; + } + else + { + _DOMImageElement.style.visibility = "visible"; + [_shadowView setHidden:NO]; + } +} + +- (CGRect)imageRect +{ + return _imageRect; +} + +- (void)tile +{ + if (!_image) + return; + + var bounds = [self bounds], + x = 0.0, + y = 0.0, + insetWidth = (_hasShadow ? HORIZONTAL_SHADOW_INSET : 0.0), + insetHeight = (_hasShadow ? VERTICAL_SHADOW_INSET : 0.0), + boundsWidth = _CGRectGetWidth(bounds), + boundsHeight = _CGRectGetHeight(bounds), + width = boundsWidth - insetWidth, + height = boundsHeight - insetHeight; + + if (_imageScaling == CPScaleToFit) + { + _DOMImageElement.width = ROUND(width); + _DOMImageElement.height = ROUND(height); + } + else + { + var size = [_image size]; + + if (_imageScaling == CPScaleProportionally) + { + // The max size it can be is size.width x size.height, so only + // only proportion otherwise. + if (width >= size.width && height >= size.height) + { + width = size.width; + height = size.height; + } + else + { + var imageRatio = size.width / size.height, + viewRatio = width / height; + + if (viewRatio > imageRatio) + width = height * imageRatio; + else + height = width / imageRatio; + } + + _DOMImageElement.width = ROUND(width); + _DOMImageElement.height = ROUND(height); + } + else + { + width = size.width; + height = size.height; + } + + var x = (boundsWidth - width) / 2.0, + y = (boundsHeight - height) / 2.0; + + CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, x, y); + } + + _imageRect = _CGRectMake(x, y, width, height); + + if (_hasShadow) + [_shadowView setFrame:_CGRectMake(x - LEFT_SHADOW_INSET, y - TOP_SHADOW_INSET, width + insetWidth, height + insetHeight)]; +} + +@end + +var CPImageViewImageKey = @"CPImageViewImageKey", + CPImageViewImageScalingKey = @"CPImageViewImageScalingKey", + CPImageViewHasShadowKey = @"CPImageViewHasShadowKey"; + +@implementation CPImageView (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super initWithCoder:aCoder]; + + if (self) + { + _DOMImageElement = document.createElement("img"); + _DOMImageElement.style.position = "absolute"; + _DOMImageElement.style.left = "0px"; + _DOMImageElement.style.top = "0px"; + + _DOMElement.appendChild(_DOMImageElement); + _DOMImageElement.style.visibility = "hidden"; + + [self setImage:[aCoder decodeObjectForKey:CPImageViewImageKey]]; + + [self setImageScaling:[aCoder decodeIntForKey:CPImageViewImageScalingKey]]; + [self setHasShadow:[aCoder decodeBoolForKey:CPImageViewHasShadowKey]]; + + [self tile]; + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + // We do this in order to avoid encoding the _shadowView, which + // should just automatically be created programmatically as needed. + if (_shadowView) + { + var actualSubviews = _subviews; + + _subviews = [_subviews copy]; + [_subviews removeObjectIdenticalTo:_shadowView]; + } + + [super encodeWithCoder:aCoder]; + + if (_shadowView) + _subviews = actualSubviews; + + [aCoder encodeObject:_image forKey:CPImageViewImageKey]; + + [aCoder encodeInt:_imageScaling forKey:CPImageViewImageScalingKey]; + [aCoder encodeBool:_hasShadow forKey:CPImageViewHasShadowKey]; +} + +@end diff --git a/AppKit/CPKulerColorPicker.j b/AppKit/CPKulerColorPicker.j new file mode 100644 index 000000000..d1d6df938 --- /dev/null +++ b/AppKit/CPKulerColorPicker.j @@ -0,0 +1,367 @@ +/* + * CPApplication.j + * AppKit + * + * Created by Ross Boucher. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + +import "CPView.j" +import "CPButton.j" +import "CPImage.j" +import "CPImageView.j" +import "CPColorPicker.j" +import "CPColorPanel.j" +import "CPTabView.j" +import "CPTabViewItem.j" + + +@implementation CPKulerColorPicker : CPColorPicker +{ + CPView _contentView; + CPTabView _tabView; + + CPScrollView _searchView; + CPScrollView _popularView; + + CPView _searchView; + DOMElement _FIXME_searchField; + + CPURLConnection _searchConnection; + CPURLConnection _popularConnection +} + +- (id)initWithPickerMask:(int)mask colorPanel:(CPColorPanel)owningColorPanel +{ + return [super initWithPickerMask:mask colorPanel: owningColorPanel]; +} + +-(id)initView +{ + aFrame = CPRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight); + _contentView = [[CPView alloc] initWithFrame:aFrame]; + + _tabView = [[CPTabView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(aFrame), CGRectGetHeight(aFrame) - 20)]; + [_tabView setAutoresizingMask: CPViewWidthSizable | CPViewHeightSizable]; + [_tabView setDelegate: self]; + [_contentView addSubview: _tabView]; + + var label = [[CPButton alloc] initWithFrame:CPRectMake((CPColorPickerViewWidth-150)/2, CPColorPickerViewHeight-20, 150, 20)]; + [label setAutoresizingMask: CPViewMinXMargin | CPViewMaxXMargin | CPViewMinYMargin]; + [label setFont:[CPFont boldSystemFontOfSize:10.0]]; + [label setTextColor: [CPColor whiteColor]]; + [label setTitle: @"Powered by Adobe Kuler"]; + [label setTarget: self]; + [label setAction: @selector(openKulerLink:)]; + [label setBordered: NO]; + [_contentView addSubview: label]; + + var searchThemeView = [[_CPKulerThemeView alloc] initWithFrame: CPRectMake(0, 0, aFrame.size.width, 0)]; + [searchThemeView setDelegate: self]; + [searchThemeView setAutoresizingMask: CPViewWidthSizable]; + + _searchView = [[CPScrollView alloc] initWithFrame: CPRectMake(0, 0, aFrame.size.width, CPColorPickerViewHeight - 10)]; + [_searchView setDocumentView: searchThemeView]; + [_searchView setHasHorizontalScroller: NO]; + [_searchView setAutoresizingMask: (CPViewWidthSizable | CPViewHeightSizable)]; + [[_searchView verticalScroller] setControlSize:CPSmallControlSize]; + [_searchView setAutohidesScrollers:YES]; + + var auxiliarySearchView = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, CPColorPickerViewWidth, 26.0)]; + [auxiliarySearchView setAutoresizingMask: (CPViewMinYMargin | CPViewWidthSizable)]; + + _FIXME_searchField = document.createElement("input"); + + if(!window.addEventListener) + _FIXME_searchField.type = "text"; + else + _FIXME_searchField.type = "search"; + + _FIXME_searchField.style.position = "absolute"; + _FIXME_searchField.style.width = "96%"; + _FIXME_searchField.style.left = "2%"; + _FIXME_searchField.style.top = "2px"; + _FIXME_searchField.onkeypress = function(aDOMEvent) + { + aDOMEvent = aDOMEvent || window.event; + if (aDOMEvent.keyCode == 13) + { + [self search]; + + if(aDOMEvent.preventDefault) + aDOMEvent.preventDefault(); + else if(aDOMEvent.stopPropagation) + aDOMEvent.stopPropagation(); + + _FIXME_searchField.blur(); + } + }; + + auxiliarySearchView._DOMElement.appendChild(_FIXME_searchField); + + var popularThemeView = [[_CPKulerThemeView alloc] initWithFrame: CPRectMake(0, 0, aFrame.size.width, 0)]; + [popularThemeView setDelegate: self]; + [popularThemeView setAutoresizingMask: CPViewWidthSizable]; + + _popularView = [[CPScrollView alloc] initWithFrame: CPRectMake(0, 0, aFrame.size.width, CPColorPickerViewHeight)]; + [_popularView setDocumentView: popularThemeView]; + [_popularView setHasHorizontalScroller: NO]; + [_popularView setAutoresizingMask: (CPViewWidthSizable | CPViewHeightSizable)]; + [[_popularView verticalScroller] setControlSize:CPSmallControlSize]; + [_popularView setAutohidesScrollers:YES]; + + var mostPopularItem = [[CPTabViewItem alloc] initWithIdentifier:@"Popular"]; + var searchItem = [[CPTabViewItem alloc] initWithIdentifier:@"Search"]; + + [searchItem setLabel:@"Search"]; + [searchItem setView:_searchView]; + [searchItem setAuxiliaryView: auxiliarySearchView]; + + [mostPopularItem setLabel:@"Popular"]; + [mostPopularItem setView: _popularView]; + + [_tabView addTabViewItem: mostPopularItem]; + [_tabView addTabViewItem: searchItem]; + + [self popularThemes]; +} + +- (void)openKulerLink:(id)sender +{ + window.open("http://kuler.adobe.com"); +} + +- (CPView)provideNewView:(BOOL)initialRequest +{ + if (initialRequest) + [self initView]; + + return _contentView; +} + +- (int)currentMode +{ + return CPKulerColorPickerMode; +} + +- (BOOL)supportsMode:(int)mode +{ + return (mode == CPKulerColorPickerMode) ? YES : NO; +} + +-(void)search +{ + var query = escape(_FIXME_searchField.value); + + if(query.replace("%20", "") == "") + return; + + [_searchConnection cancel]; + + _searchConnection = nil; + _searchConnection = [CPURLConnection connectionWithRequest: + [CPURLRequest requestWithURL: BASE_URL + "kuler.php?mode=search&query="+query] + delegate: self]; +} + +-(void)popularThemes +{ + [_popularConnection cancel]; + _popularConnection = nil; + _popularConnection = [CPURLConnection connectionWithRequest: + [CPURLRequest requestWithURL: BASE_URL + "kuler.php?mode=popular"] delegate: self]; +} + +/* +-(void)topRatedThemes +{ + _connection = [CPURLConnection connectionWithRequest: + [CPURLRequest requestWithURL: BASE_URL + "kuler.php?mode=rating"] delegate:self]; +} +*/ + +- (void)connection:(CPURLConnection)aConnection didReceiveData:(CPString)data +{ + var data = CPJSObjectCreateWithJSON(data); + + if(!data) + var themes = []; + else + var themes = data.result; + + if(aConnection == _popularConnection) + [[_popularView documentView] setThemes: themes]; + + if(aConnection == _searchConnection) + [[_searchView documentView] setThemes: themes]; +} + +- (void)connection:(CPURLConnection)aConnection didFailWithError:(CPError)anError +{ + [self connectionDidFinishLoading:aConnection]; +} + +-(void)connectionDidFinishLoading:(CPURLConnection)aConnection +{ + +} + +-(void)chooseColor:(CPColor)aColor +{ + [[self colorPanel] setColor: aColor]; +} + +@end + +@implementation _CPKulerThemeView : CPView +{ + CPArray _themes; + id _delegate; + + CPColor _alternateBGColor; +} + +-(id)initWithFrame:(CPRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + _alternateBGColor = [CPColor colorWithCalibratedRed: 241.0/255.0 green: 245.0/255.0 blue: 250.0/255.0 alpha: 1.0]; + + return self; +} + +-(id)delegate +{ + return _delegate; +} + +-(void)setDelegate:(id)delegate +{ + _delegate = delegate; +} + +-(CPArray)themes +{ + return _themes; +} + +-(void)setThemes:(CPArray)themes +{ + _themes = themes; + [self updateDisplay]; +} + +-(void)updateDisplay +{ + var width = [self frame].size.width; + + var subviews = [self subviews]; + for(var i = [subviews count]-1; i >= 0; --i) + [subviews[i] removeFromSuperview]; + + for(var i=0, count = [_themes count]; i +import +import +import + +import "_CPImageAndTitleView.j" +import "CPApplication.j" +import "CPClipView.j" +import "CPMenuItem.j" +import "CPPanel.j" + +#include "Platform/Platform.h" + + +CPMenuDidAddItemNotification = @"CPMenuDidAddItemNotification"; +CPMenuDidChangeItemNotification = @"CPMenuDidChangeItemNotification"; +CPMenuDidRemoveItemNotification = @"CPMenuDidRemoveItemNotification"; + +CPMenuDidEndTrackingNotification = @"CPMenuDidEndTrackingNotification"; + +var MENUBAR_HEIGHT = 19.0; + +var _CPMenuBarVisible = NO, + _CPMenuBarTitle = @"", + _CPMenuBarIconImage = nil, + _CPMenuBarIconImageAlphaValue = 1.0, + _CPMenuBarSharedWindow = nil; + +@implementation CPMenu : CPObject +{ + CPString _title; + + CPMutableArray _items; + CPMenu _attachedMenu; + + BOOL _autoenablesItems; + BOOL _showsStateColumn; + + id _delegate; + + CPMenuItem _highlightedIndex; + _CPMenuWindow _menuWindow; +} + +// Managing the Menu Bar + ++ (BOOL)menuBarVisible +{ + return _CPMenuBarVisible; +} + ++ (void)setMenuBarVisible:(BOOL)menuBarShouldBeVisible +{ + if (_CPMenuBarVisible == menuBarShouldBeVisible) + return; + + _CPMenuBarVisible = menuBarShouldBeVisible; + + if (menuBarShouldBeVisible) + { + if (!_CPMenuBarSharedWindow) + _CPMenuBarSharedWindow = [[_CPMenuBarWindow alloc] init]; + + [_CPMenuBarSharedWindow setMenu:[CPApp mainMenu]]; + + [_CPMenuBarSharedWindow setTitle:_CPMenuBarTitle]; + [_CPMenuBarSharedWindow setIconImage:_CPMenuBarIconImage]; + [_CPMenuBarSharedWindow setIconImageAlphaValue:_CPMenuBarIconImageAlphaValue]; + + [_CPMenuBarSharedWindow orderFront:self]; + } + else + [_CPMenuBarWindow orderOut:self]; + +// FIXME: There must be a better way to do this. +#if PLATFORM(DOM) + [[CPDOMWindowBridge sharedDOMWindowBridge] _bridgeResizeEvent:nil]; +#endif +} + ++ (void)setMenuBarTitle:(CPString)aTitle +{ + _CPMenuBarTitle = aTitle; + [_CPMenuBarSharedWindow setTitle:_CPMenuBarTitle]; +} + ++ (CPString)menuBarTitle +{ + return _CPMenuBarTitle; +} + ++ (void)setMenuBarIconImage:(CPImage)anImage +{ + _CPMenuBarImage = anImage; + [_CPMenuBarSharedWindow setIconImage:anImage]; +} + ++ (CPImage)menuBarIconImage +{ + return _CPMenuBarImage; +} + ++ (void)_setMenuBarIconImageAlphaValue:(float)anAlphaValue +{ + _CPMenuBarIconImageAlphaValue = anAlphaValue; + [_CPMenuBarSharedWindow setIconImageAlphaValue:anAlphaValue]; +} + +- (float)menuBarHeight +{ + if (self == [CPApp mainMenu]) + return MENUBAR_HEIGHT; + + return 0.0; +} + +// Creating a CPMenu Object + +- (id)initWithTitle:(CPString)aTitle +{ + self = [super init]; + + if (self) + { + _title = aTitle; + _items = []; + + _autoenablesItems = YES; + _showsStateColumn = YES; + } + + return self; +} + +// Setting Up Menu Commands + +- (void)insertItem:(CPMenuItem)aMenuItem atIndex:(unsigned)anIndex +{ + var menu = [aMenuItem menu]; + + if (menu) + if (menu != self) + [CPException raise:CPInternalInconsistencyException reason:@"Attempted to insert item into menu that was already in another menu."]; + else + return; + + [aMenuItem setMenu:self]; + [_items insertObject:aMenuItem atIndex:anIndex]; + + [[CPNotificationCenter defaultCenter] + postNotificationName:CPMenuDidAddItemNotification + object:self + userInfo:[CPDictionary dictionaryWithObject:anIndex forKey:@"CPMenuItemIndex"]]; + +} + +- (CPMenuItem)insertItemWithTitle:(CPString)aTitle action:(SEL)anAction keyEquivalent:(CPString)aKeyEquivalent atIndex:(unsigned)anIndex +{ + var item = [[CPMenuItem alloc] initWithTitle:aTitle action:anAction keyEquivalent:aKeyEquivalent]; + + [self insertItem:item atIndex:anIndex]; + + return item; +} + +- (void)addItem:(CPMenuItem)aMenuItem +{ + [self insertItem:aMenuItem atIndex:[_items count]]; +} + +- (CPMenuItem)addItemWithTitle:(CPString)aTitle action:(SEL)anAction keyEquivalent:(CPString)aKeyEquivalent +{ + return [self insertItemWithTitle:aTitle action:anAction keyEquivalent:aKeyEquivalent atIndex:[_items count]]; +} + +- (void)removeItem:(CPMenuItem)aMenuItem +{ + [self removeItemAtIndex:[_items indexOfObjectIdenticalTo:aMenuItem]]; +} + +- (void)removeItemAtIndex:(unsigned)anIndex +{ + if (anIndex < 0 || anIndex >= _items.length) + return; + + [_items[anIndex] setMenu:nil]; + [_items removeObjectAtIndex:anIndex]; + + [[CPNotificationCenter defaultCenter] + postNotificationName:CPMenuDidAddItemNotification + object:self + userInfo:[CPDictionary dictionaryWithObject:anIndex forKey:@"CPMenuItemIndex"]]; +} + +- (void)itemChanged:(CPMenuItem)aMenuItem +{ + if ([aMenuItem menu] != self) + return; + + [[CPNotificationCenter defaultCenter] + postNotificationName:CPMenuDidChangeItemNotification + object:self + userInfo:[CPDictionary dictionaryWithObject:[_items indexOfObjectIdenticalTo:aMenuItem] forKey:@"CPMenuItemIndex"]]; +} + +// Finding Menu Items + +- (CPMenuItem)menuWithTag:(int)aTag +{ + var index = [self indexOfItemWithTag:aTag]; + + if (index == CPNotFound) + return nil; + + return _items[index]; +} + +- (CPMenuItem)menuWithTitle:(CPString)aTitle +{ + var index = [self indexOfItemWithTitle:aTitle]; + + if (index == CPNotFound) + return nil; + + return _items[index]; +} + +- (CPMenuItem)itemAtIndex:(int)anIndex +{ + return [_items objectAtIndex:anIndex]; +} + +- (unsigned)numberOfItems +{ + return [_items count]; +} + +- (CPArray)itemArray +{ + return _items; +} + +// Finding Indices of Menu Items + +- (int)indexOfItem:(CPMenuItem)aMenuItem +{ + if ([aMenuItem menu] != self) + return CPNotFound; + + return [_items indexOfObjectIdenticalTo:aMenuItem]; +} + +- (int)indexOfItemWithTitle:(CPString)aTitle +{ + var index = 0, + count = _items.length; + + for (; index < count; ++index) + if ([_items[index] title] === aTitle) + return index; + + return CPNotFound; +} + +- (int)indexOfItemWithTag:(int)aTag +{ + var index = 0, + count = _items.length; + + for (; index < count; ++index) + if ([_items[index] tag] == aTag) + return index; + + return CPNotFound; +} + +- (int)indexOfItemWithTarget:(id)aTarget andAction:(SEL)anAction +{ + var index = 0, + count = _items.length; + + for (; index < count; ++index) + { + var item = _items[index]; + + if ([item target] == aTarget && (!anAction || [item action] == anAction)) + return index; + } + + return CPNotFound; +} + +- (int)indexOfItemWithRepresentedObject:(id)anObject +{ + var index = 0, + count = _items.length; + + for (; index < count; ++index) + if ([[_items[index] representedObject] isEqual:anObject]) + return index; + + return CPNotFound; +} + +- (int)indexOfItemWithSubmenu:(CPMenu)aMenu +{ + var index = 0, + count = _items.length; + + for (; index < count; ++index) + if ([_items[index] submenu] == aMenu) + return index; + + return CPNotFound; +} + +// Managing Submenus + +- (void)setSubmenu:(CPMenu)aMenu forItem:(CPMenuItem)aMenuItem +{ + [aMenuItem setTarget:aMenuItem]; + [aMenuItem setAction:@selector(submenuAction:)]; + + [aMenuItem setSubmenu:aMenu]; +} + +- (void)submenuAction:(id)aSender +{ + +} + +- (CPMenu)attachedMenu +{ + return _attachedMenu; +} + +- (BOOL)isAttached +{ + return _isAttached; +} + +- (CGPoint)locationOfSubmenu:(CPMenu)aMenu +{ + // FIXME: IMPLEMENT. +} + +- (CPMenu)supermenu +{ + return _supermenu; +} + +- (void)setSupermenu:(CPMenu)aMenu +{ + _supermenu = aMenu; +} + +- (BOOL)isTornOff +{ + return !_supermenu /* || offscreen(?) */ || self == [CPApp mainMenu]; +} + +// Enabling and Disabling Menu Items + +- (void)setAutoenablesItems:(BOOL)aFlag +{ + _autoenablesItems = aFlag; +} + +- (BOOL)autoenablesItems +{ + return _autoenablesItems; +} + +- (void)update +{ + +} + +// Managing the Title + +- (void)setTitle:(CPString)aTitle +{ + _title = aTitle; +} + +- (CPString)title +{ + return _title; +} + +// + ++ (void)popUpContextMenu:(CPMenu)aMenu withEvent:(CPEvent)anEvent forView:(CPView)aView +{ + [self popUpContextMenu:aMenu withEvent:anEvent forView:aView withFont:nil]; +} + ++ (void)popUpContextMenu:(CPMenu)aMenu withEvent:(CPEvent)anEvent forView:(CPView)aView withFont:(CPFont)aFont +{ + [self _popUpContextMenu:aMenu withEvent:anEvent forView:aView withFont:aFont forMenuBar:NO]; +} + ++ (void)_popUpContextMenu:(CPMenu)aMenu withEvent:(CPEvent)anEvent forView:(CPView)aView withFont:(CPFont)aFont forMenuBar:(BOOL)isForMenuBar +{ + var delegate = [aMenu delegate]; + + if ([delegate respondsToSelector:@selector(menuWillOpen:)]) + [delegate menuWillOpen:aMenu]; + + if (!aFont) + aFont = [CPFont systemFontOfSize:12.0]; + + var theWindow = [aView window], + menuWindow = [_CPMenuWindow menuWindowWithMenu:aMenu font:aFont]; + + [menuWindow setDelegate:self]; + [menuWindow setBackgroundStyle:isForMenuBar ? _CPMenuWindowMenuBarBackgroundStyle : _CPMenuWindowPopUpBackgroundStyle]; + + [menuWindow setFrameOrigin:[[anEvent window] convertBaseToBridge:[anEvent locationInWindow]]]; + + [menuWindow orderFront:self]; + [menuWindow beginTrackingWithEvent:anEvent sessionDelegate:self didEndSelector:@selector(_menuWindowDidFinishTracking:highlightedItem:)]; +} + ++ (void)_menuWindowDidFinishTracking:(_CPMenuWindow)aMenuWindow highlightedItem:(CPMenuItem)aMenuItem +{ + [_CPMenuWindow poolMenuWindow:aMenuWindow]; + +// var index = [self indexOfItem:aMenuItem]; + +// if (index == CPNotFound) +// return; + + var target = nil, + action = [aMenuItem action]; + + if (!action) + { +// target = [self target]; +// action = [self action]; + } + + // FIXME: If [selectedItem target] == nil do we use our own target? + else + target = [aMenuItem target]; + + [CPApp sendAction:action to:target from:nil]; +} + +// Managing Display of State Column + +- (void)setShowsStateColumn:(BOOL)shouldShowStateColumn +{ + _showsStateColumn = shouldShowStateColumn; +} + +- (BOOL)showsStateColumn +{ + return _showsStateColumn; +} + +// Handling Highlighting + +- (BOOL)highlightedItem +{ + return _highlightedIndex >= 0 ? _items[_highlightedIndex] : nil; +} + +// Managing the Delegate + +- (void)setDelegate:(id)aDelegate +{ + _delegate = aDelegate; +} + +- (id)delegate +{ + return _delegate; +} + +// Handling Tracking + +- (void)cancelTracking +{ + [_menuWindow cancelTracking]; +} + +- (void)_setMenuWindow:(_CPMenuWindow)aMenuWindow +{ + _menuWindow = aMenuWindow; +} + +- (BOOL)performKeyEquivalent:(CPEvent)anEvent +{ + if (_autoenablesItems) + [self update]; + + var index = 0, + count = _items.length, + characters = [anEvent charactersIgnoringModifiers], + modifierFlags = [anEvent modifierFlags]; + + for(; index < count; ++index) + { + var item = _items[index], + modifierMask = [item keyEquivalentModifierMask]; + + if ((modifierFlags & (CPShiftKeyMask | CPAlternateKeyMask | CPCommandKeyMask | CPControlKeyMask)) == modifierMask && + [characters caseInsensitiveCompare:[item keyEquivalent]] == CPOrderedSame) + { + if ([item isEnabled]) + [self performActionForItemAtIndex:index]; + else + { + //beep? + } + + return YES; + } + + if ([[item submenu] performKeyEquivalent:anEvent]) + return YES; + } + + return NO; +} + +// Simulating Mouse Clicks + +- (void)performActionForItemAtIndex:(unsigned)anIndex +{ + var item = _items[anIndex]; + + [CPApp sendAction:[item action] to:[item target] from:item]; +} + +// + +- (BOOL)_itemIsHighlighted:(CPMenuItem)aMenuItem +{ + return _items[_highlightedIndex] == aMenuItem; +} + +- (void)_highlightItemAtIndex:(int)anIndex +{ + var previousHighlightedIndex = _highlightedIndex; + + _highlightedIndex = anIndex; + + if (previousHighlightedIndex != CPNotFound) + [[_items[previousHighlightedIndex] _menuItemView] highlight:NO]; + + if (_highlightedIndex != CPNotFound) + [[_items[_highlightedIndex] _menuItemView] highlight:YES]; +} + +@end + + +var CPMenuTitleKey = @"CPMenuTitleKey", + CPMenuItemsKey = @"CPMenuItemsKey"; + +@implementation CPMenu (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super init]; + + if (self) + { + _title = [aCoder decodeObjectForKey:CPMenuTitleKey]; + _items = [aCoder decodeObjectForKey:CPMenuItemsKey]; + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeObject:_title forKey:CPMenuTitleKey]; + [aCoder encodeObject:_items forKey:CPMenuItemsKey]; +} + +@end + +var _CPMenuWindowPool = [], + _CPMenuWindowPoolCapacity = 5, + + _CPMenuWindowBackgroundColors = [], + + _CPMenuWindowScrollingStateUp = -1, + _CPMenuWindowScrollingStateDown = 1, + _CPMenuWindowScrollingStateNone = 0; + +_CPMenuWindowMenuBarBackgroundStyle = 0; +_CPMenuWindowPopUpBackgroundStyle = 1; +_CPMenuWindowAttachedMenuBackgroundStyle = 2; + +var STICKY_TIME_INTERVAL = 500, + + TOP_MARGIN = 5.0, + LEFT_MARGIN = 1.0, + RIGHT_MARGIN = 1.0, + BOTTOM_MARGIN = 5.0, + + SCROLL_INDICATOR_HEIGHT = 16.0; + +@implementation _CPMenuWindow : CPWindow +{ + _CPMenuView _menuView; + CPClipView _menuClipView; + CPView _lastMouseOverMenuView; + + CPImageView _moreAboveView; + CPImageView _moreBelowView; + + id _sessionDelegate; + SEL _didEndSelector; + + CPTimeInterval _startTime; + int _scrollingState; + CGPoint _lastScreenLocation; + + BOOL _isShowingTopScrollIndicator; + BOOL _isShowingBottomScrollIndicator; + BOOL _trackingCanceled; + + CGRect _unconstrainedFrame; +} + ++ (id)menuWindowWithMenu:(CPMenu)aMenu font:(CPFont)aFont +{ + var menuWindow = nil; + + if (_CPMenuWindowPool.length) + menuWindow = _CPMenuWindowPool.pop(); + else + menuWindow = [[_CPMenuWindow alloc] init]; + + [menuWindow setFont:aFont]; + [menuWindow setMenu:aMenu]; + + return menuWindow; +} + ++ (void)poolMenuWindow:(_CPMenuWindow)aMenuWindow +{ + if (!aMenuWindow || _CPMenuWindowPool.length >= _CPMenuWindowPoolCapacity) + return; + + _CPMenuWindowPool.push(aMenuWindow); +} + ++ (void)initialize +{ + if (self != [_CPMenuWindow class]) + return; + + var bundle = [CPBundle bundleForClass:self]; + + _CPMenuWindowMoreAboveImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowMoreAbove.png"] size:CGSizeMake(38.0, 18.0)]; + _CPMenuWindowMoreBelowImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowMoreBelow.png"] size:CGSizeMake(38.0, 18.0)]; +} + +- (id)init +{ + self = [super initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessWindowMask]; + + if (self) + { + [self setLevel:CPTornOffMenuWindowLevel]; + [self setHasShadow:YES]; + [self setAcceptsMouseMovedEvents:YES]; + + _unconstrainedFrame = CGRectMakeZero(); + + var contentView = [self contentView]; + + _menuView = [[_CPMenuView alloc] initWithFrame:CGRectMakeZero()]; + + _menuClipView = [[CPClipView alloc] initWithFrame:CGRectMake(LEFT_MARGIN, TOP_MARGIN, 0.0, 0.0)]; + [_menuClipView setDocumentView:_menuView]; + + [contentView addSubview:_menuClipView]; + + _moreAboveView = [[CPImageView alloc] initWithFrame:CGRectMakeZero()]; + + [_moreAboveView setImage:_CPMenuWindowMoreAboveImage]; + [_moreAboveView setFrameSize:[_CPMenuWindowMoreAboveImage size]]; + + [contentView addSubview:_moreAboveView]; + + _moreBelowView = [[CPImageView alloc] initWithFrame:CGRectMakeZero()]; + + [_moreBelowView setImage:_CPMenuWindowMoreBelowImage]; + [_moreBelowView setFrameSize:[_CPMenuWindowMoreBelowImage size]]; + + [contentView addSubview:_moreBelowView]; + } + + return self; +} + +- (void)setFont:(CPFont)aFont +{ + [_menuView setFont:aFont]; +} + +- (void)setBackgroundStyle:(_CPMenuWindowBackgroundStyle)aBackgroundStyle +{ + var color = _CPMenuWindowBackgroundColors[aBackgroundStyle]; + + if (!color) + { + var bundle = [CPBundle bundleForClass:[self class]]; + + if (aBackgroundStyle == _CPMenuWindowPopUpBackgroundStyle) + color = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices: + [ + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowRounded0.png"] size:CGSizeMake(4.0, 4.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow1.png"] size:CGSizeMake(1.0, 4.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowRounded2.png"] size:CGSizeMake(4.0, 4.0)], + + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow3.png"] size:CGSizeMake(4.0, 1.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow4.png"] size:CGSizeMake(1.0, 1.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow5.png"] size:CGSizeMake(4.0, 1.0)], + + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowRounded6.png"] size:CGSizeMake(4.0, 4.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow7.png"] size:CGSizeMake(1.0, 4.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowRounded8.png"] size:CGSizeMake(4.0, 4.0)] + ]]]; + + else if (aBackgroundStyle == _CPMenuWindowMenuBarBackgroundStyle) + color = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices: + [ + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow3.png"] size:CGSizeMake(4.0, 0.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow4.png"] size:CGSizeMake(1.0, 0.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow5.png"] size:CGSizeMake(4.0, 0.0)], + + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow3.png"] size:CGSizeMake(4.0, 1.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow4.png"] size:CGSizeMake(1.0, 1.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow5.png"] size:CGSizeMake(4.0, 1.0)], + + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowRounded6.png"] size:CGSizeMake(4.0, 4.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindow7.png"] size:CGSizeMake(1.0, 4.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuWindow/_CPMenuWindowRounded8.png"] size:CGSizeMake(4.0, 4.0)] + ]]]; + + _CPMenuWindowBackgroundColors[aBackgroundStyle] = color; + } + + [self setBackgroundColor:color]; +} + +- (void)setMenu:(CPMenu)aMenu +{ + [aMenu _setMenuWindow:self]; + [_menuView setMenu:aMenu]; + + var menuViewSize = [_menuView frame].size; + + [self setFrameSize:CGSizeMake(LEFT_MARGIN + menuViewSize.width + RIGHT_MARGIN, TOP_MARGIN + menuViewSize.height + BOTTOM_MARGIN)]; + + [_menuView scrollPoint:CGPointMake(0.0, 0.0)]; + [_menuClipView setFrame:CGRectMake(LEFT_MARGIN, TOP_MARGIN, menuViewSize.width, menuViewSize.height)]; +} + +- (void)setMinWidth:(float)aWidth +{ + var size = [self frame].size; + + [self setFrameSize:CGSizeMake(MAX(size.width, aWidth), size.height)]; +} + +- (CGPoint)rectForItemAtIndex:(int)anIndex +{ + return [_menuView convertRect:[_menuView rectForItemAtIndex:anIndex] toView:nil]; +} + +- (void)orderFront:(id)aSender +{ + [self constrainToScreen]; + + [super orderFront:aSender]; +} + +- (void)constrainToScreen +{ + _unconstrainedFrame = CGRectMakeCopy([self frame]); + + var screenBounds = CGRectInset([[CPDOMWindowBridge sharedDOMWindowBridge] contentBounds], 5.0, 5.0), + constrainedFrame = CGRectIntersection(_unconstrainedFrame, screenBounds), + menuViewOrigin = [self convertBaseToBridge:CGPointMake(LEFT_MARGIN, TOP_MARGIN)]; + + constrainedFrame.origin.x = CGRectGetMinX(_unconstrainedFrame); + constrainedFrame.size.width = CGRectGetWidth(_unconstrainedFrame); + + if (CGRectGetWidth(constrainedFrame) > CGRectGetWidth(screenBounds)) + constrainedFrame.size.width = CGRectGetWidth(screenBounds); + + if (CGRectGetMaxX(constrainedFrame) > CGRectGetMaxX(screenBounds)) + constrainedFrame.origin.x -= CGRectGetMaxX(constrainedFrame) - CGRectGetMaxX(screenBounds); + + if (CGRectGetMinX(constrainedFrame) < CGRectGetMinX(screenBounds)) + constrainedFrame.origin.x = CGRectGetMinX(screenBounds); + + [super setFrame:constrainedFrame]; + + var topMargin = TOP_MARGIN, + bottomMargin = BOTTOM_MARGIN, + + contentView = [self contentView], + bounds = [contentView bounds]; + + var moreAbove = menuViewOrigin.y < CGRectGetMinY(constrainedFrame) + TOP_MARGIN, + moreBelow = menuViewOrigin.y + CGRectGetHeight([_menuView frame]) > CGRectGetMaxY(constrainedFrame) - BOTTOM_MARGIN; + + if (moreAbove) + { + topMargin += SCROLL_INDICATOR_HEIGHT; + + var frame = [_moreAboveView frame]; + + [_moreAboveView setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth(frame)) / 2.0, (TOP_MARGIN + SCROLL_INDICATOR_HEIGHT - CGRectGetHeight(frame)) / 2.0)]; + } + + [_moreAboveView setHidden:!moreAbove]; + + if (moreBelow) + { + bottomMargin += SCROLL_INDICATOR_HEIGHT; + + [_moreBelowView setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth([_moreBelowView frame])) / 2.0, CGRectGetHeight(bounds) - SCROLL_INDICATOR_HEIGHT - BOTTOM_MARGIN)]; + } + + [_moreBelowView setHidden:!moreBelow]; + + var clipFrame = CGRectMake(LEFT_MARGIN, topMargin, CGRectGetWidth(constrainedFrame) - LEFT_MARGIN - RIGHT_MARGIN, CGRectGetHeight(constrainedFrame) - topMargin - bottomMargin) + + [_menuClipView setFrame:clipFrame]; + [_menuView setFrameSize:CGSizeMake(CGRectGetWidth(clipFrame), CGRectGetHeight([_menuView frame]))]; + + [_menuView scrollPoint:CGPointMake(0.0, [self convertBaseToBridge:clipFrame.origin].y - menuViewOrigin.y)]; +} + +- (void)cancelTracking +{ + _trackingCanceled = YES; +} + +- (void)beginTrackingWithEvent:(CPEvent)anEvent sessionDelegate:(id)aSessionDelegate didEndSelector:(SEL)aDidEndSelector +{ + _startTime = [anEvent timestamp];//new Date(); + _scrollingState = _CPMenuWindowScrollingStateNone; + _trackingCanceled = NO; + + _sessionDelegate = aSessionDelegate; + _didEndSelector = aDidEndSelector; + + [self trackEvent:anEvent]; +} + +- (void)trackEvent:(CPEvent)anEvent +{ + var type = [anEvent type], + theWindow = [anEvent window], + screenLocation = theWindow ? [theWindow convertBaseToBridge:[anEvent locationInWindow]] : [anEvent locationInWindow]; + + if (type == CPPeriodic) + { + var constrainedBounds = CGRectInset([[CPDOMWindowBridge sharedDOMWindowBridge] contentBounds], 5.0, 5.0); + + if (_scrollingState == _CPMenuWindowScrollingStateUp) + { + if (CGRectGetMinY(_unconstrainedFrame) < CGRectGetMinY(constrainedBounds)) + _unconstrainedFrame.origin.y += 10; + } + else if (_scrollingState == _CPMenuWindowScrollingStateDown) + if (CGRectGetMaxY(_unconstrainedFrame) > CGRectGetHeight(constrainedBounds)) + _unconstrainedFrame.origin.y -= 10; + + [self setFrame:_unconstrainedFrame]; + [self constrainToScreen]; + + screenLocation = _lastScreenLocation; + } + + _lastScreenLocation = screenLocation; + + var menu = [_menuView menu], + menuLocation = [self convertBridgeToBase:screenLocation], + activeItemIndex = [_menuView itemIndexAtPoint:[_menuView convertPoint:menuLocation fromView:nil]], + mouseOverMenuView = [[menu itemAtIndex:activeItemIndex] view]; + + // If we're over a custom menu view... + if (mouseOverMenuView) + { + if (!_lastMouseOverMenuView) + [menu _highlightItemAtIndex:CPNotFound]; + + if (_lastMouseOverMenuView != mouseOverMenuView) + { + [mouseOverMenuView mouseExited:anEvent]; + // FIXME: Possibly multiple of these? + [_lastMouseOverMenuView mouseEntered:anEvent]; + + _lastMouseOverMenuView = mouseOverMenuView; + } + + [self sendEvent:[CPEvent mouseEventWithType:type location:menuLocation modifierFlags:[anEvent modifierFlags] + timestamp:[anEvent timestamp] windowNumber:[self windowNumber] context:nil + eventNumber:0 clickCount:[anEvent clickCount] pressure:[anEvent pressure]]]; + } + else + { + if (_lastMouseOverMenuView) + { + [_lastMouseOverMenuView mouseExited:anEvent]; + _lastMouseOverMenuView = nil; + } + + [menu _highlightItemAtIndex:[_menuView itemIndexAtPoint:[_menuView convertPoint:[self convertBridgeToBase:screenLocation] fromView:nil]]]; + + if (type == CPMouseMoved || type == CPLeftMouseDragged || type == CPLeftMouseDown) + { + var frame = [self frame], + oldScrollingState = _scrollingState; + + _scrollingState = _CPMenuWindowScrollingStateNone; + + // If we're at or above of the top scroll indicator... + if (screenLocation.y < CGRectGetMinY(frame) + TOP_MARGIN + SCROLL_INDICATOR_HEIGHT) + _scrollingState = _CPMenuWindowScrollingStateUp; + + // If we're at or below the bottom scroll indicator... + else if (screenLocation.y > CGRectGetMaxY(frame) - BOTTOM_MARGIN - SCROLL_INDICATOR_HEIGHT) + _scrollingState = _CPMenuWindowScrollingStateDown; + + if (_scrollingState != oldScrollingState) + + if (_scrollingState == _CPMenuWindowScrollingStateNone) + [CPEvent stopPeriodicEvents]; + + else if (oldScrollingState == _CPMenuWindowScrollingStateNone) + [CPEvent startPeriodicEventsAfterDelay:0.0 withPeriod:0.04]; + } + + else if (type == CPLeftMouseUp && ([anEvent timestamp] - _startTime > STICKY_TIME_INTERVAL)) + { + // Stop these if they're still goin'. + if (_scrollingState != _CPMenuWindowScrollingStateNone) + [CPEvent stopPeriodicEvents]; + + [self cancelTracking]; + } + } + + if (_trackingCanceled) + { + var highlightedItem = [[_menuView menu] highlightedItem]; + + [menu _highlightItemAtIndex:CPNotFound]; + + // Clear these now so its faster next time around. + [_menuView setMenu:nil]; + + [self orderOut:self]; + + if (_sessionDelegate && _didEndSelector) + objj_msgSend(_sessionDelegate, _didEndSelector, self, highlightedItem); + + [[CPNotificationCenter defaultCenter] + postNotificationName:CPMenuDidEndTrackingNotification + object:menu]; + + var delegate = [menu delegate]; + + if ([delegate respondsToSelector:@selector(menuDidClose:)]) + [delegate menuDidClose:menu]; + + return; + } + + [CPApp setTarget:self selector:@selector(trackEvent:) forNextEventMatchingMask:CPPeriodicMask | CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES]; +} + +@end + +@implementation _CPMenuView : CPView +{ + CPArray _menuItemViews; + + CPFont _font; +} + +/*- (id)initWithFrame:(CGRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + [self setAutoresizingMask:CPViewWidthSizable]; + + return self; +}*/ + +- (void)setFont:(CPFont)aFont +{ + _font = aFont; +} + +- (CGRect)rectForItemAtIndex:(int)anIndex +{ + return [_menuItemViews[anIndex == CPNotFound ? 0 : anIndex] frame]; +} + +- (int)itemIndexAtPoint:(CGPoint)aPoint +{ + var index = 0, + count = _menuItemViews.length; + + for (; index < count; ++index) + { + var view = _menuItemViews[index]; + + if ([view isHidden]) + continue; + + if (CGRectContainsPoint([view frame], aPoint)) + return index; + } + + return CPNotFound; +} + +- (void)setMenu:(CPMenu)aMenu +{ + [super setMenu:aMenu]; + + [_menuItemViews makeObjectsPerformSelector:@selector(removeFromSuperview)]; + + _menuItemViews = []; + + var menu = [self menu]; + + if (!menu) + return; + + var items = [menu itemArray], + index = 0, + count = [items count], + maxWidth = 0, + y = 0, + showsStateColumn = [menu showsStateColumn]; + + for (; index < count; ++index) + { + var item = items[index], + view = [item _menuItemView]; + + _menuItemViews.push(view); + + if ([item isHidden]) + continue; + + [view setFont:_font]; + [view setShowsStateColumn:showsStateColumn]; + [view synchronizeWithMenuItem]; + + [view setFrameOrigin:CGPointMake(0.0, y)]; + + [self addSubview:view]; + + var size = [view minSize], + width = size.width; + + if (maxWidth < width) + maxWidth = width; + + y += size.height; + } + + for (index = 0; index < count; ++index) + { + var view = _menuItemViews[index]; + + [view setFrameSize:CGSizeMake(maxWidth, CGRectGetHeight([view frame]))]; + } + + [self setAutoresizesSubviews:NO]; + [self setFrameSize:CGSizeMake(maxWidth, y)]; + [self setAutoresizesSubviews:YES]; +} + +@end + +var MENUBAR_HEIGHT = 29.0, + MENUBAR_MARGIN = 10.0, + MENUBAR_LEFT_MARGIN = 10.0, + MENUBAR_RIGHT_MARGIN = 10.0; + +var _CPMenuBarWindowBackgroundColor = nil, + _CPMenuBarWindowFont = nil; + +@implementation _CPMenuBarWindow : CPPanel +{ + CPMenu _menu; + CPView _highlightView; + + CPMenuItem _trackingMenuItem; + + CPImageView _iconImageView; + CPTextField _titleField; +} + ++ (void)initialize +{ + if (self != [_CPMenuBarWindow class]) + return; + + var bundle = [CPBundle bundleForClass:self]; + + _CPMenuBarWindowBackgroundColor = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPMenuBarWindow/_CPMenuBarWindowBackground.png"] size:CGSizeMake(1.0, 18.0)]]; + + _CPMenuBarWindowFont = [CPFont systemFontOfSize:11.0]; +} + +- (id)init +{ + var bridgeWidth = CGRectGetWidth([[CPDOMWindowBridge sharedDOMWindowBridge] contentBounds]); + + self = [super initWithContentRect:CGRectMake(0.0, 0.0, bridgeWidth, MENUBAR_HEIGHT) styleMask:CPBorderlessWindowMask]; + + if (self) + { + // FIXME: http://280north.lighthouseapp.com/projects/13294-cappuccino/tickets/39-dont-allow-windows-to-go-above-menubar + [self setLevel:-1];//CPTornOffMenuWindowLevel]; + [self setAutoresizingMask:CPWindowWidthSizable]; + + var contentView = [self contentView]; + + [contentView setBackgroundColor:_CPMenuBarWindowBackgroundColor]; + [contentView setAutoresizesSubviews:NO]; + + [self setBecomesKeyOnlyIfNeeded:YES]; + + // + _iconImageView = [[CPImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 16.0, 16.0)]; + + [contentView addSubview:_iconImageView]; + + _titleField = [[_CPImageAndTitleView alloc] initWithFrame:CGRectMakeZero()]; + + [_titleField setFont:[CPFont boldSystemFontOfSize:12.0]]; + + [_titleField setImagePosition:CPImageLeft]; + [_titleField setAlignment:CPCenterTextAlignment]; + + [contentView addSubview:_titleField]; + } + + return self; +} + +- (void)setTitle:(CPString)aTitle +{ +#if PLATFORM(DOM) + var bundleName = [[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPBundleName"]; + + if (![bundleName length]) + document.title = aTitle; + else if ([aTitle length]) + document.title = aTitle + @" - " + bundleName; + else + document.title = bundleName; +#endif + + [_titleField setTitle:aTitle]; + [_titleField sizeToFit]; + + [self tile]; +} + +- (void)setIconImage:(CPImage)anImage +{ + [_iconImageView setImage:anImage]; + [_iconImageView setHidden:anImage == nil]; + + [self tile]; +} + +- (void)setIconImageAlphaValue:(float)anAlphaValue +{ + [_iconImageView setAlphaValue:anAlphaValue]; +} + +- (void)setMenu:(CPMenu)aMenu +{ + if (_menu == aMenu) + return; + + var defaultCenter = [CPNotificationCenter defaultCenter]; + + if (_menu) + { + [defaultCenter + removeObserver:self + name:CPMenuDidAddItemNotification + object:_menu]; + + [defaultCenter + removeObserver:self + name:CPMenuDidChangeItemNotification + object:_menu]; + + [defaultCenter + removeObserver:self + name:CPMenuDidRemoveItemNotification + object:_menu]; + + var items = [_menu itemArray], + count = items.length; + + while (count--) + [[items[count] _menuItemView] removeFromSuperview]; + } + + _menu = aMenu; + + if (_menu) + { + [defaultCenter + addObserver:self + selector:@selector(menuDidAddItem:) + name:CPMenuDidAddItemNotification + object:_menu]; + + [defaultCenter + addObserver:self + selector:@selector(menuDidChangeItem:) + name:CPMenuDidChangeItemNotification + object:_menu]; + + [defaultCenter + addObserver:self + selector:@selector(menuDidRemoveItem:) + name:CPMenuDidRemoveItemNotification + object:_menu]; + } + + var contentView = [self contentView], + items = [_menu itemArray], + count = items.length; + + for (index = 0; index < count; ++index) + { + var item = items[index], + menuItemView = [item _menuItemView]; + + [menuItemView setShowsStateColumn:NO]; + [menuItemView setBelongsToMenuBar:YES]; + [menuItemView setFont:_CPMenuBarWindowFont]; + [menuItemView setHidden:[item isHidden]]; + + [menuItemView synchronizeWithMenuItem]; + + [contentView addSubview:menuItemView]; + } + + [self tile]; +} + +- (void)menuDidChangeItem:(CPNotification)aNotification +{ + var menuItem = [_menu itemAtIndex:[[aNotification userInfo] objectForKey:@"CPMenuItemIndex"]], + menuItemView = [menuItem _menuItemView]; + + [menuItemView setHidden:[menuItem isHidden]]; + [menuItemView synchronizeWithMenuItem]; + + [self tile]; +} + +- (CGRect)frameForMenuItem:(CPMenuItem)aMenuItem +{ + var frame = [[aMenuItem _menuItemView] frame]; + + frame.origin.x -= 5.0; + frame.origin.y = 0; + frame.size.width += 10.0; + frame.size.height = MENUBAR_HEIGHT; + + return frame; +} + +- (CPView)menuItemAtPoint:(CGPoint)aPoint +{ + var items = [_menu itemArray], + count = items.length; + + while (count--) + { + var item = items[count]; + + if ([item isHidden] || [item isSeparatorItem]) + continue; + + if (CGRectContainsPoint([self frameForMenuItem:item], aPoint)) + return item; + } + + return nil; +} + +- (void)mouseDown:(CPEvent)anEvent +{ + _trackingMenuItem = [self menuItemAtPoint:[anEvent locationInWindow]]; + + if (![_trackingMenuItem isEnabled]) + return; + + if ([[_trackingMenuItem _menuItemView] eventOnSubmenu:anEvent]) + return [self showMenu:anEvent]; + + if ([_trackingMenuItem isEnabled]) + [self trackEvent:anEvent]; +} + +- (void)trackEvent:(CPEvent)anEvent +{ + var type = [anEvent type]; + + if (type == CPPeriodic) + return [self showMenu:anEvent]; + + var frame = [self frameForMenuItem:_trackingMenuItem], + menuItemView = [_trackingMenuItem _menuItemView], + onMenuItemView = CGRectContainsPoint(frame, [anEvent locationInWindow]); + + if (type == CPLeftMouseDown) + { + if ([_trackingMenuItem submenu] != nil) + { + // If the item has a submenu, but not direct action, a.k.a. a "pure" menu, simply show the menu. + if (![_trackingMenuItem action]) + return [self showMenu:anEvent]; + + // If this is a hybrid button/menu, show it in a bit... + [CPEvent startPeriodicEventsAfterDelay:0.0 withPeriod:0.5]; + } + + [menuItemView highlight:onMenuItemView]; + } + + else if (type == CPLeftMouseDragged) + { + if (!onMenuItemView && [_trackingMenuItem submenu]) + return [self showMenu:anEvent]; + + [menuItemView highlight:onMenuItemView]; + } + + else /*if (type == CPLeftMouseUp)*/ + { + [CPEvent stopPeriodicEvents]; + + [menuItemView highlight:NO]; + + if (onMenuItemView) + [CPApp sendAction:[_trackingMenuItem action] to:[_trackingMenuItem target] from:nil]; + + return; + } + + [CPApp setTarget:self selector:@selector(trackEvent:) forNextEventMatchingMask:CPPeriodicMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES]; +} + +- (void)showMenu:(CPEvent)anEvent +{ + [CPEvent stopPeriodicEvents]; + + var frame = [self frameForMenuItem:_trackingMenuItem], + menuItemView = [_trackingMenuItem _menuItemView]; + + if (!_highlightView) + { + _highlightView = [[CPView alloc] initWithFrame:frame]; + + [_highlightView setBackgroundColor:[CPColor colorWithCalibratedRed:81.0 / 255.0 green:83.0 / 255.0 blue:109.0 / 255.0 alpha:1.0]]; + } + else + [_highlightView setFrame:frame]; + + [[self contentView] addSubview:_highlightView positioned:CPWindowBelow relativeTo:menuItemView]; + + [menuItemView activate:YES]; + + var submenu = [_trackingMenuItem submenu]; + + [[CPNotificationCenter defaultCenter] + addObserver:self + selector:@selector(menuDidEndTracking:) + name:CPMenuDidEndTrackingNotification + object:submenu]; + + [CPMenu _popUpContextMenu:submenu + withEvent:[CPEvent mouseEventWithType:CPLeftMouseDown location:CGPointMake(CGRectGetMinX(frame), CGRectGetMaxY(frame)) + modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:[self windowNumber] + context:nil eventNumber:0 clickCount:[anEvent clickCount] pressure:[anEvent pressure]] + forView:[self contentView] + withFont:nil + forMenuBar:YES]; +} + +- (void)menuDidEndTracking:(CPNotification)aNotification +{ + [_highlightView removeFromSuperview]; + + [[_trackingMenuItem _menuItemView] activate:NO]; + + [[CPNotificationCenter defaultCenter] + removeObserver:self + name:CPMenuDidEndTrackingNotification + object:[aNotification object]]; +} + +- (void)tile +{ + var items = [_menu itemArray], + index = 0, + count = items.length, + + x = MENUBAR_LEFT_MARGIN, + y = 0.0, + isLeftAligned = YES; + + for (; index < count; ++index) + { + var item = items[index]; + + if ([item isSeparatorItem]) + { + x = CGRectGetWidth([self frame]) - MENUBAR_RIGHT_MARGIN; + isLeftAligned = NO; + + continue; + } + + if ([item isHidden]) + continue; + + var menuItemView = [item _menuItemView], + frame = [menuItemView frame]; + + if (isLeftAligned) + { + [menuItemView setFrameOrigin:CGPointMake(x, (MENUBAR_HEIGHT - 1.0 - CGRectGetHeight(frame)) / 2.0)]; + + x += CGRectGetWidth([menuItemView frame]) + MENUBAR_MARGIN; + } + else + { + [menuItemView setFrameOrigin:CGPointMake(x - CGRectGetWidth(frame), (MENUBAR_HEIGHT - 1.0 - CGRectGetHeight(frame)) / 2.0)]; + + x = CGRectGetMinX([menuItemView frame]) - MENUBAR_MARGIN; + } + } + + var bounds = [[self contentView] bounds], + titleFrame = [_titleField frame]; + + if ([_iconImageView isHidden]) + [_titleField setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth(titleFrame)) / 2.0, (CGRectGetHeight(bounds) - CGRectGetHeight(titleFrame)) / 2.0)]; + else + { + var iconFrame = [_iconImageView frame], + iconWidth = CGRectGetWidth(iconFrame), + totalWidth = iconWidth + CGRectGetWidth(titleFrame); + + [_iconImageView setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - totalWidth) / 2.0, (CGRectGetHeight(bounds) - CGRectGetHeight(iconFrame)) / 2.0)]; + [_titleField setFrameOrigin:CGPointMake((CGRectGetWidth(bounds) - totalWidth) / 2.0 + iconWidth, (CGRectGetHeight(bounds) - CGRectGetHeight(titleFrame)) / 2.0)]; + } +} + +- (void)setFrameSize:(CGSize)aSize +{ + [super setFrameSize:aSize]; + + [self tile]; +} + +@end diff --git a/AppKit/CPMenuItem.j b/AppKit/CPMenuItem.j new file mode 100644 index 000000000..68050294e --- /dev/null +++ b/AppKit/CPMenuItem.j @@ -0,0 +1,897 @@ +/* + * CPMenuItem.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import +import + +import +import +import + + +@implementation CPMenuItem : CPObject +{ + CPString _title; + //CPAttributedString _attributedTitle; + + CPFont _font; + + id _target; + SEL _action; + + BOOL _isEnabled; + BOOL _isHidden; + + int _tag; + int _state; + + CPImage _image; + CPImage _alternateImage; + CPImage _onStateImage; + CPImage _offStateImage; + CPImage _mixedStateImage; + + CPMenu _submenu; + CPMenu _menu; + + CPString _keyEquivalent; + unsigned _keyEquivalentModifierMask; + + int _mnemonicLocation; + + BOOL _isAlternate; + int _indentationLevel; + + CPString _toolTip; + id _representedObject; + CPView _view; + + _CPMenuItemView _menuItemView; +} + +- (id)initWithTitle:(CPString)aTitle action:(SEL)anAction keyEquivalent:(CPString)aKeyEquivalent +{ + self = [super init]; + + if (self) + { + _title = aTitle; + _action = anAction; + + _isEnabled = YES; + + _state = CPOffState; + + _keyEquivalent = aKeyEquivalent; + _keyEquivalentModifierMask = CPPlatformActionKeyMask; + + _mnemonicLocation = CPNotFound; + } + + return self; +} + +// Enabling a Menu Item + +- (void)setEnabled:(BOOL)isEnabled +{ + if ([_menu autoenablesItems]) + return; + + _isEnabled = isEnabled; + + [_menuItemView setDirty]; + + [_menu itemChanged:self]; +} + +- (BOOL)isEnabled +{ + return _isEnabled; +} + +// Managing Hidden Status + +- (void)setHidden:(BOOL)isHidden +{ + _isHidden = isHidden; +} + +- (BOOL)isHidden +{ + return _isHidden; +} + +- (BOOL)isHiddenOrHasHiddenAncestor +{ + if (_isHidden) + return YES; + + if ([[[_menu supermenu] indexOfItemWithSubmenu:_menu] isHiddenOrHasHiddenAncestor]) + return YES; + + return NO; +} + +// Managing Target and Action + +- (void)setTarget:(id)aTarget +{ + _target = aTarget; +} + +- (id)target +{ + return _target; +} + +- (void)setAction:(SEL)anAction +{ + _action = anAction; +} + +- (SEL)action +{ + return _action; +} + +// Managing the Title + +- (void)setTitle:(CPString)aTitle +{ + _mnemonicLocation = CPNotFound; + + if (_title == aTitle) + return; + + _title = aTitle; + + [_menuItemView setDirty]; + + [_menu itemChanged:self]; +} + +- (CPString)title +{ + return _title; +} + +- (void)setFont:(CPFont)aFont +{ + if (_font == aFont) + return; + + _font = aFont; + + [_menu itemChanged:self]; + + [_menuItemView setDirty]; +} + +- (CPFont)font +{ + return _font; +} + +/* +- (void)setAttributedTitle:(CPAttributedString)aTitle +{ +} + +- (CPAttributedString)attributedTitle +{ +} +*/ + +// Managing the Tag + +- (void)setTag:(int)aTag +{ + _tag = aTag; +} + +- (int)tag +{ + return _tag; +} + +- (void)setState:(int)aState +{ + if (_state == aState) + return; + + _state = aState; + + [_menu itemChanged:self]; + + [_menuItemView setDirty]; +} + +- (int)state +{ + return _state; +} + +// Managing the Image + +- (void)setImage:(CPImage)anImage +{ + if (_image == anImage) + return; + + _image = anImage; + + [_menuItemView setDirty]; + + [_menu itemChanged:self]; +} + +- (CPImage)image +{ + return _image; +} + +- (void)setAlternateImage:(CPImage)anImage +{ + _alternateImage = anImage; +} + +- (CPImage)alternateImage +{ + return _alternateImage; +} + +- (void)setOnStateImage:(CPImage)anImage +{ + if (_onStateImage == anImage) + return; + + _onStateImage = anImage; + [_menu itemChanged:self]; +} + +- (CPImage)onStateImage +{ + return _onStateImage; +} + +- (void)setOffStateImage:(CPImage)anImage +{ + if (_offStateImage == anImage) + return; + + _offStateImage = anImage; + [_menu itemChanged:self]; +} + +- (CPImage)offStateImage +{ + return _offStateImage; +} + +- (void)setMixedStateImage:(CPImage)anImage +{ + if (_mixedStateImage == anImage) + return; + + _mixedStateImage = anImage; + [_menu itemChanged:self]; +} + +- (CPImage)mixedStateImage +{ + return _mixedStateImage; +} + +// Managing Subemenus + +- (void)setSubmenu:(CPMenu)aMenu +{ + var supermenu = [_submenu supermenu]; + + if (supermenu == self) + return; + + if (supermenu) + return alert("bad"); + + [_submenu setSupermenu:_menu]; + + _submenu = aMenu; + + [_menuItemView setDirty]; + + [_menu itemChanged:self]; +} + +- (CPMenu)submenu +{ + return _submenu; +} + +- (BOOL)hasSubmenu +{ + return _submenu ? YES : NO; +} + +// Getting a Separator Item + ++ (CPMenuItem)separatorItem +{ + return [[_CPMenuItemSeparator alloc] init]; +} + +- (BOOL)isSeparatorItem +{ + return NO; +} + +// Managing the Owning Menu + +- (void)setMenu:(CPMenu)aMenu +{ + _menu = aMenu; +} + +- (CPMenu)menu +{ + return _menu; +} + +// + +- (void)setKeyEquivalent:(CPString)aString +{ + _keyEquivalent = aString; +} + +- (CPString)keyEquivalent +{ + return _keyEquivalent; +} + +- (void)setKeyEquivalentModifierMask:(unsigned)aMask +{ + _keyEquivalentModifierMask = aMask; +} + +- (unsigned)keyEquivalentModifierMask +{ + return _keyEquivalentModifierMask; +} + +// Managing Mnemonics + +- (void)setMnemonicLocation:(unsigned)aLocation +{ + _mnemonicLocation = aLocation; +} + +- (unsigned)mnemonicLocation +{ + return _mnemonicLocation; +} + +- (void)setTitleWithMnemonicLocation:(CPString)aTitle +{ + var location = [aTitle rangeOfString:@"&"].location; + + if (location == CPNotFound) + [self setTitle:aTitle]; + else + { + [self setTitle:[aTitle substringToIndex:location] + [aTitle substringFromIndex:location + 1]]; + [self setMnemonicLocation:location]; + } +} + +- (CPString)mnemonic +{ + return _mnemonicLocation == CPNotFound ? @"" : [_title characterAtIndex:_mnemonicLocation]; +} + +// Managing Alternates + +- (void)setAlternate:(BOOL)isAlternate +{ + _isAlternate = isAlternate; +} + +- (BOOL)isAlternate +{ + return _isAlternate; +} + +// Managing Indentation Levels + +- (void)setIndentationLevel:(unsigned)aLevel +{ + if (aLevel < 0) + alert("bad"); + + _indentationLevel = MIN(15, aLevel); +} + +- (unsigned)indentationLevel +{ + return _indentationLevel; +} + +// Managing Tool Tips +- (void)setToolTip:(CPString)aToolTip +{ + _toolTip = aToolTip; +} + +- (CPString)toolTip +{ + return _toolTip; +} + +// Representing an Object + +- (void)setRepresentedObject:(id)anObject +{ + _representedObject = anObject; +} + +- (id)representedObject +{ + return _representedObject; +} + +// Managing the View + +- (void)setView:(CPView)aView +{ + if (_view == aView) + return; + + _view = aView; + + [_menuItemView setDirty]; + + [_menu itemChanged:self]; +} + +- (CPView)view +{ + return _view; +} + +// Getting Highlighted Status + +- (BOOL)isHighlighted +{ + return [[self menu] highlightedItem] == self; +} + +// + +- (id)_menuItemView +{ + if (!_menuItemView) + _menuItemView = [[_CPMenuItemView alloc] initWithFrame:CGRectMakeZero() forMenuItem:self]; + + return _menuItemView; +} + +@end + +@implementation _CPMenuItemSeparator : CPMenuItem +{ +} + +- (id)init +{ + return [super initWithTitle:@"" action:nil keyEquivalent:@""]; +} + +- (BOOL)isSeparatorItem +{ + return YES; +} + +@end + +var CPMenuItemTitleKey = @"CPMenuItemTitleKey", + CPMenuItemTargetKey = @"CPMenuItemTargetKey", + CPMenuItemActionKey = @"CPMenuItemActionKey", + + CPMenuItemIsEnabledKey = @"CPMenuItemIsEnabledKey", + CPMenuItemIsHiddenKey = @"CPMenuItemIsHiddenKey", + + CPMenuItemImageKey = @"CPMenuItemImageKey", + CPMenuItemAlternateImageKey = @"CPMenuItemAlternateImageKey", + + CPMenuItemSubmenuKey = @"CPMenuItemSubmenuKey", + CPMenuItemMenuKey = @"CPMenuItemMenuKey", + + CPMenuItemRepresentedObjectKey = @"CPMenuItemRepresentedObjectKey"; + +@implementation CPMenuItem (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super init]; + + if (self) + { + _title = [aCoder decodeObjectForKey:CPMenuItemTitleKey]; + +// _font; + + _target = [aCoder decodeObjectForKey:CPMenuItemTargetKey]; + _action = [aCoder decodeObjectForKey:CPMenuItemActionKey]; + + _isEnabled = [aCoder decodeObjectForKey:CPMenuItemIsEnabledKey]; + _isHidden = [aCoder decodeObjectForKey:CPMenuItemIsHiddenKey]; + +// int _tag; +// int _state; + + _image = [aCoder decodeObjectForKey:CPMenuItemImageKey]; + _alternateImage = [aCoder decodeObjectForKey:CPMenuItemAlternateImageKey]; +// CPImage _onStateImage; +// CPImage _offStateImage; +// CPImage _mixedStateImage; + + _submenu = [aCoder decodeObjectForKey:CPMenuItemSubmenuKey]; + _menu = [aCoder decodeObjectForKey:CPMenuItemMenuKey]; + +// CPString _keyEquivalent; +// unsigned _keyEquivalentModifierMask; + +// int _mnemonicLocation; + +// BOOL _isAlternate; +// int _indentationLevel; + +// CPString _toolTip; + + _representedObject = [aCoder decodeObjectForKey:CPMenuItemRepresentedObjectKey]; +// id _representedObject; +// CPView _view; + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeObject:_title forKey:CPMenuItemTitleKey]; + + [aCoder encodeObject:_target forKey:CPMenuItemTargetKey]; + [aCoder encodeObject:_action forKey:CPMenuItemActionKey]; + + [aCoder encodeObject:_isEnabled forKey:CPMenuItemIsEnabledKey]; + [aCoder encodeObject:_isHidden forKey:CPMenuItemIsHiddenKey]; + + [aCoder encodeObject:_image forKey:CPMenuItemImageKey]; + [aCoder encodeObject:_alternateImage forKey:CPMenuItemAlternateImageKey]; + + [aCoder encodeObject:_submenu forKey:CPMenuItemSubmenuKey]; + [aCoder encodeObject:_menu forKey:CPMenuItemMenuKey]; + + [aCoder encodeObject:_representedObject forKey:CPMenuItemRepresentedObjectKey]; +} + +@end + +var LEFT_MARGIN = 3.0, + RIGHT_MARGIN = 16.0, + STATE_COLUMN_WIDTH = 14.0, + INDENTATION_WIDTH = 17.0; + +var _CPMenuItemSelectionColor = nil, + + _CPMenuItemDefaultStateImages = [], + _CPMenuItemDefaultStateHighlightedImages = [], + + _CPMenuItemViewMenuBarArrowImage = nil, + _CPMenuItemViewMenuBarArrowActivatedImage = nil; + +@implementation _CPMenuItemView : CPView +{ + CPMenuItem _menuItem; + + CPFont _font; + + CGSize _minSize; + BOOL _isDirty; + BOOL _showsStateColumn; + BOOL _belongsToMenuBar; + + CPImageView _stateView; + _CPImageAndTitleView _imageAndTitleView; + CPImageView _submenuImageView; +} + ++ (void)initialize +{ + if (self != [_CPMenuItemView class]) + return; + + _CPMenuItemSelectionColor = [CPColor colorWithCalibratedRed:81.0 / 255.0 green:83.0 / 255.0 blue:109.0 / 255.0 alpha:1.0]; + + var bundle = [CPBundle bundleForClass:self]; + + _CPMenuItemDefaultStateImages[CPOffState] = nil; + _CPMenuItemDefaultStateHighlightedImages[CPOffState] = nil; + + _CPMenuItemDefaultStateImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnState.png"] size:CGSizeMake(14.0, 14.0)]; + _CPMenuItemDefaultStateHighlightedImages[CPOnState] = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPMenuItem/CPMenuItemOnStateHighlighted.png"] size:CGSizeMake(14.0, 14.0)]; + + _CPMenuItemDefaultStateImages[CPMixedState] = nil; + _CPMenuItemDefaultStateHighlightedImages[CPMixedState] = nil; +} + ++ (float)leftMargin +{ + return LEFT_MARGIN + STATE_COLUMN_WIDTH; +} + +- (id)initWithFrame:(CGRect)aFrame forMenuItem:(CPMenuItem)aMenuItem +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _menuItem = aMenuItem; + _showsStateColumn = YES; + _isDirty = YES; + + [self setAutoresizingMask:CPViewWidthSizable]; + + [self synchronizeWithMenuItem]; + } + + return self; +} + +- (CGSize)minSize +{ + return _minSize; +} + +- (void)setDirty +{ + _isDirty = YES; +} + +- (void)synchronizeWithMenuItem +{ + if (!_isDirty) + return; + + _isDirty = NO; + + var view = [_menuItem view]; + + if (view) + { + [_imageAndTitleView removeFromSuperview]; + _imageAndTitleView = nil; + + [_stateView removeFromSuperview]; + _stateView = nil; + + [_submenuImageView removeFromSuperview]; + _submenuImageView = nil; + + _minSize = [view frame].size; + + [self setFrameSize:_minSize]; + + [self addSubview:view]; + + return; + } + + // State Column + var x = _belongsToMenuBar ? 0.0 : (LEFT_MARGIN + [_menuItem indentationLevel] * INDENTATION_WIDTH); + + if (_showsStateColumn) + { + if (!_stateView) + { + _stateView = [[CPImageView alloc] initWithFrame:CGRectMake(x, (CGRectGetHeight([self frame]) - STATE_COLUMN_WIDTH) / 2.0, STATE_COLUMN_WIDTH, STATE_COLUMN_WIDTH)]; + + [_stateView setAutoresizingMask:CPViewMinYMargin | CPViewMaxYMargin]; + + [self addSubview:_stateView]; + } + + var state = [_menuItem state]; + + switch (state) + { + case CPOffState: + case CPOnState: + case CPMixedState: [_stateView setImage:_CPMenuItemDefaultStateImages[state]]; + break; + + default: [_stateView setImage:nil]; + } + + x += STATE_COLUMN_WIDTH; + } + else + { + [_stateView removeFromSuperview]; + + _stateView = nil; + } + + // Image and Title + + if (!_imageAndTitleView) + { + _imageAndTitleView = [[_CPImageAndTitleView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 0.0)]; + + [_imageAndTitleView setImagePosition:CPImageLeft]; + + [self addSubview:_imageAndTitleView]; + } + + var font = [_menuItem font]; + + if (!font) + font = _font; + + [_imageAndTitleView setFont:font]; + [_imageAndTitleView setImage:[_menuItem image]]; + [_imageAndTitleView setTitle:[_menuItem title]]; + [_imageAndTitleView setTextColor:[_menuItem isEnabled] ? [CPColor blackColor] : [CPColor darkGrayColor]]; + [_imageAndTitleView setFrameOrigin:CGPointMake(x, 0.0)]; + + [_imageAndTitleView sizeToFit]; + + var frame = [_imageAndTitleView frame]; + + x += CGRectGetWidth(frame); + + // Submenu Arrow + if ([_menuItem hasSubmenu]) + { + if (!_submenuImageView) + { + _submenuImageView = [[CPImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 10.0, 10.0)]; + + [self addSubview:_submenuImageView]; + } + + if (_belongsToMenuBar && !_CPMenuItemViewMenuBarArrowImage) + _CPMenuItemViewMenuBarArrowImage = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[_CPMenuItemView class]] pathForResource:@"_CPMenuItemView/_CPMenuItemViewMenuBarArrow.png"] size:CGSizeMake(10.0, 10.0)]; + + [_submenuImageView setHidden:NO]; + [_submenuImageView setImage:_belongsToMenuBar ? _CPMenuItemViewMenuBarArrowImage : nil]; + [_submenuImageView setFrameOrigin:CGPointMake(x, (CGRectGetHeight(frame) - 10.0) / 2.0)]; + + x += 10.0; + } + else + [_submenuImageView setHidden:YES]; + + _minSize = CGSizeMake(x + (_belongsToMenuBar ? 0.0 : RIGHT_MARGIN), CGRectGetHeight(frame)); + + [self setFrameSize:_minSize]; +} + +- (float)calculatedLeftMargin +{ + if (_belongsToMenuBar) + return 0.0; + + return LEFT_MARGIN + ([[_menuItem menu] showsStateColumn] ? STATE_COLUMN_WIDTH : 0.0) + [_menuItem indentationLevel] * INDENTATION_WIDTH; +} + +- (void)setShowsStateColumn:(BOOL)shouldShowStateColumn +{ + _showsStateColumn = shouldShowStateColumn; +} + +- (void)setBelongsToMenuBar:(BOOL)shouldBelongToMenuBar +{ + _belongsToMenuBar = shouldBelongToMenuBar; +} + +- (void)highlight:(BOOL)shouldHighlight +{ + // ASSERT(![_menuItem view]); + + if (_belongsToMenuBar) + [_imageAndTitleView setImage:shouldHighlight ? [_menuItem alternateImage] : [_menuItem image]]; + + else + { + [_imageAndTitleView setTextColor:shouldHighlight ? [CPColor whiteColor] : [CPColor blackColor]]; + + if (shouldHighlight) + [self setBackgroundColor:_CPMenuItemSelectionColor]; + else + [self setBackgroundColor:nil]; + + var state = [_menuItem state]; + + switch (state) + { + case CPOffState: + case CPOnState: + case CPMixedState: [_stateView setImage:shouldHighlight ? _CPMenuItemDefaultStateHighlightedImages[state] : _CPMenuItemDefaultStateImages[state]]; + break; + + default: [_stateView setImage:nil]; + } + } +} + +- (void)activate:(BOOL)shouldActivate +{ + [_imageAndTitleView setImage:[_menuItem image]]; + + if (shouldActivate) + { + if (!_CPMenuItemViewMenuBarArrowActivatedImage) + _CPMenuItemViewMenuBarArrowActivatedImage = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[_CPMenuItemView class]] pathForResource:@"_CPMenuItemView/_CPMenuItemViewMenuBarArrowActivated.png"] size:CGSizeMake(10.0, 10.0)]; + + [_imageAndTitleView setTextColor:[CPColor whiteColor]]; + [_submenuImageView setImage:_CPMenuItemViewMenuBarArrowActivatedImage]; + } + else + { + [_imageAndTitleView setTextColor:[CPColor blackColor]]; + [_submenuImageView setImage:_CPMenuItemViewMenuBarArrowImage]; + } +} + +- (BOOL)eventOnSubmenu:(CPEvent)anEvent +{ + if (![_menuItem hasSubmenu]) + return NO; + + return CGRectContainsPoint([_submenuImageView frame], [self convertPoint:[anEvent locationInWindow] fromView:nil]); +} + +- (BOOL)isHidden +{ + return [_menuItem isHidden]; +} + +- (CPMenuItem)menuItem +{ + return _menuItem; +} + +- (void)setFont:(CPFont)aFont +{ + if (_font == aFont) + return; + + _font = aFont; + + [self setDirty]; +} + +@end + diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j new file mode 100644 index 000000000..a19b008a8 --- /dev/null +++ b/AppKit/CPOutlineView.j @@ -0,0 +1,79 @@ +/* + * CPOutlineView.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPTableView.j" + + +@implementation CPOutlineView : CPTableView +{ + id _outlineDataSource; + CPArray _itemsByRow; +} + +- (id)initWithFrame:(CGRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + [super setDataSource:self]; + _itemsByRow = [[CPArray alloc] init]; + } + + return self; +} + +- (void)setDataSource:(id)aDataSource +{ + _outlineDataSource = aDataSource; + + [self reloadData]; +} + +- (void)reloadData +{ + _numberOfVisibleItems = [_outlineDataSource outlineView:self numberOfChildrenOfItem:nil]; + _numberOfRows = _numberOfVisibleItems; + + var i = 0; + + for (; i < _numberOfVisibleItems; ++i) + _itemsByRow[i] = [_outlineDataSource outlineView:self child:i ofItem:nil]; + + [self loadTableCellsInRect:[self bounds]]; +} + +@end + +@implementation CPOutlineView (CPTableDataSource) + +- (void)numberOfRowsInTableView:(CPTableView)aTableView +{ + return _numberOfVisibleItems; +} + +- (void)tableView:(CPTableView)aTableView objectValueForTableColumn:(CPTableColumn)aTableColumn row:(int)aRowIndex +{ + return [_outlineDataSource outlineView:self objectValueForTableColumn:aTableColumn byItem:_itemsByRow[aRowIndex]]; +} + +@end \ No newline at end of file diff --git a/AppKit/CPPanel.j b/AppKit/CPPanel.j new file mode 100644 index 000000000..345acf5a4 --- /dev/null +++ b/AppKit/CPPanel.j @@ -0,0 +1,70 @@ +/* + * CPPanel.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPWindow.j" + + +CPOKButton = 1; +CPCancelButton = 0; + +@implementation CPPanel : CPWindow +{ + BOOL _becomesKeyOnlyIfNeeded; + BOOL _worksWhenModal; +} + +- (BOOL)isFloatingPanel +{ + return [self level] == CPFloatingWindowLevel; +} + +- (void)setFloatingPanel:(BOOL)isFloatingPanel +{ + [self setLevel:isFloatingPanel ? CPFloatingWindowLevel : CPNormalWindowLevel]; +} + +- (BOOL)becomesKeyOnlyIfNeeded +{ + return _becomesKeyOnlyIfNeeded; +} + +- (void)setBecomesKeyOnlyIfNeeded:(BOOL)shouldBecomeKeyOnlyIfNeeded +{ + _becomesKeyOnlyIfNeeded = shouldBecomeKeyOnlyIfNeeded +} + +- (BOOL)worksWhenModal +{ + return _worksWhenModal; +} + +- (void)setWorksWhenModal:(BOOL)shouldWorkWhenModal +{ + _worksWhenModal = shouldWorkWhenModal; +} + +- (BOOL)canBecomeMainWindow +{ + return NO; +} + +@end diff --git a/AppKit/CPPasteboard.j b/AppKit/CPPasteboard.j new file mode 100644 index 000000000..80283397f --- /dev/null +++ b/AppKit/CPPasteboard.j @@ -0,0 +1,226 @@ +/* + * CPPasteboard.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import +import +import + + +CPGeneralPboard = @"CPGeneralPboard"; +CPFontPboard = @"CPFontPboard"; +CPRulerPboard = @"CPRulerPboard"; +CPFindPboard = @"CPFindPboard"; +CPDragPboard = @"CPDragPboard"; + +CPColorPboardType = @"CPColorPboardType"; +CPFilenamesPboardType = @"CPFilenamesPboardType"; +CPFontPboardType = @"CPFontPboardType"; +CPHTMLPboardType = @"CPHTMLPboardType"; +CPStringPboardType = @"CPStringPboardType"; +CPURLPboardType = @"CPURLPboardType"; +CPImagePboardType = @"CPImagePboardType"; + +var CPPasteboards = nil; + +@implementation CPPasteboard : CPObject +{ + CPArray _types; + CPDictionary _owners; + CPDictionary _provided; + + unsigned _changeCount; + CPString _stateUID; +} + ++ (void)initialize +{ + if (self != [CPPasteboard class]) + return; + + [self setVersion:1.0]; + + CPPasteboards = [CPDictionary dictionary]; +} + ++ (id)generalPasteboard +{ + return [CPPasteboard pasteboardWithName:CPGeneralPboard]; +} + ++ (id)pasteboardWithName:(CPString)aName +{ + var pasteboard = [CPPasteboards objectForKey:aName]; + + if (pasteboard) + return pasteboard; + + pasteboard = [[CPPasteboard alloc] _initWithName:aName]; + [CPPasteboards setObject:pasteboard forKey:aName]; + + return pasteboard; +} + +- (id)_initWithName:(CPString)aName +{ + self = [super init]; + + if (self) + { + _name = aName; + _types = []; + + _owners = [CPDictionary dictionary]; + _provided = [CPDictionary dictionary]; + + _changeCount = 0; + } + + return self; +} + +- (unsigned)addTypes:(CPArray)types owner:(id)anOwner +{ + var i = 0, + count = types.length; + + for (; i < count; ++i) + { + var type = types[i]; + + if(![_owners objectForKey:type]) + { + [_types addObject:type]; + [_provided removeObjectForKey:type]; + } + + [_owners setObject:anOwner forKey:type]; + } + + return ++_changeCount; +} + +- (unsigned)declareTypes:(CPArray)types owner:(id)anOwner +{ + [_types setArray:types]; + + _owners = [CPDictionary dictionary]; + _provided = [CPDictionary dictionary]; + + var count = _types.length; + + while (count--) + [_owners setObject:anOwner forKey:_types[count]]; + + return ++_changeCount; +} + +- (BOOL)setData:(CPData)aData forType:(CPString)aType +{ + [_provided setObject:aData forKey:aType]; + + return YES; +} + +- (BOOL)setPropertyList:(id)aPropertyList forType:(CPString)aType +{ + return [self setData:[CPPropertyListSerialization dataFromPropertyList:aPropertyList format:CPPropertyListXMLFormat_v1_0 errorDescription:nil] forType:aType]; +} + +- (void)setString:(CPString)aString forType:(CPString)aType +{ + return [self setPropertyList:aString forType:aType]; +} + +// Determining Types + +- (CPString)availableTypeFromArray:(CPArray)anArray +{ + return [_types firstObjectCommonWithArray:anArray]; +} + +- (CPArray)types +{ + return _types; +} + +// Reading data + +- (unsigned)changeCount +{ + return _changeCount; +} + +- (CPData)dataForType:(CPString)aType +{ + var data = [_provided objectForKey:aType]; + + if (data) + return data; + + var owner = [_owners objectForKey:aType]; + + if (owner) + { + [owner pasteboard:self provideDataForType:aType]; + + ++_changeCount; + + return [_provided objectForKey:aType]; + } + + return nil; +} + +- (id)propertyListForType:(CPString)aType +{ + var data = [self dataForType:aType]; + + if (data) + return [CPPropertyListSerialization propertyListFromData:data format:CPPropertyListXMLFormat_v1_0 errorDescription:nil]; + + return nil; +} + +- (CPString)stringForType:(CPString)aType +{ + return [self propertyListForType:aType]; +} + +- (CPString)_generateStateUID +{ + var bits = 32; + + _stateUID = @""; + + while (bits--) + _stateUID += FLOOR(RAND() * 16.0).toString(16).toUpperCase(); + + return _stateUID; +} + +- (CPString)_stateUID +{ + return _stateUID; +} + +@end diff --git a/AppKit/CPPopUpButton.j b/AppKit/CPPopUpButton.j new file mode 100644 index 000000000..2c1898990 --- /dev/null +++ b/AppKit/CPPopUpButton.j @@ -0,0 +1,577 @@ +/* + * CPPopUpButton.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPButton.j" +import "CPGeometry.j" +import "CPMenu.j" +import "CPMenuItem.j" + + +var VISIBLE_MARGIN = 7.0; + +var CPPopUpButtonArrowsImage = nil; + +@implementation CPPopUpButton : CPButton +{ + BOOL _pullsDown; + int _selectedIndex; + CPRectEdge _preferredEdge; + + CPImageView _arrowsView; + + CPMenu _menu; +} + +- (id)initWithFrame:(CGRect)aFrame pullsDown:(BOOL)shouldPullDown +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _pullsDown = shouldPullDown; + _selectedIndex = CPNotFound; + _preferredEdge = CPMaxYEdge; + + [self setBezelStyle:CPTexturedRoundedBezelStyle]; + + [self setImagePosition:CPImageLeft]; + [self setAlignment:CPLeftTextAlignment]; + + [self setMenu:[[CPMenu alloc] initWithTitle:@""]]; + } + + return self; +} + +- (id)initWithFrame:(CGRect)aFrame +{ + return [self initWithFrame:aFrame pullsDown:NO]; +} + +- (void)setBordered:(BOOL)shouldBeBordered +{ + if (shouldBeBordered) + { + var bounds = [self bounds]; + + _arrowsView = [[CPImageView alloc] initWithFrame:CGRectMake(CGRectGetWidth(bounds) - 10.0, (CGRectGetHeight(bounds) - 8.0) / 2.0, 5.0, 8.0)]; + + if (!CPPopUpButtonArrowsImage) + CPPopUpButtonArrowsImage = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:[CPPopUpButton class]] pathForResource:@"CPPopUpButton/CPPopUpButtonArrows.png"] size:CGSizeMake(5.0, 8.0)]; + + [_arrowsView setImage:CPPopUpButtonArrowsImage]; + [_arrowsView setAutoresizingMask:CPViewMaxXMargin | CPViewMinYMargin | CPViewMaxYMargin]; + + + [self addSubview:_arrowsView]; + } + else + { + [_arrowsView removeFromSuperview]; + + _arrowsView = nil; + } + + [super setBordered:shouldBeBordered]; +} + +// Setting the Type of Menu + +- (void)setPullsDown:(BOOL)shouldPullDown +{ + if (_pullsDown == shouldPullDown) + return; + + _pullsDown = shouldPullDown; + + var items = [_menu itemArray]; + + if (items.length <= 0) + return; + + [items[0] setHidden:_pullsDown]; + + [self synchronizeTitleAndSelectedItem]; +} + +- (BOOL)pullsDown +{ + return _pullsDown; +} + +// Inserting and Deleting Items + +- (void)addItemWithTitle:(CPString)aTitle +{ + [_menu addItemWithTitle:aTitle action:NULL keyEquivalent:NULL]; +} + +- (void)addItemsWithTitles:(CPArray)titles +{ + var index = 0, + count = [titles count]; + + for (; index < count; ++index) + [self addItemWithTitle:titles[index]]; +} + +- (void)insertItemWithTitle:(CPString)aTitle atIndex:(int)anIndex +{ + var items = [self itemArray], + count = [items count]; + + while (count--) + if ([items[count] title] == aTitle) + [self removeItemAtIndex:count]; + + [_menu insertItemWithTitle:aTitle action:NULL keyEquivalent:NULL atIndex:anIndex]; +} + +- (void)removeAllItems +{ + var count = [_menu numberOfItems]; + + while (count--) + [_menu removeItemAtIndex:0]; +} + +- (void)removeItemWithTitle:(CPString)aTitle +{ + [self removeItemAtIndex:[self indexOfItemWithTitle:aTitle]]; + [self synchronizeTitleAndSelectedItem]; +} + +- (void)removeItemAtIndex:(int)anIndex +{ + [_menu removeItemAtIndex:anIndex]; + [self synchronizeTitleAndSelectedItem]; +} + +// Getting the User's Selection + +- (CPMenuItem)selectedItem +{ + if (_selectedIndex < 0) + return nil; + + return [_menu itemAtIndex:_selectedIndex]; +} + +- (CPString)titleOfSelectedItem +{ + return [[self selectedItem] title]; +} + +- (int)indexOfSelectedItem +{ + return _selectedIndex; +} + +// For us, CPNumber is toll-free bridged to Number, so just return the selected index. +- (id)objectValue +{ + return _selectedIndex; +} + +// Setting the Current Selection + +- (void)selectItem:(CPMenuItem)aMenuItem +{ + [self selectItemAtIndex:[self indexOfItem:aMenuItem]]; +} + +- (void)selectItemAtIndex:(int)anIndex +{ + if (_selectedIndex == anIndex) + return; + + if (_selectedIndex >= 0 && !_pullsDown) + [[self selectedItem] setState:CPOffState]; + + _selectedIndex = anIndex; + + if (_selectedIndex >= 0 && !_pullsDown) + [[self selectedItem] setState:CPOnState]; + + [self synchronizeTitleAndSelectedItem]; +} + +- (void)selectItemWithTag:(int)aTag +{ + [self selectItemAtIndex:[self indexOfItemWithTag:aTag]]; +} + +- (void)selectItemWithTitle:(CPString)aTitle +{ + [self selectItemAtIndex:[self indexOfItemWithTitle:aTitle]]; +} + +- (void)setObjectValue:(id)aValue +{ + [self selectItemAtIndex:[aValue intValue]]; +} + +// Getting Menu Items + +- (CPMenu)menu +{ + return _menu; +} + +- (void)setMenu:(CPMenu)aMenu +{ + if (_menu == aMenu) + return; + + var defaultCenter = [CPNotificationCenter defaultCenter]; + + if (_menu) + { + [defaultCenter + removeObserver:self + selector:@selector(menuDidAddItem:) + name:CPMenuDidAddItemNotification + object:_menu]; + + [defaultCenter + removeObserver:self + selector:@selector(menuDidChangeItem:) + name:CPMenuDidChangeItemNotification + object:_menu]; + + [defaultCenter + removeObserver:self + selector:@selector(menuDidRemoveItem:) + name:CPMenuDidRemoveItemNotification + object:_menu]; + } + + _menu = aMenu; + + if (_menu) + { + [defaultCenter + addObserver:self + selector:@selector(menuDidAddItem:) + name:CPMenuDidAddItemNotification + object:_menu]; + + [defaultCenter + addObserver:self + selector:@selector(menuDidChangeItem:) + name:CPMenuDidChangeItemNotification + object:_menu]; + + [defaultCenter + addObserver:self + selector:@selector(menuDidRemoveItem:) + name:CPMenuDidRemoveItemNotification + object:_menu]; + } + + [self synchronizeTitleAndSelectedItem]; +} + +- (int)numberOfItems +{ + return [_menu numberOfItems]; +} + +- (CPArray)itemArray +{ + return [_menu itemArray]; +} + +- (CPMenuItem)itemAtIndex:(unsigned)anIndex +{ + return [_menu itemAtIndex:anIndex]; +} + +- (CPString)itemTitleAtIndex:(unsigned)anIndex +{ + return [[_menu itemAtIndex:anIndex] title]; +} + +- (CPArray)itemTitles +{ + var titles = [], + items = [self itemArray], + + index = 0, + count = [items count]; + + for (; index < count; ++index) + items.push([items[index] title]); +} + +- (CPMenuItem)itemWithTitle:(CPString)aTitle +{ + return [_menu itemAtIndex:[_menu indexOfItemWithTitle:aTitle]]; +} + +- (CPMenuItem)lastItem +{ + return [[_menu itemArray] lastObject]; +} + +// Getting the Indices of Menu Items + +- (int)indexOfItem:(CPMenuItem)aMenuItem +{ + return [_menu indexOfItem:aMenuItem]; +} + +- (int)indexOfItemWithTag:(int)aTag +{ + return [_menu indexOfItemWithTag:aMenuItem]; +} + +- (int)indexOfItemWithTitle:(CPString)aTitle +{ + return [_menu indexOfItemWithTitle:aTitle]; +} + +- (int)indexOfItemWithRepresentedObject:(id)anObject +{ + return [_menu indexOfItemWithRepresentedObejct:anObject]; +} + +- (int)indexOfItemWithTarget:(id)aTarget action:(SEL)anAction +{ + return [_menu indexOfItemWithTarget:aTarget action:anAction]; +} + +// Setting the Cell Edge to Pop out in Restricted Situations + +- (CPRectEdge)preferredEdge +{ + return _preferredEdge; +} + +- (void)setPreferredEdge:(CPRectEdge)aRectEdge +{ + _preferredEdge = aRectEdge; +} + +// Setting the Title + +- (void)setTitle:(CPString)aTitle +{ + if ([self title] == aTitle) + return; + + if (_pullsDown) + { + [_items[0] setTitle:aTitle]; + [self synchronizeTitleAndSelectedItem]; + } + else + { + var index = [self indexOfItemWithTitle:aTitle]; + + if (index < 0) + { + [self addItemWithTitle:aTitle]; + + index = [self numberOfItems] - 1; + } + + [self selectItemAtIndex:index]; + } +} + +// Setting the Image + +- (void)setImage:(CPImage)anImage +{ + // The Image is set by the currently selected item. +} + +// Setting the State + +- (void)synchronizeTitleAndSelectedItem +{ + var item = nil; + + if (_pullsDown) + { + var items = [_menu itemArray]; + + if (items.length > 0) + item = items[0]; + } + else + item = [self selectedItem]; + + [super setImage:[item image]]; + [super setTitle:[item title]]; +} + +// + +- (void)menuDidAddItem:(CPNotification)aNotification +{ + var index = [[aNotification userInfo] objectForKey:@"CPMenuItemIndex"]; + + if (_selectedIndex < 0) + [self selectItemAtIndex:0]; + + else if (index == _selectedIndex) + [self synchronizeTitleAndSelectedItem]; + + else if (index < _selectedIndex) + ++_selectedIndex; + + if (index == 0 && _pullsDown) + { + var items = [_menu itemArray]; + + [items[0] setHidden:YES]; + + if (items.length > 0) + [items[1] setHidden:NO]; + } +} + +- (void)menuDidChangeItem:(CPNotification)aNotification +{ + var index = [[aNotification userInfo] objectForKey:@"CPMenuItemIndex"]; + + if (_pullsDown && index != 0) + return; + + if (!_pullsDown && index != _selectedIndex) + return; + + [self synchronizeTitleAndSelectedItem]; +} + +- (void)menuDidRemoveItem:(CPNotification)aNotification +{ + var numberOfItems = [self numberOfItems]; + + if (numberOfItems <= _selectedIndex) + [self selectItemAtIndex:numberOfItems - 1]; +} + +- (void)mouseDown:(CPEvent)anEvent +{ + if (![self isEnabled]) + return; + + [self highlight:YES]; + + var theWindow = [self window], + menuWindow = [_CPMenuWindow menuWindowWithMenu:[self menu] font:[self font]]; + + [menuWindow setDelegate:self]; + [menuWindow setBackgroundStyle:_CPMenuWindowPopUpBackgroundStyle]; + + var menuOrigin = [theWindow convertBaseToBridge:[self convertPoint:CGPointMakeZero() toView:nil]]; + + // Pull Down Menus show up directly below their buttons. + if (_pullsDown) + menuOrigin.y += CGRectGetHeight([self frame]); + + // Pop Up Menus attempt to show up "on top" of the selected item. + else + { + var contentRect = [menuWindow rectForItemAtIndex:_selectedIndex]; + + menuOrigin.x -= CGRectGetMinX(contentRect) + [_CPMenuItemView leftMargin]; + menuOrigin.y -= CGRectGetMinY(contentRect); + } + + [menuWindow setFrameOrigin:menuOrigin]; + + var menuMaxX = CGRectGetMaxX([menuWindow frame]), + buttonMaxX = CGRectGetMaxX([self convertRect:[self bounds] toView:nil]); + + if (menuMaxX < buttonMaxX) + [menuWindow setMinWidth:CGRectGetWidth([menuWindow frame]) + buttonMaxX - menuMaxX - VISIBLE_MARGIN]; + + [menuWindow orderFront:self]; + [menuWindow beginTrackingWithEvent:anEvent sessionDelegate:self didEndSelector:@selector(menuWindowDidFinishTracking:highlightedItem:)]; +} + +- (void)menuWindowDidFinishTracking:(_CPMenuWindow)aMenuWindow highlightedItem:(CPMenuItem)aMenuItem +{ + [_CPMenuWindow poolMenuWindow:aMenuWindow]; + + [self highlight:NO]; + + var index = [_menu indexOfItem:aMenuItem]; + + if (index == CPNotFound) + return; + + [self selectItemAtIndex:index]; + + var selectedItem = [self selectedItem], + target = nil, + action = [selectedItem action]; + + if (!action) + { + target = [self target]; + action = [self action]; + } + + // FIXME: If [selectedItem target] == nil do we use our own target? + else + target = [selectedItem target]; + + [self sendAction:action to:target]; +} + +@end + +var CPPopUpButtonMenuKey = @"CPPopUpButtonMenuKey", + CPPopUpButtonSelectedIndexKey = @"CPPopUpButtonSelectedIndexKey", + CPPopUpButtonPullsDownKey = @"CPPopUpButtonPullsDownKey"; + +@implementation CPPopUpButton (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super initWithCoder:aCoder]; + + if (self) + { + [self setMenu:[aCoder decodeObjectForKey:CPPopUpButtonMenuKey]]; + [self selectItemAtIndex:[aCoder decodeObjectForKey:CPPopUpButtonSelectedIndexKey]]; + [self setPullsDown:[aCoder decodeBoolForKey:CPPopUpButtonPullsDownKey]]; + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [super encodeWithCoder:aCoder]; + + [aCoder encodeObject:_menu forKey:CPPopUpButtonMenuKey]; + [aCoder encodeInt:_selectedIndex forKey:CPPopUpButtonSelectedIndexKey]; + [aCoder encodeBool:_pullsDown forKey:CPPopUpButtonPullsDownKey]; +} + +@end diff --git a/AppKit/CPProgressIndicator.j b/AppKit/CPProgressIndicator.j new file mode 100644 index 000000000..e5717ed40 --- /dev/null +++ b/AppKit/CPProgressIndicator.j @@ -0,0 +1,375 @@ +/* + * CPProgressIndicator.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import +import + +#include "CoreGraphics/CGGeometry.h" + + +CPProgressIndicatorBarStyle = 0; +CPProgressIndicatorSpinningStyle = 1; +CPProgressIndicatorHUDBarStyle = 2; + +var CPProgressIndicatorSpinningStyleColors = nil, + + CPProgressIndicatorClassName = nil, + CPProgressIndicatorStyleIdentifiers = nil, + CPProgressIndicatorStyleSizes = nil; + +@implementation CPProgressIndicator : CPView +{ + double _minValue; + double _maxValue; + + double _doubleValue; + + CPControlSize _controlSize; + + BOOL _isIndeterminate; + CPProgressIndicatorStyle _style; + + BOOL _isAnimating; + + BOOL _isDisplayedWhenStoppedSet; + BOOL _isDisplayedWhenStopped; + + CPView _barView; +} + ++ (void)initialize +{ + if (self != [CPProgressIndicator class]) + return; + + var bundle = [CPBundle bundleForClass:self]; + + CPProgressIndicatorSpinningStyleColors = []; + + CPProgressIndicatorSpinningStyleColors[CPMiniControlSize] = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile: + [bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif"] size:CGSizeMake(64.0, 64.0)]]; + CPProgressIndicatorSpinningStyleColors[CPSmallControlSize] = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile: + [bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif"] size:CGSizeMake(64.0, 64.0)]]; + CPProgressIndicatorSpinningStyleColors[CPRegularControlSize] = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile: + [bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif"] size:CGSizeMake(64.0, 64.0)]]; + + CPProgressIndicatorBezelBorderViewPool = []; + + var start = CPProgressIndicatorBarStyle, + end = CPProgressIndicatorHUDBarStyle; + + for (; start <= end; ++start) + { + CPProgressIndicatorBezelBorderViewPool[start] = []; + + CPProgressIndicatorBezelBorderViewPool[start][CPMiniControlSize] = []; + CPProgressIndicatorBezelBorderViewPool[start][CPSmallControlSize] = []; + CPProgressIndicatorBezelBorderViewPool[start][CPRegularControlSize] = []; + } + + CPProgressIndicatorClassName = [self className]; + + + CPProgressIndicatorStyleIdentifiers = []; + + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle] = @"Bar"; + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorSpinningStyle] = @"Spinny"; + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorHUDBarStyle] = @"HUDBar"; + + var regularIdentifier = _CPControlIdentifierForControlSize(CPRegularControlSize), + smallIdentifier = _CPControlIdentifierForControlSize(CPSmallControlSize), + miniIdentifier = _CPControlIdentifierForControlSize(CPMiniControlSize); + + CPProgressIndicatorStyleSizes = []; + + // Bar Sttyle + var prefix = CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle]; + + CPProgressIndicatorStyleSizes[prefix + regularIdentifier] = [_CGSizeMake(3.0, 15.0), _CGSizeMake(1.0, 15.0), _CGSizeMake(3.0, 15.0)]; + CPProgressIndicatorStyleSizes[prefix + smallIdentifier] = [_CGSizeMake(3.0, 15.0), _CGSizeMake(1.0, 15.0), _CGSizeMake(3.0, 15.0)]; + CPProgressIndicatorStyleSizes[prefix + miniIdentifier] = [_CGSizeMake(3.0, 15.0), _CGSizeMake(1.0, 15.0), _CGSizeMake(3.0, 15.0)]; + + prefix = CPProgressIndicatorClassName + @"Bar" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle]; + + CPProgressIndicatorStyleSizes[prefix + regularIdentifier] = _CGSizeMake(1.0, 9.0); + CPProgressIndicatorStyleSizes[prefix + smallIdentifier] = _CGSizeMake(1.0, 9.0); + CPProgressIndicatorStyleSizes[prefix + miniIdentifier] = _CGSizeMake(1.0, 9.0); + + // HUD Bar Style + prefix = CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorHUDBarStyle]; + + CPProgressIndicatorStyleSizes[prefix + regularIdentifier] = [_CGSizeMake(3.0, 15.0), _CGSizeMake(1.0, 15.0), _CGSizeMake(3.0, 15.0)]; + CPProgressIndicatorStyleSizes[prefix + smallIdentifier] = [_CGSizeMake(3.0, 15.0), _CGSizeMake(1.0, 15.0), _CGSizeMake(3.0, 15.0)]; + CPProgressIndicatorStyleSizes[prefix + miniIdentifier] = [_CGSizeMake(3.0, 15.0), _CGSizeMake(1.0, 15.0), _CGSizeMake(3.0, 15.0)]; + + prefix = CPProgressIndicatorClassName + @"Bar" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorHUDBarStyle]; + + CPProgressIndicatorStyleSizes[prefix + regularIdentifier] = _CGSizeMake(1.0, 9.0); + CPProgressIndicatorStyleSizes[prefix + smallIdentifier] = _CGSizeMake(1.0, 9.0); + CPProgressIndicatorStyleSizes[prefix + miniIdentifier] = _CGSizeMake(1.0, 9.0); +} + +- (id)initWithFrame:(CGRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _minValue = 0.0; + _maxValue = 100.0; + + _doubleValue = 0.0; + + _style = CPProgressIndicatorBarStyle; + _isDisplayedWhenStoppedSet = NO; + + _controlSize = CPRegularControlSize; + + [self updateBackgroundColor]; + [self drawBar]; + } + + return self; +} + +- (void)setUsesThreadedAnimation:(BOOL)aFlag +{ +} + +- (void)startAnimation:(id)aSender +{ + _isAnimating = YES; + + [self _hideOrDisplay]; +} + +- (void)stopAnimation:(id)aSender +{ + _isAnimating = NO; + + [self _hideOrDisplay]; +} + +- (BOOL)usesThreadedAnimation +{ + return NO; +} + +// Advancing the Progress Bar + +- (void)incrementBy:(double)aValue +{ + [self setDoubleValue:_doubleValue + aValue]; +} + +- (void)setDoubleValue:(double)aValue +{ + _doubleValue = MIN(MAX(aValue, _minValue), _maxValue); + + [self drawBar]; +} + +- (double)doubleValue +{ + return _doubleValue; +} + +- (void)setMinValue:(double)aValue +{ + _minValue = aValue; +} + +- (double)minValue +{ + return _minValue; +} + +- (void)setMaxValue:(double)aValue +{ + _maxValue = aValue; +} + +- (double)maxValue +{ + return _maxValue; +} + +// Setting the Appearance + +- (void)setControlSize:(CPControlSize)aControlSize +{ + if (_controlSize == aControlSize) + return; + + _controlSize = aControlSize; + + [self updateBackgroundColor]; +} + +- (CPControlSize)controlSize +{ + return _controlSize; +} + +- (void)setControlTint:(CPControlTint)aControlTint +{ +} + +- (CPControlTint)controlTint +{ + return 0; +} + +- (void)setBezeled:(BOOL)isBezeled +{ +} + +- (BOOL)isBezeled +{ + return YES; +} + +- (void)setIndeterminate:(BOOL)isIndeterminate +{ + if (_indeterminate == isIndeterminate) + return; + + _isIndeterminate = isIndeterminate; + + [self updateBackgroundColor]; +} + +- (BOOL)isIndeterminate +{ + return _isIndeterminate; +} + +- (void)setStyle:(CPProgressIndicatorStyle)aStyle +{ + if (_style == aStyle) + return; + + _style = aStyle; + + [self updateBackgroundColor]; +} + +- (void)sizeToFit +{ + if (_style == CPProgressIndicatorSpinningStyle) + [self setFrameSize:[[CPProgressIndicatorSpinningStyleColors[_controlSize] patternImage] size]]; + else + [self setFrameSize:CGSizeMake(CGRectGetWidth([self frame]), CPProgressIndicatorStyleSizes[ + CPProgressIndicatorClassName + @"BezelBorder" + CPProgressIndicatorStyleIdentifiers[CPProgressIndicatorBarStyle] + + _CPControlIdentifierForControlSize(_controlSize)][0].height)]; +} + +- (void)setDisplayedWhenStopped:(BOOL)isDisplayedWhenStopped +{ + if (_isDisplayedWhenStoppedSet && _isDisplayedWhenStopped == isDisplayedWhenStopped) + return; + + _isDisplayedWhenStoppedSet = YES; + + _isDisplayedWhenStopped = isDisplayedWhenStopped; + + [self _hideOrDisplay]; +} + +- (BOOL)isDisplayedWhenStopped +{ + if (_isDisplayedWhenStoppedSet) + return _isDisplayedWhenStopped; + + if (_style == CPProgressIndicatorBarStyle || _style == CPProgressIndicatorHUDBarStyle) + return YES; + + return NO; +} + +- (void)_hideOrDisplay +{ + [self setHidden:!_isAnimating && ![self isDisplayedWhenStopped]]; +} + +- (void)setFrameSize:(CGSize)aSize +{ + [super setFrameSize:aSize]; + + [self drawBar]; +} + +- (void)drawBar +{ + if (_style == CPProgressIndicatorSpinningStyle) + return; + + if (!_barView) + { + _barView = [[CPView alloc] initWithFrame:CGRectMake(2.0, 2.0, 0.0, 9.0)]; + + [_barView setBackgroundColor:[CPColor redColor]]; + + [self addSubview:_barView]; + } + + [_barView setBackgroundColor:_CPControlColorWithPatternImage( + CPProgressIndicatorStyleSizes, + CPProgressIndicatorClassName, + @"Bar", + CPProgressIndicatorStyleIdentifiers[_style], + _CPControlIdentifierForControlSize(_controlSize))]; + + [_barView setFrameSize:CGSizeMake(CGRectGetWidth([self bounds]) * (_doubleValue - _minValue) / (_maxValue - _minValue) - 4.0, 9.0)]; +} + +- (void)updateBackgroundColor +{ + if (YES)//_isBezeled) + { + if (_style == CPProgressIndicatorSpinningStyle) + { + [_barView removeFromSuperview]; + + _barView = nil; + + [self setBackgroundColor:CPProgressIndicatorSpinningStyleColors[_controlSize]]; + } + else + { + [self setBackgroundColor:_CPControlThreePartImagePattern( + NO, + CPProgressIndicatorStyleSizes, + CPProgressIndicatorClassName, + @"BezelBorder", + CPProgressIndicatorStyleIdentifiers[_style], + _CPControlIdentifierForControlSize(_controlSize))]; + + [self drawBar]; + } + } + else + [self setBackgroundColor:nil]; +} + +@end diff --git a/AppKit/CPResponder.j b/AppKit/CPResponder.j new file mode 100644 index 000000000..e51ed792f --- /dev/null +++ b/AppKit/CPResponder.j @@ -0,0 +1,225 @@ +/* + * CPResponder.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + +CPDeleteKeyCode = 8; +CPUpArrowKeyCode = 63232; +CPDownArrowKeyCode = 63233; +CPLeftArrowKeyCode = 63234; +CPRightArrowKeyCode = 63235; + +@implementation CPResponder : CPObject +{ + CPMenu _menu; + CPResponder _nextResponder; +} + +// Changing the first responder + +- (BOOL)acceptsFirstResponder +{ + return NO; +} + +- (BOOL)becomeFirstResponder +{ + return YES; +} + +- (BOOL)resignFirstResponder +{ + return YES; +} + +// Setting the next responder + +- (void)setNextResponder:(CPResponder)aResponder +{ + _nextResponder = aResponder; +} + +- (CPResponder)nextResponder +{ + return _nextResponder; +} + +- (void)interpretKeyEvents:(CPArray)events +{ + var event, + index = 0; + + while(event = events[index++]) + { + switch([event keyCode]) + { + case CPLeftArrowKeyCode: [self moveBackward:self]; + break; + case CPRightArrowKeyCode: [self moveForward:self]; + break; + case CPUpArrowKeyCode: [self moveUp:self]; + break; + case CPDownArrowKeyCode: [self moveDown:self]; + break; + case CPDeleteKeyCode: [self deleteBackward:self]; + break; + case 3: + case 13: [self insertLineBreak:self]; + break; + default: [self insertText:[event characters]]; + } + } +} + +- (void)mouseDown:(CPEvent)anEvent +{ + [_nextResponder performSelector:_cmd withObject:anEvent]; +} + +- (void)mouseDragged:(CPEvent)anEvent +{ + [_nextResponder performSelector:_cmd withObject:anEvent]; +} + +- (void)mouseUp:(CPEvent)anEvent +{ + [_nextResponder performSelector:_cmd withObject:anEvent]; +} + +- (void)mouseMoved:(CPEvent)anEvent +{ + [_nextResponder performSelector:_cmd withObject:anEvent]; +} + +- (void)mouseEntered:(CPEvent)anEvent +{ + [_nextResponder performSelector:_cmd withObject:anEvent]; +} + +- (void)mouseExited:(CPEvent)anEvent +{ + [_nextResponder performSelector:_cmd withObject:anEvent]; +} + +- (void)scrollWheel:(CPEvent)anEvent +{ + [_nextResponder performSelector:_cmd withObject:anEvent]; +} + +- (void)keyDown:(CPEvent)anEvent +{ + [_nextResponder performSelector:_cmd withObject:anEvent]; +} + +- (void)keyUp:(CPEvent)anEvent +{ + [_nextResponder performSelector:_cmd withObject:anEvent]; +} + +- (BOOL)performKeyEquivalent:(CPEvent)anEvent +{ + return NO; +} + +// Action Methods + +- (void)deleteBackward:(id)aSender +{ +} + +- (void)insertLineBreak:(id)aSender +{ +} + +- (void)insertText:(CPString)aString +{ +} + +// Dispatch methods + +- (void)doCommandBySelector:(SEL)aSelector +{ + if([self respondsToSelector:aSelector]) + [self performSelector:aSelector]; + else + [_nextResponder doCommandBySelector:aSelector]; +} + +- (BOOL)tryToPerform:(SEL)aSelector with:(id)anObject +{ + if([self respondsToSelector:aSelector]) + { + [self performSelector:aSelector withObject:anObject]; + + return YES; + } + + return [_nextResponder tryToPerform:aSelector with:anObject]; +} + +// Managing a Responder's menu + +- (void)setMenu:(CPMenu)aMenu +{ + _menu = aMenu; +} + +- (CPMenu)menu +{ + return _menu; +} + +// Getting the Undo Manager + +- (CPUndoManager)undoManager +{ + return [_nextResponder performSelector:_cmd]; +} + +// Terminating the responder chain + +- (void)noResponderFor:(SEL)anEventSelector +{ +} + +@end + +var CPResponderNextResponderKey = @"CPResponderNextResponderKey"; + +@implementation CPResponder (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [self init]; + + if (self) + _nextResponder = [aCoder decodeObjectForKey:CPResponderNextResponderKey]; + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeConditionalObject:_nextResponder forKey:CPResponderNextResponderKey]; +} + +@end diff --git a/AppKit/CPScrollView.j b/AppKit/CPScrollView.j new file mode 100644 index 000000000..30cacbe55 --- /dev/null +++ b/AppKit/CPScrollView.j @@ -0,0 +1,467 @@ +/* + * CPScrollView.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPView.j" +import "CPClipView.j" +import "CPScroller.j" + +#include "CoreGraphics/CGGeometry.h" + + +@implementation CPScrollView : CPView +{ + CPClipView _contentView; + + BOOL _hasVerticalScroller; + BOOL _hasHorizontalScroller; + BOOL _autohidesScrollers; + + CPScroller _verticalScroller; + CPScroller _horizontalScroller; + + int _recursionCount; + + float _verticalLineScroll; + float _verticalPageScroll; + float _horizontalLineScroll; + float _horizontalPageScroll; +} + +- (id)initWithFrame:(CPRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _verticalLineScroll = 10.0; + _verticalPageScroll = 10.0; + + _horizontalLineScroll = 10.0; + _horizontalPageScroll = 10.0; + + _contentView = [[CPClipView alloc] initWithFrame:[self bounds]]; + + [self addSubview:_contentView]; + + [self setHasVerticalScroller:YES]; + [self setHasHorizontalScroller:YES]; + } + + return self; +} + +// Determining component sizes +- (CPRect)contentSize +{ + return [_contentView frame].size; +} + +- (id)documentView +{ + return [_contentView documentView]; +} + +- (void)setContentView:(CPClipView)aContentView +{ + if (!aContentView) + return; + + var documentView = [aContentView documentView]; + + if (documentView) + [documentView removeFromSuperview]; + + [_contentView removeFromSuperview]; + + var size = [self contentSize]; + + _contentView = aContentView; + + [_contentView setFrame:CGRectMake(0.0, 0.0, size.width, size.height)]; + [_contentView setDocumentView:documentView]; + + [self addSubview:_contentView]; +} + +- (CPClipView)contentView +{ + return _contentView; +} + +- (void)setDocumentView:(CPView)aView +{ + [_contentView setDocumentView:aView]; + [self reflectScrolledClipView:_contentView]; +} + +- (void)reflectScrolledClipView:(CPClipView)aClipView +{ + if(_contentView != aClipView) + return; + + if (_recursionCount > 5) + return; + + ++_recursionCount; + + var documentView = [self documentView]; + + if (!documentView) + { + if (_autohidesScrollers) + { + [_verticalScroller setHidden:YES]; + [_horizontalScroller setHidden:YES]; + } + else + { + [_verticalScroller setEnabled:NO]; + [_horizontalScroller setEnabled:NO]; + } + + [_contentView setFrame:[self bounds]]; + + --_recursionCount; + + return; + } + + var documentFrame = [documentView frame], + contentViewFrame = [self bounds], + scrollPoint = [_contentView bounds].origin, + difference = _CGSizeMake(CPRectGetWidth(documentFrame) - CPRectGetWidth(contentViewFrame), CPRectGetHeight(documentFrame) - CPRectGetHeight(contentViewFrame)), + shouldShowVerticalScroller = (!_autohidesScrollers || difference.height > 0.0) && _hasVerticalScroller, + shouldShowHorizontalScroller = (!_autohidesScrollers || difference.width > 0.0) && _hasHorizontalScroller, + wasShowingVerticalScroller = ![_verticalScroller isHidden], + wasShowingHorizontalScroller = ![_horizontalScroller isHidden], + verticalScrollerWidth = [CPScroller scrollerWidthForControlSize:[_verticalScroller controlSize]], + horizontalScrollerHeight = [CPScroller scrollerWidthForControlSize:[_horizontalScroller controlSize]]; + + if (_autohidesScrollers) + { + if (shouldShowVerticalScroller) + shouldShowHorizontalScroller = (!_autohidesScrollers || difference.width > -verticalScrollerWidth) && _hasHorizontalScroller; + if (shouldShowHorizontalScroller) + shouldShowVerticalScroller = (!_autohidesScrollers || difference.height > -horizontalScrollerHeight) && _hasVerticalScroller; + } + + [_verticalScroller setHidden:!shouldShowVerticalScroller]; + [_verticalScroller setEnabled:!_autohidesScrollers && difference.height < 0]; + + [_horizontalScroller setHidden:!shouldShowHorizontalScroller]; + [_horizontalScroller setEnabled:!_autohidesScrollers && difference.width < 0]; + + if (shouldShowVerticalScroller) + { + var verticalScrollerHeight = CPRectGetHeight(contentViewFrame); + + if (shouldShowHorizontalScroller) + verticalScrollerHeight -= horizontalScrollerHeight; + + difference.width += verticalScrollerWidth; + contentViewFrame.size.width -= verticalScrollerWidth; + + [_verticalScroller setFloatValue:(difference.height <= 0.0) ? 0.0 : scrollPoint.y / difference.height + knobProportion:CPRectGetHeight(contentViewFrame) / CPRectGetHeight(documentFrame)]; + [_verticalScroller setFrame:CPRectMake(CPRectGetMaxX(contentViewFrame), 0.0, verticalScrollerWidth, verticalScrollerHeight)]; + } + else if (wasShowingVerticalScroller) + [_verticalScroller setFloatValue:0.0 knobProportion:1.0]; + + if (shouldShowHorizontalScroller) + { + difference.height += horizontalScrollerHeight; + contentViewFrame.size.height -= horizontalScrollerHeight; + + [_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width + knobProportion:CPRectGetWidth(contentViewFrame) / CPRectGetWidth(documentFrame)]; + [_horizontalScroller setFrame:CPRectMake(0.0, CPRectGetMaxY(contentViewFrame), CPRectGetWidth(contentViewFrame), horizontalScrollerHeight)]; + } + else if (wasShowingHorizontalScroller) + [_horizontalScroller setFloatValue:0.0 knobProportion:1.0]; + + [_contentView setFrame:contentViewFrame]; + + // The reason we have to do this is because this is called on a frame size change, so when the frame changes, + // so does the the float value, so we have to update the clip view accordingly. + if (_hasVerticalScroller && (shouldShowVerticalScroller || wasShowingVerticalScroller)) + { + //[self _verticalScrollerDidScroll:_verticalScroller]; + var value = [_verticalScroller floatValue], + contentBounds = [_contentView bounds]; + + contentBounds.origin.y = value * (_CGRectGetHeight([[_contentView documentView] frame]) - _CGRectGetHeight(contentBounds)); + + [_contentView scrollToPoint:contentBounds.origin]; + } + if (_hasHorizontalScroller && (shouldShowHorizontalScroller || wasShowingHorizontalScroller)) + { + //[self _horizontalScrollerDidScroll:_horizontalScroller]; + + var value = [_horizontalScroller floatValue], + contentBounds = [_contentView bounds]; + + contentBounds.origin.x = value * (_CGRectGetWidth([[_contentView documentView] frame]) - _CGRectGetWidth(contentBounds)); + + [_contentView scrollToPoint:contentBounds.origin]; + } + + --_recursionCount; +} + +// Managing Scrollers + +- (void)setHorizontalScroller:(CPScroller)aScroller +{ + if (_horizontalScroller == aScroller) + return; + + [_horizontalScroller removeFromSuperview]; + [_horizontalScroller setTarget:nil]; + [_horizontalScroller setAction:nil]; + + _horizontalScroller = aScroller; + + [_horizontalScroller setTarget:self]; + [_horizontalScroller setAction:@selector(_horizontalScrollerDidScroll:)]; + [self addSubview:_horizontalScroller]; +} + +- (CPScroller)horizontalScroller +{ + return _horizontalScroller; +} + +- (void)setHasHorizontalScroller:(BOOL)hasHorizontalScroller +{ + _hasHorizontalScroller = hasHorizontalScroller; + + if (_hasHorizontalScroller && !_horizontalScroller) + [self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CPRectMake(0.0, 0.0, CPRectGetWidth([self bounds]), [CPScroller scrollerWidth])]]; + else if (!hasHorizontalScroller && _horizontalScroller) + [_horizontalScroller setHidden:YES]; +} + +- (BOOL)hasHorizontalScroller +{ + return _hasHorizontalScroller; +} + +- (void)setVerticalScroller:(CPScroller)aScroller +{ + if (_verticalScroller == aScroller) + return; + + [_verticalScroller removeFromSuperview]; + [_verticalScroller setTarget:nil]; + [_verticalScroller setAction:nil]; + + _verticalScroller = aScroller; + + [_verticalScroller setTarget:self]; + [_verticalScroller setAction:@selector(_verticalScrollerDidScroll:)]; + [self addSubview:_verticalScroller]; +} + +- (CPScroller)verticalScroller +{ + return _verticalScroller; +} + +- (void)setHasVerticalScroller:(BOOL)hasVerticalScroller +{ + _hasVerticalScroller = hasVerticalScroller; + + if (_hasVerticalScroller && !_verticalScroller) + [self setVerticalScroller:[[CPScroller alloc] initWithFrame:CPRectMake(0.0, 0.0, [CPScroller scrollerWidth], CPRectGetHeight([self bounds]))]]; + else if (!hasVerticalScroller && _verticalScroller) + [_verticalScroller setHidden:YES]; +} + +- (BOOL)hasHorizontalScroller +{ + return _hasHorizontalScroller; +} + +- (void)setAutohidesScrollers:(BOOL)autohidesScrollers +{ + _autohidesScrollers = autohidesScrollers; +} + +- (BOOL)autohidesScrollers +{ + return _autohidesScrollers; +} +/* +- (void)setFrameSize:(CPRect)aSize +{ + [super setFrameSize:aSize]; + + [self reflectScrolledClipView:_contentView]; +}*/ + +- (void)_verticalScrollerDidScroll:(CPScroller)aScroller +{ + var value = [aScroller floatValue], + documentFrame = [[_contentView documentView] frame]; + contentBounds = [_contentView bounds]; + + switch ([_verticalScroller hitPart]) + { + case CPScrollerDecrementLine: contentBounds.origin.y -= _verticalLineScroll; + break; + + case CPScrollerIncrementLine: contentBounds.origin.y += _verticalLineScroll; + break; + + case CPScrollerDecrementPage: contentBounds.origin.y -= _CGRectGetHeight(contentBounds) - _verticalPageScroll; + break; + + case CPScrollerIncrementPage: contentBounds.origin.y += _CGRectGetHeight(contentBounds) - _verticalPageScroll; + break; + + case CPScrollerKnobSlot: + case CPScrollerKnob: + default: contentBounds.origin.y = value * (_CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds)); + } + + [_contentView scrollToPoint:contentBounds.origin]; +} + +- (void)_horizontalScrollerDidScroll:(CPScroller)aScroller +{ + var value = [aScroller floatValue], + documentFrame = [[self documentView] frame], + contentBounds = [_contentView bounds]; + + switch ([_horizontalScroller hitPart]) + { + case CPScrollerDecrementLine: contentBounds.origin.x -= _horizontalLineScroll; + break; + + case CPScrollerIncrementLine: contentBounds.origin.x += _horizontalLineScroll; + break; + + case CPScrollerDecrementPage: contentBounds.origin.x -= _CGRectGetWidth(contentBounds) - _horizontalPageScroll; + break; + + case CPScrollerIncrementPage: contentBounds.origin.x += _CGRectGetWidth(contentBounds) - _horizontalPageScroll; + break; + + case CPScrollerKnobSlot: + case CPScrollerKnob: + default: contentBounds.origin.x = value * (_CGRectGetWidth(documentFrame) - _CGRectGetWidth(contentBounds)); + } + + [_contentView scrollToPoint:contentBounds.origin]; +} + +- (void)tile +{ + // yuck. + // RESIZE: tile->setHidden AND refl + // Outside Change: refl->tile->setHidden AND refl + // scroll: refl. +} + +-(void)resizeSubviewsWithOldSize:(CPSize)aSize +{ + [self reflectScrolledClipView:_contentView]; +} + +// Setting Scrolling Behavior + +- (void)setLineScroll:(float)aLineScroll +{ + [self setHorizonalLineScroll:aLineScroll]; + [self setVerticalLineScroll:aLineScroll]; +} + +- (float)lineScroll +{ + return [self horizontalLineScroll]; +} + +- (void)setHorizontalLineScroll:(float)aLineScroll +{ + _horizontalLineScroll = aLineScroll; +} + +- (float)horizontalLineScroll +{ + return _horizontalLineScroll; +} + +- (void)setVerticalLineScroll:(float)aLineScroll +{ + _verticalLineScroll = aLineScroll; +} + +- (float)verticalLineScroll +{ + return _verticalLineScroll; +} + +- (void)setPageScroll:(float)aPageScroll +{ + [self setHorizontalPageScroll:aPageScroll]; + [self setVerticalPageScroll:aPageScroll]; +} + +- (float)pageScroll +{ + return [self horizontalPageScroll]; +} + +- (void)setHorizontalPageScroll:(float)aPageScroll +{ + _horizontalPageScroll = aPageScroll; +} + +- (float)horizontalPageScroll +{ + return _horizontalPageScroll; +} + +- (void)setVerticalPageScroll:(float)aPageScroll +{ + _verticalPageScroll = aPageScroll; +} + +- (float)verticalPageScroll +{ + return _verticalPageScroll; +} + +- (void)scrollWheel:(CPEvent)anEvent +{ + var value = [_verticalScroller floatValue], + documentFrame = [[self documentView] frame], + contentBounds = [_contentView bounds]; + + contentBounds.origin.x += [anEvent deltaX] * _horizontalLineScroll; + contentBounds.origin.y += [anEvent deltaY] * _verticalLineScroll; + + [_contentView scrollToPoint:contentBounds.origin]; +} + +@end diff --git a/AppKit/CPScroller.j b/AppKit/CPScroller.j new file mode 100644 index 000000000..795e56793 --- /dev/null +++ b/AppKit/CPScroller.j @@ -0,0 +1,621 @@ +/* + * CPScroller.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPControl.j" + +#include "CoreGraphics/CGGeometry.h" + + +// CPScroller Constants +CPScrollerNoPart = 0; +CPScrollerDecrementPage = 1; +CPScrollerKnob = 2; +CPScrollerIncrementPage = 3; +CPScrollerDecrementLine = 4; +CPScrollerIncrementLine = 5; +CPScrollerKnobSlot = 6; + +CPScrollerIncrementArrow = 0; +CPScrollerDecrementArrow = 1; + +CPNoScrollerParts = 0; +CPOnlyScrollerArrows = 1; +CPAllScrollerParts = 2; + +var _CPScrollerWidths = [], + _CPScrollerKnobMinimumHeights = [], + _CPScrollerArrowHeights = [], + _CPScrollerArrowUsableHeights = []; + +_CPScrollerWidths[CPRegularControlSize] = 14.0; +_CPScrollerWidths[CPSmallControlSize] = 11.0; +_CPScrollerWidths[CPMiniControlSize] = 11.0; // FIXME + +_CPScrollerKnobMinimumHeights[CPRegularControlSize] = 18.0; +_CPScrollerKnobMinimumHeights[CPSmallControlSize] = 12.0; +_CPScrollerKnobMinimumHeights[CPMiniControlSize] = 12.0; // FIXME + +_CPScrollerArrowHeights[CPRegularControlSize] = 21.0; +_CPScrollerArrowHeights[CPSmallControlSize] = 16.0; +_CPScrollerArrowHeights[CPMiniControlSize] = 16.0; // FIXME + +_CPScrollerArrowUsableHeights[CPRegularControlSize] = 16.0 +_CPScrollerArrowUsableHeights[CPSmallControlSize] = 10.0; +_CPScrollerArrowUsableHeights[CPMiniControlSize] = 10.0; // FIXME + +var _CPScrollerKnobIdentifier = @"Knob", + _CPScrollerKnobSlotIdentifier = @"KnobSlot", + _CPScrollerDecrementArrowIdentifier = @"DecrementArrow", + _CPScrollerIncrementArrowIdentifier = @"IncrementArrow", + _CPScrollerHorizontalIdentifier = @"Horizontal", + _CPScrollerVerticalIdentifier = @"Vertical", + _CPScrollerHighlightedIdentifier = @"Highlighted", + _CPScrollerDisabledIdentifier = @"Disabled"; + +var _CPScrollerClassName = nil, + _CPScrollerPartSizes = {}; + +@implementation CPScroller : CPControl +{ + CPControlSize _controlSize; + CPUsableScrollerParts _usableParts; + CPArray _partRects; + + BOOL _isHorizontal; + float _knobProportion; + + CPScrollerPart _hitPart; + + CPScrollerPart _trackingPart; + float _trackingFloatValue; + CGPoint _trackingStartPoint; + + CPView _knobView; + CPView _knobSlotView; + + CPView _decrementArrowView; + CPView _incrementArrowView; +} + ++ (void)initialize +{ + if (self != [CPScroller class]) + return; + + _CPScrollerClassName = [self className]; + + var regularIdentifier = _CPControlIdentifierForControlSize(CPRegularControlSize), + smallIdentifier = _CPControlIdentifierForControlSize(CPSmallControlSize), + miniIdentifier = _CPControlIdentifierForControlSize(CPMiniControlSize); + + // Horizontal Knob Sizes + var prefix = _CPScrollerClassName + _CPScrollerKnobIdentifier + _CPScrollerHorizontalIdentifier; + + _CPScrollerPartSizes[prefix + regularIdentifier] = [_CGSizeMake(9.0, _CPScrollerWidths[CPRegularControlSize]), _CGSizeMake(1.0, _CPScrollerWidths[CPRegularControlSize]), _CGSizeMake(9.0, _CPScrollerWidths[CPRegularControlSize])]; + _CPScrollerPartSizes[prefix + smallIdentifier] = [_CGSizeMake(6.0, _CPScrollerWidths[CPSmallControlSize]), _CGSizeMake(1.0, _CPScrollerWidths[CPSmallControlSize]), _CGSizeMake(6.0, _CPScrollerWidths[CPSmallControlSize])]; + _CPScrollerPartSizes[prefix + miniIdentifier] = [_CGSizeMake(6.0, _CPScrollerWidths[CPMiniControlSize]), _CGSizeMake(1.0, _CPScrollerWidths[CPMiniControlSize]), _CGSizeMake(6.0, _CPScrollerWidths[CPMiniControlSize])]; + + // Vertical Knob Sizes + var prefix = _CPScrollerClassName + _CPScrollerKnobIdentifier + _CPScrollerVerticalIdentifier; + + _CPScrollerPartSizes[prefix + regularIdentifier] = [_CGSizeMake(_CPScrollerWidths[CPRegularControlSize], 9.0), _CGSizeMake(_CPScrollerWidths[CPRegularControlSize], 1.0), _CGSizeMake(_CPScrollerWidths[CPRegularControlSize], 9.0)]; + _CPScrollerPartSizes[prefix + smallIdentifier] = [_CGSizeMake(_CPScrollerWidths[CPSmallControlSize], 6.0), _CGSizeMake(_CPScrollerWidths[CPSmallControlSize], 1.0), _CGSizeMake(_CPScrollerWidths[CPSmallControlSize], 6.0)]; + _CPScrollerPartSizes[prefix + miniIdentifier] = [_CGSizeMake(_CPScrollerWidths[CPMiniControlSize], 6.0), _CGSizeMake(_CPScrollerWidths[CPMiniControlSize], 1.0), _CGSizeMake(_CPScrollerWidths[CPMiniControlSize], 6.0)]; + + // Horizontal Knob Slot Sizes + var prefix = _CPScrollerClassName + _CPScrollerKnobSlotIdentifier + _CPScrollerHorizontalIdentifier; + + _CPScrollerPartSizes[prefix + regularIdentifier] = _CGSizeMake(1.0, _CPScrollerWidths[CPRegularControlSize]); + _CPScrollerPartSizes[prefix + smallIdentifier] = _CGSizeMake(1.0, _CPScrollerWidths[CPSmallControlSize]); + _CPScrollerPartSizes[prefix + miniIdentifier] = _CGSizeMake(1.0, _CPScrollerWidths[CPMiniControlSize]); + + // Vertical Knob Slot Sizes + var prefix = _CPScrollerClassName + _CPScrollerKnobSlotIdentifier + _CPScrollerVerticalIdentifier; + + _CPScrollerPartSizes[prefix + regularIdentifier] = _CGSizeMake(_CPScrollerWidths[CPRegularControlSize], 1.0); + _CPScrollerPartSizes[prefix + smallIdentifier] = _CGSizeMake(_CPScrollerWidths[CPSmallControlSize], 1.0); + _CPScrollerPartSizes[prefix + miniIdentifier] = _CGSizeMake(_CPScrollerWidths[CPMiniControlSize], 1.0); + + // Horizontal Decrement Arrows Sizes + var prefix = _CPScrollerClassName + _CPScrollerDecrementArrowIdentifier + _CPScrollerHorizontalIdentifier; + + _CPScrollerPartSizes[prefix + regularIdentifier] = _CGSizeMake(_CPScrollerArrowHeights[CPRegularControlSize], _CPScrollerWidths[CPRegularControlSize]); + _CPScrollerPartSizes[prefix + regularIdentifier + _CPScrollerHighlightedIdentifier] = _CGSizeMake(_CPScrollerArrowHeights[CPRegularControlSize], _CPScrollerWidths[CPRegularControlSize]); + _CPScrollerPartSizes[prefix + smallIdentifier] = _CGSizeMake(_CPScrollerArrowHeights[CPSmallControlSize] , _CPScrollerWidths[CPSmallControlSize]); + _CPScrollerPartSizes[prefix + smallIdentifier + _CPScrollerHighlightedIdentifier] = _CGSizeMake(_CPScrollerArrowHeights[CPSmallControlSize] , _CPScrollerWidths[CPSmallControlSize]); + _CPScrollerPartSizes[prefix + miniIdentifier] = _CGSizeMake(_CPScrollerArrowHeights[CPMiniControlSize], _CPScrollerWidths[CPMiniControlSize]); + _CPScrollerPartSizes[prefix + miniIdentifier + _CPScrollerHighlightedIdentifier] = _CGSizeMake(_CPScrollerArrowHeights[CPMiniControlSize], _CPScrollerWidths[CPMiniControlSize]); + + // Vertical Decrement Arrows Sizes + var prefix = _CPScrollerClassName + _CPScrollerDecrementArrowIdentifier + _CPScrollerVerticalIdentifier; + + _CPScrollerPartSizes[prefix + regularIdentifier] = _CGSizeMake(_CPScrollerWidths[CPRegularControlSize], _CPScrollerArrowHeights[CPRegularControlSize]); + _CPScrollerPartSizes[prefix + regularIdentifier + _CPScrollerHighlightedIdentifier] = _CGSizeMake(_CPScrollerWidths[CPRegularControlSize], _CPScrollerArrowHeights[CPRegularControlSize]); + _CPScrollerPartSizes[prefix + smallIdentifier] = _CGSizeMake(_CPScrollerWidths[CPSmallControlSize], _CPScrollerArrowHeights[CPSmallControlSize]); + _CPScrollerPartSizes[prefix + smallIdentifier + _CPScrollerHighlightedIdentifier] = _CGSizeMake(_CPScrollerWidths[CPSmallControlSize], _CPScrollerArrowHeights[CPSmallControlSize]); + _CPScrollerPartSizes[prefix + miniIdentifier] = _CGSizeMake(_CPScrollerWidths[CPMiniControlSize], _CPScrollerArrowHeights[CPMiniControlSize]); + _CPScrollerPartSizes[prefix + miniIdentifier + _CPScrollerHighlightedIdentifier] = _CGSizeMake(_CPScrollerWidths[CPMiniControlSize], _CPScrollerArrowHeights[CPMiniControlSize]); + + // Horizontal Increment Arrows Sizes + var prefix = _CPScrollerClassName + _CPScrollerIncrementArrowIdentifier + _CPScrollerHorizontalIdentifier; + + _CPScrollerPartSizes[prefix + regularIdentifier] = _CGSizeMake(_CPScrollerArrowHeights[CPRegularControlSize], _CPScrollerWidths[CPRegularControlSize]); + _CPScrollerPartSizes[prefix + regularIdentifier + _CPScrollerHighlightedIdentifier] = _CGSizeMake(_CPScrollerArrowHeights[CPRegularControlSize], _CPScrollerWidths[CPRegularControlSize]); + _CPScrollerPartSizes[prefix + smallIdentifier] = _CGSizeMake(_CPScrollerArrowHeights[CPSmallControlSize], _CPScrollerWidths[CPSmallControlSize]); + _CPScrollerPartSizes[prefix + smallIdentifier + _CPScrollerHighlightedIdentifier] = _CGSizeMake(_CPScrollerArrowHeights[CPSmallControlSize], _CPScrollerWidths[CPSmallControlSize]); + _CPScrollerPartSizes[prefix + miniIdentifier] = _CGSizeMake(_CPScrollerArrowHeights[CPMiniControlSize], _CPScrollerWidths[CPMiniControlSize]); + _CPScrollerPartSizes[prefix + miniIdentifier + _CPScrollerHighlightedIdentifier] = _CGSizeMake(_CPScrollerArrowHeights[CPMiniControlSize], _CPScrollerWidths[CPMiniControlSize]); + + // Vertical Increment Arrows Sizes + var prefix = _CPScrollerClassName + _CPScrollerIncrementArrowIdentifier + _CPScrollerVerticalIdentifier; + + _CPScrollerPartSizes[prefix + regularIdentifier] = _CGSizeMake(_CPScrollerWidths[CPRegularControlSize], _CPScrollerArrowHeights[CPRegularControlSize]); + _CPScrollerPartSizes[prefix + regularIdentifier + _CPScrollerHighlightedIdentifier] = _CGSizeMake(_CPScrollerWidths[CPRegularControlSize], _CPScrollerArrowHeights[CPRegularControlSize]); + _CPScrollerPartSizes[prefix + smallIdentifier] = _CGSizeMake(_CPScrollerWidths[CPSmallControlSize], _CPScrollerArrowHeights[CPSmallControlSize]); + _CPScrollerPartSizes[prefix + smallIdentifier + _CPScrollerHighlightedIdentifier] = _CGSizeMake(_CPScrollerWidths[CPSmallControlSize], _CPScrollerArrowHeights[CPSmallControlSize]); + _CPScrollerPartSizes[prefix + miniIdentifier] = _CGSizeMake(_CPScrollerWidths[CPMiniControlSize], _CPScrollerArrowHeights[CPMiniControlSize]); + _CPScrollerPartSizes[prefix + miniIdentifier + _CPScrollerHighlightedIdentifier] = _CGSizeMake(_CPScrollerWidths[CPMiniControlSize], _CPScrollerArrowHeights[CPMiniControlSize]); +} + +// Calculating Layout + +- (id)initWithFrame:(CPRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _controlSize = CPRegularControlSize; + _partRects = []; + + [self setFloatValue:0.0 knobProportion:1.0]; + + _isHorizontal = CPRectGetWidth(aFrame) > CPRectGetHeight(aFrame); + + _hitPart = CPScrollerNoPart; + + [self checkSpaceForUsableParts]; + [self drawParts]; + + [self layoutSubviews]; + } + + return self; +} + +// Determining CPScroller Size + ++ (float)scrollerWidth +{ + return [self scrollerWidthForControlSize:CPRegularControlSize]; +} + ++ (float)scrollerWidthForControlSize:(CPControlSize)aControlSize +{ + return _CPScrollerWidths[aControlSize]; +} + +- (void)setControlSize:(CPControlSize)aControlSize +{ + if (_controlSize == aControlSize) + return; + + _controlSize = aControlSize; + + [self drawKnobSlot]; + [self drawKnob]; + [self drawArrow:CPScrollerDecrementArrow highlight:NO]; + [self drawArrow:CPScrollerIncrementArrow highlight:NO]; + + [self layoutSubviews]; +} + +- (CPControlSize)controlSize +{ + return _controlSize; +} + +// Setting the Knob Position + +- (void)setFloatValue:(float)aValue +{ + [super setFloatValue:MIN(1.0, MAX(0.0, aValue))]; + + [self checkSpaceForUsableParts]; + [self layoutSubviews]; +} + +- (void)setFloatValue:(float)aValue knobProportion:(float)aProportion +{ + _knobProportion = MIN(1.0, MAX(0.0001, aProportion)); + + [self setFloatValue:aValue]; +} + +- (float)knobProportion +{ + return _knobProportion; +} + +// Calculating Layout + +- (CGRect)rectForPart:(CPScrollerPart)aPart +{ + if (aPart == CPScrollerNoPart) + return _CGRectMakeZero(); + + return _partRects[aPart]; +} + +- (CPScrollerPart)testPart:(CGPoint)aPoint +{ + aPoint = [self convertPoint:aPoint fromView:nil]; + + // The ordering of these tests is important. We check the knob and + // page rects first since they may overlap with the arrows. + + if (CGRectContainsPoint([self rectForPart:CPScrollerKnob], aPoint)) + return CPScrollerKnob; + + if (CGRectContainsPoint([self rectForPart:CPScrollerDecrementPage], aPoint)) + return CPScrollerDecrementPage; + + if (CGRectContainsPoint([self rectForPart:CPScrollerIncrementPage], aPoint)) + return CPScrollerIncrementPage; + + if (CGRectContainsPoint([self rectForPart:CPScrollerDecrementLine], aPoint)) + return CPScrollerDecrementLine; + + if (CGRectContainsPoint([self rectForPart:CPScrollerIncrementLine], aPoint)) + return CPScrollerIncrementLine; + + if (CGRectContainsPoint([self rectForPart:CPScrollerKnobSlot], aPoint)) + return CPScrollerKnobSlot; + + return CPScrollerNoPart; +} + +- (void)checkSpaceForUsableParts +{ + var bounds = [self bounds]; + + // Assume we won't be needing the arrows. + if (_knobProportion == 1.0) + { + _usableParts = CPNoScrollerParts; + + _partRects[CPScrollerDecrementPage] = _CGRectMakeZero(); + _partRects[CPScrollerKnob] = _CGRectMakeZero(); + _partRects[CPScrollerIncrementPage] = _CGRectMakeZero(); + _partRects[CPScrollerDecrementLine] = _CGRectMakeZero(); + _partRects[CPScrollerIncrementLine] = _CGRectMakeZero(); + + // In this case, the slot is the entirety of the scroller. + _partRects[CPScrollerKnobSlot] = _CGRectMakeCopy(bounds); + + return; + } + + var width = _CGRectGetWidth(bounds), + height = _CGRectGetHeight(bounds), + usableArrowHeight = _CPScrollerArrowUsableHeights[_controlSize], + slotWidth = (_isHorizontal ? width : height) - 2.0 * usableArrowHeight, + knobWidth = MAX(_CPScrollerKnobMinimumHeights[_controlSize], (slotWidth * _knobProportion)); + + _usableParts = CPAllScrollerParts; + + var arrowHeight = _CPScrollerArrowHeights[_controlSize], + knobLocation = usableArrowHeight + (slotWidth - knobWidth) * [self floatValue]; + + // At this point we know we're going to need arrows. + if (_isHorizontal) + { + // ASSERT(_CPScrollerWidths[_controlSize] == height) + + _partRects[CPScrollerDecrementPage] = _CGRectMake(usableArrowHeight, 0.0, knobLocation - usableArrowHeight, height); + _partRects[CPScrollerKnob] = _CGRectMake(knobLocation, 0.0, knobWidth, _CPScrollerWidths[_controlSize]); + _partRects[CPScrollerIncrementPage] = _CGRectMake(knobLocation + knobWidth, 0.0, width - (knobLocation + knobWidth) - usableArrowHeight, height); + _partRects[CPScrollerKnobSlot] = _CGRectMake(usableArrowHeight, 0.0, slotWidth, height); + _partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, arrowHeight, height); + _partRects[CPScrollerIncrementLine] = _CGRectMake(width - _CPScrollerArrowHeights[_controlSize], 0.0, arrowHeight, height); + } + else + { + // ASSERT(_CPScrollerWidths[_controlSize] == width) + + _partRects[CPScrollerDecrementPage] = _CGRectMake(0.0, usableArrowHeight, width, knobLocation - usableArrowHeight); + _partRects[CPScrollerKnob] = _CGRectMake(0.0, knobLocation, _CPScrollerWidths[_controlSize], knobWidth); + _partRects[CPScrollerIncrementPage] = _CGRectMake(0.0, knobLocation + knobWidth, width, height - (knobLocation + knobWidth) - usableArrowHeight); + _partRects[CPScrollerKnobSlot] = _CGRectMake(0.0, usableArrowHeight, width, slotWidth); + _partRects[CPScrollerDecrementLine] = _CGRectMake(0.0, 0.0, width, arrowHeight); + _partRects[CPScrollerIncrementLine] = _CGRectMake(0.0, height - _CPScrollerArrowHeights[_controlSize], width, arrowHeight); + } +} + +- (CPUsableScrollerParts)usableParts +{ + return _usableParts; +} + +// Drawing the Parts + +- (void)drawArrow:(CPScrollerArrow)anArrow highlight:(BOOL)shouldHighlight +{ + var identifier = (anArrow == CPScrollerDecrementArrow ? _CPScrollerDecrementArrowIdentifier : _CPScrollerIncrementArrowIdentifier), + arrowView = (anArrow == CPScrollerDecrementArrow ? _decrementArrowView : _incrementArrowView); + + [arrowView setBackgroundColor:_CPControlColorWithPatternImage( + _CPScrollerPartSizes, + _CPScrollerClassName, + identifier, + _isHorizontal ? _CPScrollerHorizontalIdentifier : _CPScrollerVerticalIdentifier, + _CPControlIdentifierForControlSize(_controlSize), + shouldHighlight ? _CPScrollerHighlightedIdentifier : @"")]; +} + +- (void)drawKnob +{ + [_knobView setBackgroundColor:_CPControlThreePartImagePattern( + !_isHorizontal, + _CPScrollerPartSizes, + _CPScrollerClassName, + _CPScrollerKnobIdentifier, + _isHorizontal ? _CPScrollerHorizontalIdentifier : _CPScrollerVerticalIdentifier, + _CPControlIdentifierForControlSize(_controlSize))]; +} + +- (void)drawKnobSlot +{ + [_knobSlotView setBackgroundColor:_CPControlColorWithPatternImage( + _CPScrollerPartSizes, + _CPScrollerClassName, + _CPScrollerKnobSlotIdentifier, + _isHorizontal ? _CPScrollerHorizontalIdentifier : _CPScrollerVerticalIdentifier, + _CPControlIdentifierForControlSize(_controlSize))]; +} + +- (void)drawParts +{ + _knobSlotView = [[CPView alloc] initWithFrame:_CGRectMakeZero()]; + + [_knobSlotView setHitTests:NO]; + + [self addSubview:_knobSlotView]; + + [self drawKnobSlot]; + + _knobView = [[CPView alloc] initWithFrame:_CGRectMakeZero()]; + + [_knobView setHitTests:NO]; + + [self addSubview:_knobView]; + + [self drawKnob]; + + _decrementArrowView = [[CPView alloc] initWithFrame:_CGRectMakeZero()]; + + [_decrementArrowView setHitTests:NO]; + + [self addSubview:_decrementArrowView]; + + [self drawArrow:CPScrollerDecrementArrow highlight:NO]; + + _incrementArrowView = [[CPView alloc] initWithFrame:_CGRectMakeZero()]; + + [_incrementArrowView setHitTests:NO]; + + [self addSubview:_incrementArrowView]; + + [self drawArrow:CPScrollerIncrementArrow highlight:NO]; +} + +- (void)highlight:(BOOL)shouldHighlight +{ + if (_trackingPart == CPScrollerDecrementLine) + [self drawArrow:CPScrollerDecrementArrow highlight:shouldHighlight]; + + else if (_trackingPart == CPScrollerIncrementLine) + [self drawArrow:CPScrollerIncrementArrow highlight:shouldHighlight]; +} + +// Event Handling + +- (CPScrollerPart)hitPart +{ + return _hitPart; +} + +- (void)trackKnob:(CPEvent)anEvent +{ + var type = [anEvent type]; + + if (type == CPLeftMouseUp) + { + _hitPart = CPScrollerNoPart; + + return; + } + + if (type == CPLeftMouseDown) + { + _trackingFloatValue = [self floatValue]; + _trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil]; + } + + else if (type == CPLeftMouseDragged) + { + var knobRect = [self rectForPart:CPScrollerKnob], + knobSlotRect = [self rectForPart:CPScrollerKnobSlot], + remainder = _isHorizontal ? (_CGRectGetWidth(knobSlotRect) - _CGRectGetWidth(knobRect)) : (_CGRectGetHeight(knobSlotRect) - _CGRectGetHeight(knobRect)); + + if (remainder <= 0) + [self setFloatValue:0.0]; + else + { + var location = [self convertPoint:[anEvent locationInWindow] fromView:nil]; + delta = _isHorizontal ? location.x - _trackingStartPoint.x : location.y - _trackingStartPoint.y; + + [self setFloatValue:_trackingFloatValue + delta / remainder]; + } + } + + [CPApp setTarget:self selector:@selector(trackKnob:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES]; + + [self sendAction:[self action] to:[self target]]; +} + +- (void)trackScrollButtons:(CPEvent)anEvent +{ + var type = [anEvent type]; + + if (type == CPLeftMouseUp) + { + [self highlight:NO]; + [CPEvent stopPeriodicEvents]; + + _hitPart = CPScrollerNoPart; + + return; + } + + if (type == CPLeftMouseDown) + { + _trackingPart = [self hitPart]; + + _trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil]; + + if ([anEvent modifierFlags] & CPAlternateKeyMask) + { + if (_trackingPart == CPScrollerDecrementLine) + _hitPart = CPScrollerDecrementPage; + else if (_trackingPart == CPScrollerIncrementLine) + _hitPart = CPScrollerIncrementPage; + else if (_trackingPart == CPScrollerDecrementPage || _trackingPart == CPScrollerIncrementPage) + { + var knobRect = [self rectForPart:CPScrollerKnob], + knobWidth = _isHorizontal ? _CGRectGetWidth(knobRect) : _CGRectGetHeight(knobRect), + knobSlotRect = [self rectForPart:CPScrollerKnobSlot], + remainder = (_isHorizontal ? _CGRectGetWidth(knobSlotRect) : _CGRectGetHeight(knobSlotRect)) - knobWidth; + + [self setFloatValue:((_isHorizontal ? _trackingStartPoint.x - _CGRectGetMinX(knobSlotRect) : _trackingStartPoint.y - _CGRectGetMinY(knobSlotRect)) - knobWidth / 2.0) / remainder]; + + _hitPart = CPScrollerKnob; + + [self sendAction:[self action] to:[self target]]; + + // Now just track the knob. + return [self trackKnob:anEvent]; + } + } + + [self highlight:YES]; + [self sendAction:[self action] to:[self target]]; + + [CPEvent startPeriodicEventsAfterDelay:0.5 withPeriod:0.04]; + } + + else if (type == CPLeftMouseDragged) + { + _trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil]; + + if (_trackingPart == CPScrollerDecrementPage || _trackingPart == CPScrollerIncrementPage) + { + var hitPart = [self testPart:[anEvent locationInWindow]]; + + if (hitPart == CPScrollerDecrementPage || hitPart == CPScrollerIncrementPage) + { + _trackingPart = hitPart; + _hitPart = hitPart; + } + } + + [self highlight:CGRectContainsPoint([self rectForPart:_trackingPart], _trackingStartPoint)]; + } + else if (type == CPPeriodic && CGRectContainsPoint([self rectForPart:_trackingPart], _trackingStartPoint)) + [self sendAction:[self action] to:[self target]]; + + [CPApp setTarget:self selector:@selector(trackScrollButtons:) forNextEventMatchingMask:CPPeriodicMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES]; + +} + +- (void)setFrameSize:(CGSize)aSize +{ + [super setFrameSize:aSize]; + + [self checkSpaceForUsableParts]; + + var frame = [self frame], + isHorizontal = CPRectGetWidth(frame) > CPRectGetHeight(frame); + + if (_isHorizontal != isHorizontal) + { + _isHorizontal = isHorizontal; + + [self drawParts]; + } + + [self layoutSubviews]; +} + +- (void)layoutSubviews +{ + [_knobSlotView setFrame:[self rectForPart:CPScrollerKnobSlot]]; + + var usableParts = [self usableParts], + hidden = !(usableParts == CPAllScrollerParts); + + if (hidden != [_knobView isHidden]) + { + [_knobView setHidden:hidden]; + [_decrementArrowView setHidden:hidden]; + [_incrementArrowView setHidden:hidden]; + } + + if (!hidden) + { + [_knobView setFrame:[self rectForPart:CPScrollerKnob]]; + [_decrementArrowView setFrame:[self rectForPart:CPScrollerDecrementLine]]; + [_incrementArrowView setFrame:[self rectForPart:CPScrollerIncrementLine]]; + } +} + +- (void)mouseDown:(CPEvent)anEvent +{ + _hitPart = [self testPart:[anEvent locationInWindow]]; + + switch (_hitPart) + { + case CPScrollerKnob: return [self trackKnob:anEvent]; + + case CPScrollerDecrementLine: + case CPScrollerIncrementLine: + case CPScrollerDecrementPage: + case CPScrollerIncrementPage: return [self trackScrollButtons:anEvent]; + } +} + +// FIXME: This is a result of the "dumb" code that just makes things transparent when disabled. +- (void)setEnabled:(BOOL)shouldBeEnabled +{ +} + +@end diff --git a/AppKit/CPSegmentedControl.j b/AppKit/CPSegmentedControl.j new file mode 100644 index 000000000..925f69c10 --- /dev/null +++ b/AppKit/CPSegmentedControl.j @@ -0,0 +1,542 @@ +/* + * CPSegmentedControl.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + +import "CPControl.j" + + +CPSegmentSwitchTrackingSelectOne = 0; +CPSegmentSwitchTrackingSelectAny = 1; +CPSegmentSwitchTrackingMomentary = 2; + +@implementation CPSegmentedControl : CPControl +{ + unsigned _segmentCount; + + CPArray _segments; + CPArray _selectedSegment; + + CPSegmentSwitchTracking _trackingMode; + unsigned _trackingSegment; + BOOL _trackingHighlighted; +} + +- (id)initWithFrame:(CGRect)aRect +{ + self = [super initWithFrame:aRect]; + + if (self) + { + _segments = []; + _selectedSegment = -1; + + _segmentCount = 0; + + _trackingMode = CPSegmentSwitchTrackingSelectOne; + } + + return self; +} + +- (int)selectedTag +{ + return _segments[_selectedSegment].tag; +} + +// Specifying the number of segments + +- (void)setSegmentCount:(unsigned)aCount +{ + if (_segmentCount == aCount) + return; + + var height = CGRectGetHeight([self bounds]); + + if (_segmentCount < aCount) + { + var index = _segmentCount; + + for (; index < aCount; ++index) + { + _segments[index] = _CPSegmentMake(); + _segments[index].frame.size.height = height; + } + } + else if (aCount < _segmentCount) + { + var index = aCount; + + for (; index < _segmentCount; ++index) + { + [_segments[index].imageView removeFromSuperview]; + [_segments[index].labelView removeFromSuperview]; + + _segments[index] = nil; + } + } + + _segmentCount = aCount; + + if (_selectedSegment < _segmentCount) + _selectedSegment = -1; + + [self tileWithChangedSegment:0]; +} + +- (unsigned)segmentCount +{ + return _segmentCount; +} + +// Specifying Selected Segment + +- (void)setSelectedSegment:(unsigned)aSegment +{ + [self setSelected:YES forSegment:aSegment]; +} + +- (unsigned)selectedSegment +{ + return _selectedSegment; +} + +- (BOOL)selectSegmentWithTag:(int)aTag +{ + var index = 0; + + for (; index < _segmentCount; ++index) + if (_segments[index].tag == aTag) + { + [self setSelectedSegment:index]; + + return YES; + } + + return NO; +} + +// Specifying Tracking Mode + +- (BOOL)isTracking +{ + +} + +- (void)setTrackingMode:(CPSegmentSwitchTracking)aTrackingMode +{ + if (_trackingMode == aTrackingMode) + return; + + _trackingMode = aTrackingMode; + + if (_trackingMode == CPSegmentSwitchTrackingSelectOne) + { + var index = 0, + selected = NO; + + for (; index < _segmentCount; ++index) + if (_segments[index].selected) + if (selected) + [self setSelected:NO forSegment:index]; + else + selected = YES; + } + + else if (_trackingMode == CPSegmentSwitchTrackingMomentary) + { + var index = 0; + + for (; index < _segmentCount; ++index) + if (_segments[index].selected) + [self setSelected:NO forSegment:index]; + } +} + +- (CPSegmetnSwitchTracking)trackingMode +{ + return _trackingMode; +} + +// Working with Individual Segments + +- (void)setWidth:(float)aWidth forSegment:(unsigned)aSegment +{ + _segments[aSegment].width = aWidth; + + [self tileWithChangedSegment:aSegment]; +} + +- (float)widthForSegment:(unsigned)aSegment +{ + return _segments[aSegment].width; +} + +- (void)setImage:(CPImage)anImage forSegment:(unsigned)aSegment +{ + var segment = _segments[aSegment]; + + if (!anImage) + { + [segment.imageView removeFromSuperview]; + + segment.imageView = nil; + } + + else + { + if (!segment.imageView) + { + segment.imageView = [[CPImageView alloc] initWithFrame:CGRectMakeZero()]; + + [self addSubview:segment.imageView]; + } + + [segment.imageView setImage:anImage]; + [segment.imageView setFrameSize:CGSizeMakeCopy([anImage size])]; + } + + segment.image = anImage; + + if (segment.width) + [self drawSegment:aSegment highlight:NO]; + else + [self tileWithChangedSegment:aSegment]; +} + +- (CPImage)imageForSegment:(unsigned)aSegment +{ + return _segments[aSegment].image; +} + +- (void)setLabel:(CPString)aLabel forSegment:(unsigned)aSegment +{ + var segment = _segments[aSegment]; + + if (!aLabel || !aLabel.length) + { + [segment.labelView removeFromSuperview]; + + segment.labelView = nil; + } + + else + { + if (!segment.labelView) + { + segment.labelView = [[CPTextField alloc] initWithFrame:CGRectMakeZero()]; + + [segment.labelView setFont:[self font]]; + + [self addSubview:segment.labelView]; + } + + [segment.labelView setStringValue:aLabel]; + [segment.labelView sizeToFit]; + } + + _segments[aSegment].label = aLabel; + + if (segment.width) + [self drawSegment:aSegment highlight:NO]; + else + [self tileWithChangedSegment:aSegment]; +} + +- (CPImage)labelForSegment:(unsigned)aSegment +{ + return _segments[aSegment].label; +} + +- (void)setMenu:(CPMenu)aMenu forSegment:(unsigned)aSegment +{ + _segments[aSegment].menu = aMenu; +} + +- (CPImage)menuForSegment:(unsigned)aSegment +{ + return _segments[aSegment].menu; +} + +- (void)setSelected:(BOOL)isSelected forSegment:(unsigned)aSegment +{ + // FIXME: EXCEPTION REQUIRED + if (aSegment < 0 || aSegment >= _segments.length) + return; + + var segment = _segments[aSegment]; + + // If we're already in this state, bail. + if (segment.selected == isSelected) + return; + + segment.selected = isSelected; + + // We need to do some cleanup if we only allow one selection. + if (isSelected) + { + var oldSelectedSegment = _selectedSegment; + + _selectedSegment = aSegment; + + if (_trackingMode == CPSegmentSwitchTrackingSelectOne && oldSelectedSegment != aSegment && oldSelectedSegment != -1) + { + _segments[oldSelectedSegment].selected = NO; + + [self drawSegmentBezel:oldSelectedSegment highlight:NO]; + } + } + + if (_trackingMode != CPSegmentSwitchTrackingMomentary) + [self drawSegmentBezel:aSegment highlight:NO]; +} + +- (CPImage)isSelectedForSegment:(unsigned)aSegment +{ + return _segments[aSegment].selected; +} + +- (void)setEnabled:(BOOL)isEnabled forSegment:(unsigned)aSegment +{ + _segments[aSegment].enabled = isEnabled; +} + +- (CPImage)isEnabledForSegment:(unsigned)aSegment +{ + return _segments[aSegment].enabled; +} + +- (void)setTag:(int)aTag forSegment:(unsigned)aSegment +{ + _segments[aSegment].tag = aTag; +} + +- (int)tagForSegment:(unsigned)aSegment +{ + return _segments[aSegment].tag; +} + +// Drawings + +- (void)drawSegmentBezel:(int)aSegment highlgiht:(BOOL)shouldHighlight +{ +} + +- (void)drawSegment:(int)aSegment highlight:(BOOL)shouldHighlight +{ + var segment = _segments[aSegment], + + imageView = segment.imageView, + labelView = segment.labelView, + + frame = segment.frame, + + segmentX = CGRectGetMinX(frame), + segmentWidth = CGRectGetWidth(frame), + segmentHeight = CGRectGetHeight(frame) - 1.0; + + if (imageView && labelView) + { + var imageViewSize = [imageView frame].size, + labelViewSize = [labelView frame].size, + totalHeight = imageViewSize.height + labelViewSize.height, + labelWidth = MIN(labelViewSize.width, width), + y = (segmentHeight - totalHeight) / 2.0; + + [imageView setFrameOrigin:CGPointMake(segmentX + (segmentWidth - imageViewSize.width) / 2.0, y)]; + + if (labelWidth < labelViewSize.width) + [labelView setFrameSize:CGSizeMake(labelWidth, labelViewSize.height)]; + + [labelView setFrameOrigin:CGPointMake(segmentX + (segmentWidth - labelWidth) / 2.0, y + imageViewSize.height)]; + } + else if (imageView) + { + var imageViewSize = [imageView frame].size; + + [imageView setFrameOrigin:CGPointMake(segmentX + (segmentWidth - imageViewSize.width) / 2.0, (segmentHeight - imageViewSize.height) / 2.0)]; + } + else if (labelView) + { + var labelViewSize = [labelView frame].size, + labelWidth = MIN(labelViewSize.width, segmentWidth); + + if (labelWidth < labelViewSize.width) + [labelView setFrameSize:CGSizeMake(labelWidth, labelViewSize.height)]; + + [labelView setFrameOrigin:CGPointMake(segmentX + (segmentWidth - labelWidth) / 2.0, (segmentHeight - labelViewSize.height) / 2.0)]; + } +} + +- (void)tileWithChangedSegment:(unsigned)aSegment +{ + var segment = _segments[aSegment], + segmentWidth = segment.width; + + if (!segmentWidth) + { + if (segment.labelView && segment.imageView) + segmentWidth = MAX(CGRectGetWidth([segment.labelView frame]) , CGRectGetWidth([segment.imageView frame])); + else if (segment.labelView) + segmentWidth = CGRectGetWidth([segment.labelView frame]); + else if (segment.imageView) + segmentWidth = CGRectGetWidth([segment.imageView frame]); + } + + var delta = segmentWidth - CGRectGetWidth(segment.frame); + + if (!delta) + return; + + // Update Contorl Size + var frame = [self frame]; + + [self setFrameSize:CGSizeMake(CGRectGetWidth(frame) + delta, CGRectGetHeight(frame))]; + + // Update Segment Width + segment.frame.size.width = segmentWidth; + + // Update Following Segments Widths + var index = aSegment + 1; + + for (; index < _segmentCount; ++index) + { + _segments[index].frame.origin.x += delta; + + [self drawSegmentBezel:index highlight:NO]; + [self drawSegment:index highlight:NO]; + } + + [self drawSegmentBezel:aSegment highlight:NO]; + [self drawSegment:aSegment highlight:NO]; +} + +- (CGRect)frameForSegment:(unsigned)aSegment +{ + return _segments[aSegment].frame; +} + +- (unsigned)testSegment:(CGPoint)aPoint +{ + var location = [self convertPoint:aPoint fromView:nil], + count = _segments.length; + + while (count--) + if (CGRectContainsPoint(_segments[count].frame, aPoint)) + return count; + + return -1; +} + +- (void)mouseDown:(CPEvent)anEvent +{ + if (![self isEnabled]) + return; + + [self trackSegment:anEvent]; +} + +// FIXME: this should be fixed way up in cpbutton/cpcontrol. +- (void)mouseUp:(CPEvent)anEvent +{ +} + +- (void)trackSegment:(CPEvent)anEvent +{ + var type = [anEvent type], + location = [self convertPoint:[anEvent locationInWindow] fromView:nil]; + + if (type == CPLeftMouseUp) + { + if (CGRectContainsPoint(_segments[_trackingSegment].frame, location)) + { + if (_trackingMode == CPSegmentSwitchTrackingSelectAny) + { + [self setSelected:![self isSelectedForSegment:_trackingSegment] forSegment:_trackingSegment]; + + // With ANY, _selectedSegment means last pressed. + _selectedSegment = _trackingSegment; + } + else + [self setSelected:YES forSegment:_trackingSegment]; + + [self sendAction:[self action] to:[self target]]; + + if (_trackingMode == CPSegmentSwitchTrackingMomentary) + { + [self setSelected:NO forSegment:_trackingSegment]; + + _selectedSegment = -1; + } + } + + [self drawSegmentBezel:_trackingSegment highlight:NO]; + + _trackingSegment = -1; + + return; + } + + if (type == CPLeftMouseDown) + { + _trackingHighlighted = YES; + _trackingSegment = [self testSegment:location]; + + [self drawSegmentBezel:_trackingSegment highlight:YES]; + } + + else if (type == CPLeftMouseDragged) + { + var highlighted = CGRectContainsPoint(_segments[_trackingSegment].frame, location); + + if (highlighted != _trackingHighlighted) + { + _trackingHighlighted = highlighted; + + [self drawSegmentBezel:_trackingSegment highlight:_trackingHighlighted]; + } + } + + [CPApp setTarget:self selector:@selector(trackSegment:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES]; +} + +- (void)setFont:(CPFont)aFont +{ + [super setFont:aFont]; + + var count = _segmentCount; + + if (!count) + return; + + while (count--) + [_segments[count].labelView setFont:aFont]; + + [self tileWithChangedSegment:0]; +} + +@end + +var _CPSegmentMake = function() +{ + return { width:0, image:nil, label:@"", menu:nil, selected:NO, enabled:NO, tag:0, labelView:nil, imageView:nil, frame:CGRectMakeZero() } +} diff --git a/AppKit/CPShadow.j b/AppKit/CPShadow.j new file mode 100644 index 000000000..30b92fd52 --- /dev/null +++ b/AppKit/CPShadow.j @@ -0,0 +1,75 @@ +/* + * CPShadow.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + +@implementation CPShadow : CPObject +{ + CPSize _offset; + float _blurRadius; + CPColor _color; + + CPString _cssString; +} + ++ (id)shadowWithOffset:(CPSize)anOffset blurRadius:(float)aBlurRadius color:(CPColor)aColor +{ + return [[CPShadow alloc] _initWithOffset:anOffset blurRadius:aBlurRadius color:aColor]; +} + +- (id)_initWithOffset:(CPSize)anOffset blurRadius:(float)aBlurRadius color:(CPColor)aColor +{ + self = [super init]; + + if (self) + { + _offset = anOffset; + _blurRadius = aBlurRadius; + _color = aColor; + + _cssString = [_color cssString] + " " + Math.round(anOffset.width) + @"px " + Math.round(anOffset.height) + @"px " + Math.round(_blurRadius) + @"px"; + } + + return self; +} + +- (CPSize)shadowOffset +{ + return _offset; +} + +- (float)shadowBlurRadius +{ + return _blurRadius; +} + +- (CPColor)shadowColor +{ + return _color; +} + +- (CPString)cssString +{ + return _cssString; +} + +@end \ No newline at end of file diff --git a/AppKit/CPShadowView.j b/AppKit/CPShadowView.j new file mode 100644 index 000000000..0f306e237 --- /dev/null +++ b/AppKit/CPShadowView.j @@ -0,0 +1,175 @@ +/* + * CPShadowView.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + +import "CGGeometry.j" +import "CPImage.j" +import "CPImageView.j" +import "CPView.j" + +#include "CoreGraphics/CGGeometry.h" + +CPLightShadow = 0; +CPHeavyShadow = 1; + +var CPShadowViewLightBackgroundColor = nil, + CPShadowViewHeavyBackgroundColor = nil; + +var LIGHT_LEFT_INSET = 3.0, + LIGHT_RIGHT_INSET = 3.0, + LIGHT_TOP_INSET = 3.0, + LIGHT_BOTTOM_INSET = 5.0, + + HEAVY_LEFT_INSET = 7.0, + HEAVY_RIGHT_INSET = 7.0, + HEAVY_TOP_INSET = 5.0, + HEAVY_BOTTOM_INSET = 5.0; + +@implementation CPShadowView : CPView +{ + CPShadowWeight _weight; +} + ++ (void)initialize +{ + if (self != [CPShadowView class]) + return; + + var bundle = [CPBundle bundleForClass:[self class]]; + + CPShadowViewLightBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices: + [ + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightTopLeft.png"] size:CGSizeMake(9.0, 9.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightTop.png"] size:CGSizeMake(1.0, 9.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightTopRight.png"] size:CGSizeMake(9.0, 9.0)], + + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightLeft.png"] size:CGSizeMake(9.0, 1.0)], + nil, + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightRight.png"] size:CGSizeMake(9.0, 1.0)], + + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightBottomLeft.png"] size:CGSizeMake(9.0, 9.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightBottom.png"] size:CGSizeMake(1.0, 9.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewLightBottomRight.png"] size:CGSizeMake(9.0, 9.0)] + ]]]; + + CPShadowViewHeavyBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices: + [ + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyTopLeft.png"] size:CGSizeMake(17.0, 17.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyTop.png"] size:CGSizeMake(1.0, 17.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyTopRight.png"] size:CGSizeMake(17.0, 17.0)], + + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyLeft.png"] size:CGSizeMake(17.0, 1.0)], + nil, + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyRight.png"] size:CGSizeMake(17.0, 1.0)], + + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyBottomLeft.png"] size:CGSizeMake(17.0, 17.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyBottom.png"] size:CGSizeMake(1.0, 17.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPShadowView/CPShadowViewHeavyBottomRight.png"] size:CGSizeMake(17.0, 17.0)] + ]]]; +} + +- (id)initWithFrame:(CGRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _weight = CPLightShadow; + + [self setBackgroundColor:CPShadowViewLightBackgroundColor]; + + [self setHitTests:NO]; + } + + return self; +} + +- (void)setWeight:(CPShadowWeight)aWeight +{ + if (_weight == aWeight) + return; + + _weight = aWeight; + + if (_weight == CPLightShadow) + [self setBackgroundColor:CPShadowViewLightBackgroundColor]; + + else + [self setBackgroundColor:CPShadowViewHeavyBackgroundColor]; +} + +- (float)leftInset +{ + return _weight == CPLightShadow ? LIGHT_LEFT_INSET : HEAVY_LEFT_INSET; +} + +- (float)rightInset +{ + return _weight == CPLightShadow ? LIGHT_RIGHT_INSET : HEAVY_RIGHT_INSET; +} + +- (float)topInset +{ + return _weight == CPLightShadow ? LIGHT_TOP_INSET : HEAVY_TOP_INSET; +} + +- (float)bottomInset +{ + return _weight == CPLightShadow ? LIGHT_BOTTOM_INSET : HEAVY_BOTTOM_INSET; +} + +- (float)horizontalInset +{ + if (_weight == CPLightShadow) + return LIGHT_LEFT_INSET + LIGHT_RIGHT_INSET; + + return HEAVY_LEFT_INSET + HEAVY_RIGHT_INSET; +} + +- (float)verticalInset +{ + if (_weight == CPLightShadow) + return LIGHT_TOP_INSET + LIGHT_BOTTOM_INSET; + + return HEAVY_TOP_INSET + HEAVY_BOTTOM_INSET; +} + ++ (CGRect)frameForContentFrame:(CGRect)aFrame withWeight:(CPShadowWeight)aWeight +{ + if (aWeight == CPLightShadow) + return CGRectMake(_CGRectGetMinX(aFrame) - LIGHT_LEFT_INSET, _CGRectGetMinY(aFrame) - LIGHT_TOP_INSET, _CGRectGetWidth(aFrame) + LIGHT_LEFT_INSET + LIGHT_RIGHT_INSET, _CGRectGetHeight(aFrame) + LIGHT_TOP_INSET + LIGHT_BOTTOM_INSET); + else + return CGRectMake(_CGRectGetMinX(aFrame) - HEAVY_LEFT_INSET, _CGRectGetMinY(aFrame) - HEAVY_TOP_INSET, _CGRectGetWidth(aFrame) + HEAVY_LEFT_INSET + HEAVY_RIGHT_INSET, _CGRectGetHeight(aFrame) + HEAVY_TOP_INSET + HEAVY_BOTTOM_INSET); +} + +- (CGRect)frameForContentFrame:(CGRect)aFrame +{ + return [[self class] frameForContentFrame:aFrame withWeight:_weight]; +} + +- (void)setFrameForContentFrame:(CGRect)aFrame +{ + [self setFrame:[self frameForContentFrame:aFrame]]; +} + +@end diff --git a/AppKit/CPSlider.j b/AppKit/CPSlider.j new file mode 100644 index 000000000..9c0020a7f --- /dev/null +++ b/AppKit/CPSlider.j @@ -0,0 +1,378 @@ +/* + * CPSlider.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPControl.j" + +var CPSliderHorizontalKnobImage = nil + CPSliderHorizontalBarLeftImage = nil, + CPSliderHorizontalBarRightImage = nil, + CPSliderHorizontalBarCenterImage = nil; + +@implementation CPSlider : CPControl +{ + double _value; + double _minValue; + double _maxValue; + double _altIncrementValue; + + CPView _bar; + CPView _knob; + + BOOL _isVertical; + CPImageView _standardKnob; + CPView _standardVerticalBar; + CPView _standardHorizontalBar; +} + ++ (void)initialize +{ + if (self != [CPSlider class]) + return; + + var bundle = [CPBundle bundleForClass:self]; + + CPSliderKnobImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSlider/CPSliderKnobRegular.png"] size:CPSizeMake(11.0, 11.0)], + CPSliderKnobPushedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSlider/CPSliderKnobRegularPushed.png"] size:CPSizeMake(11.0, 11.0)], + CPSliderHorizontalBarLeftImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSlider/CPSliderTrackHorizontalLeft.png"] size:CPSizeMake(2.0, 4.0)], + CPSliderHorizontalBarRightImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSlider/CPSliderTrackHorizontalRight.png"] size:CPSizeMake(2.0, 4.0)], + CPSliderHorizontalBarCenterImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSlider/CPSliderTrackHorizontalCenter.png"] size:CPSizeMake(1.0, 4.0)]; +} + +- (id)initWithFrame:(CPRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _value = 50.0; + _minValue = 0.0; + _maxValue = 100.0; + + _bar = [self bar]; + _knob = [self knob]; + _knobSize = [[self knobImage] size]; + _isVertical = [self isVertical]; + + [_knob setFrameOrigin:[self knobPosition]]; + + [self addSubview:_bar]; + [self addSubview:_knob]; + } + + return self; +} + +- (void)setFrameSize:(CPSize)aSize +{ + if(aSize.height > 21.0) + aSize.height = 21.0; + + if (_isVertical != [self isVertical]) + { + _isVertical = [self isVertical]; + + var bar = [self bar], + knob = [self knob]; + + if (_bar != bar) + [self replaceSubview:_bar = bar withView:_bar]; + + if (_knob != knob) + { + [self replaceSubview:knob withView:_knob]; + + _knob = knob; + [_knob setFrameOrigin:[self knobPosition]]; + } + } + + [super setFrameSize:aSize]; + + [_knob setFrameOrigin:[self knobPosition]]; +} + +- (double)altIncrementValue +{ + return _altIncrementValue; +} + +- (float)knobThickness +{ + return CPRectGetWidth([_knob frame]); +} + +- (CPImage)leftTrackImage +{ + return CPSliderHorizontalBarLeftImage; +} + +- (CPImage)rightTrackImage +{ + return CPSliderHorizontalBarRightImage; +} + +- (CPImage)centerTrackImage +{ + return CPSliderHorizontalBarCenterImage +} + +- (CPImage)knobImage +{ + return CPSliderKnobImage; +} + +- (CPImage)pushedKnobImage +{ + return CPSliderKnobPushedImage; +} + +- (CPView)knob +{ + if (!_standardKnob) + { + var knobImage = [self knobImage], + knobSize = [knobImage size]; + + _standardKnob = [[CPImageView alloc] initWithFrame:CPRectMake(0.0, 0.0, knobSize.width, knobSize.height)]; + + [_standardKnob setImage:knobImage]; + } + + return _standardKnob; +} + +- (CPView)bar +{ + // FIXME: veritcal. + if ([self isVertical]) + return nil; + else + { + if (!_standardHorizontalBar) + { + var frame = [self frame], + barFrame = CPRectMake(0.0, 0.0, CPRectGetWidth(frame), 4.0); + + _standardHorizontalBar = [[CPView alloc] initWithFrame:barFrame]; + + [_standardHorizontalBar setBackgroundColor:[CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices: + [[self leftTrackImage], [self centerTrackImage], [self rightTrackImage]] isVertical:NO]]]; + + [_standardHorizontalBar setFrame:CPRectMake(0.0, (CPRectGetHeight(frame) - CPRectGetHeight(barFrame)) / 2.0, CPRectGetWidth(_isVertical ? barFrame : frame), CPRectGetHeight(_isVertical ? frame : barFrame))]; + [_standardHorizontalBar setAutoresizingMask:_isVertical ? CPViewHeightSizable : CPViewWidthSizable]; + } + + return _standardHorizontalBar; + } +} + +- (void)setAltIncrementValue:(double)anIncrementValue +{ + _altIncrementValue = anIncrementValue; +} + +- (int)isVertical +{ + var frame = [self frame]; + + if (CPRectGetWidth(frame) == CPRectGetHeight(frame)) + return -1; + + return CPRectGetWidth(frame) < CPRectGetHeight(frame); +} + +- (double)maxValue +{ + return _maxValue; +} + +- (double)minValue +{ + return _minValue; +} + +- (void)setMaxValue:(double)aMaxValue +{ + _maxValue = aMaxValue; +} + +- (void)setMinValue:(double)aMinValue +{ + _minValue = aMinValue; +} + +- (void)setValue:(double)aValue +{ + _value = aValue; + + [_knob setFrameOrigin:[self knobPosition]]; +} + +- (double)value +{ + return _value; +} + +- (CPPoint)knobPosition +{ + if ([self isVertical]) + return CPPointMake(0.0, 0.0); + else + return CPPointMake( + ((_value - _minValue) / (_maxValue - _minValue)) * (CPRectGetWidth([self frame]) - CPRectGetWidth([_knob frame])), + (CPRectGetHeight([self frame]) - CPRectGetHeight([_knob frame])) / 2.0); +} + +- (float)valueForKnobPosition:(CPPoint)aPoint +{ + if ([self isVertical]) + return 0.0; + else + return MAX(MIN((aPoint.x) * (_maxValue - _minValue) / ( CPRectGetWidth([self frame]) - CPRectGetWidth([_knob frame]) ) + _minValue, _maxValue), _minValue); +} + +- (CPPoint)constrainKnobPosition:(CPPoint)aPoint +{ + //FIXME + aPoint.x -= _knobSize.width / 2.0; + return CPPointMake(MAX(MIN(CPRectGetWidth([self bounds]) - _knobSize.width, aPoint.x), 0.0), (CPRectGetHeight([self bounds]) - CPRectGetHeight([_knob frame])) / 2.0); +} + +- (void)mouseUp:(CPEvent)anEvent +{ + [[self knob] setImage: [self knobImage]]; + + if ([_target respondsToSelector:@selector(sliderDidFinish:)]) + [_target sliderDidFinish:self]; +} + +- (void)mouseDown:(CPEvent)anEvent +{ + [_knob setFrameOrigin:[self constrainKnobPosition:[self convertPoint:[anEvent locationInWindow] fromView:nil]]]; + + _value = [self valueForKnobPosition:[_knob frame].origin]; + + [[self knob] setImage: [self pushedKnobImage]]; + [self sendAction:_action to:_target]; +} + +- (void)mouseDragged:(CPEvent)anEvent +{ + [_knob setFrameOrigin:[self constrainKnobPosition:[self convertPoint:[anEvent locationInWindow] fromView:nil]]]; + + _value = [self valueForKnobPosition:[_knob frame].origin]; + + [self sendAction:_action to:_target]; +} + +@end + +var CPSliderMinValueKey = @"CPSliderMinValueKey", + CPSliderMaxValueKey = @"CPSliderMaxValueKey", + CPSliderValueKey = @"CPSliderValueKey"; + +@implementation CPSlider (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super initWithCoder:aCoder]; + + if (self) + { + _value = [aCoder decodeDoubleForKey:CPSliderValueKey]; + _minValue = [aCoder decodeDoubleForKey:CPSliderMinValueKey]; + _maxValue = [aCoder decodeDoubleForKey:CPSliderMaxValueKey]; + + _bar = [self bar]; + _knob = [self knob]; + _knobSize = [[self knobImage] size]; + _isVertical = [self isVertical]; + + [_knob setFrameOrigin:[self knobPosition]]; + + [self addSubview:_bar]; + [self addSubview:_knob]; + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + var subviews = _subviews; + + _subviews = []; + + [super encodeWithCoder:aCoder]; + + _subviews = subviews; + + [aCoder encodeDouble:_value forKey:CPSliderValueKey]; + [aCoder encodeDouble:_minValue forKey:CPSliderMinValueKey]; + [aCoder encodeDouble:_maxValue forKey:CPSliderMaxValueKey]; +} + +@end + +var CPHUDSliderKnobImage = nil, + CPHUDSliderHorizontalBarLeftImage = nil, + CPHUDSliderHorizontalBarRightImage = nil, + CPHUDSliderHorizontalBarCenterImage = nil; + +@implementation CPHUDSlider : CPSlider +{ +} + ++ (void)initialize +{ + if (self != [CPHUDSlider class]) + return; + + var bundle = [CPBundle bundleForClass:self]; + + CPHUDSliderKnobImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/CPSliderHorizontalKnob.png"] size:CPSizeMake(12.0, 12.0)], + CPHUDSliderHorizontalBarLeftImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/CPSliderHorizontalBarLeft.png"] size:CPSizeMake(3.0, 4.0)], + CPHUDSliderHorizontalBarRightImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/CPSliderHorizontalBarRight.png"] size:CPSizeMake(3.0, 4.0)], + CPHUDSliderHorizontalBarCenterImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/CPSliderHorizontalBarCenter.png"] size:CPSizeMake(1.0, 4.0)]; +} + +- (CPImage)leftTrackImage +{ + return CPHUDSliderHorizontalBarLeftImage; +} + +- (CPImage)rightTrackImage +{ + return CPHUDSliderHorizontalBarRightImage; +} + +- (CPImage)centerTrackImage +{ + return CPHUDSliderHorizontalBarCenterImage +} + +- (CPImage)knobImage +{ + return CPHUDSliderKnobImage; +} + +@end diff --git a/AppKit/CPSliderColorPicker.j b/AppKit/CPSliderColorPicker.j new file mode 100644 index 000000000..f115b1154 --- /dev/null +++ b/AppKit/CPSliderColorPicker.j @@ -0,0 +1,404 @@ +/* + * CPApplication.j + * AppKit + * + * Created by Ross Boucher. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + +import +import +import +import + +@implementation CPSliderColorPicker : CPColorPicker +{ + CPView _contentView; + + CPSlider _redSlider; + CPSlider _greenSlider; + CPSlider _blueSlider; + CPSlider _hueSlider; + CPSlider _saturationSlider; + CPSlider _brightnessSlider; + + CPTextField _rgbLabel; + CPTextField _hsbLabel; + CPTextField _redLabel; + CPTextField _greenLabel; + CPTextField _blueLabel; + CPTextField _hueLabel; + CPTextField _saturationLabel; + CPTextField _brightnessLabel; + CPTextField _hexLabel; + + DOMElement _redValue; + DOMElement _greenValue; + DOMElement _blueValue; + DOMElement _hueValue; + DOMElement _saturationValue; + DOMElement _brightnessValue; + DOMElement _hexValue; +} + +- (id)initWithPickerMask:(int)mask colorPanel:(CPColorPanel)owningColorPanel +{ + return [super initWithPickerMask:mask colorPanel: owningColorPanel]; +} + +-(id)initView +{ + aFrame = CPRectMake(0, 0, CPColorPickerViewWidth, CPColorPickerViewHeight); + _contentView = [[CPView alloc] initWithFrame:aFrame]; + + _rgbLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 10, 100, 20)]; + [_rgbLabel setStringValue: "RGB"]; + [_rgbLabel setTextColor:[CPColor whiteColor]]; + + _redLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 35, 15, 20)]; + [_redLabel setStringValue: "R"]; + [_redLabel setTextColor:[CPColor whiteColor]]; + + _redSlider = [[CPSlider alloc] initWithFrame: CPRectMake(15, 35, aFrame.size.width - 70, 20)]; + [_redSlider setMaxValue: 1.0]; + [_redSlider setMinValue: 0.0]; + [_redSlider setTarget: self]; + [_redSlider setAction: @selector(sliderChanged:)]; + [_redSlider setAutoresizingMask: CPViewWidthSizable]; + + var updateFunction = function(aDOMEvent) + { + if(isNaN(this.value)) + return; + + switch(this) + { + case _redValue: [_redSlider setValue: MAX(MIN(ROUND(this.value), 255) / 255.0, 0)]; + [self sliderChanged: _redSlider]; + break; + + case _greenValue: [_greenSlider setValue: MAX(MIN(ROUND(this.value), 255) / 255.0, 0)]; + [self sliderChanged: _greenSlider]; + break; + + case _blueValue: [_blueSlider setValue: MAX(MIN(ROUND(this.value), 255) / 255.0, 0)]; + [self sliderChanged: _blueSlider]; + break; + + case _hueValue: [_hueSlider setValue: MAX(MIN(ROUND(this.value), 360), 0)]; + [self sliderChanged: _hueSlider]; + break; + + case _saturationValue: [_saturationSlider setValue: MAX(MIN(ROUND(this.value), 100), 0)]; + [self sliderChanged: _saturationSlider]; + break; + + case _brightnessValue: [_brightnessSlider setValue: MAX(MIN(ROUND(this.value), 100), 0)]; + [self sliderChanged: _brightnessSlider]; + break; + } + + this.blur(); + }; + + var keypressFunction = function(aDOMEvent) + { + aDOMEvent = aDOMEvent || window.event; + if (aDOMEvent.keyCode == 13) + { + updateFunction(aDOMEvent); + + if(aDOMEvent.preventDefault) + aDOMEvent.preventDefault(); + else if(aDOMEvent.stopPropagation) + aDOMEvent.stopPropagation(); + } + } + + //red value input box + var redValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 35, 45, 20)]; + [redValue setAutoresizingMask: CPViewMinXMargin]; + + _redValue = document.createElement("input"); + _redValue.style.width = "40px"; + _redValue.style.backgroundColor = "transparent"; + _redValue.style.border = "1px solid white"; + _redValue.style.color = "white"; + _redValue.style.position = "absolute"; + _redValue.style.top = "0px"; + _redValue.style.left = "0px"; + _redValue.onchange = updateFunction; + + redValue._DOMElement.appendChild(_redValue); + [_contentView addSubview: redValue]; + + _greenLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 58, 15, 20)]; + [_greenLabel setStringValue: "G"]; + [_greenLabel setTextColor:[CPColor whiteColor]]; + + _greenSlider = [[CPSlider alloc] initWithFrame: CPRectMake(15, 58, aFrame.size.width - 70, 20)]; + [_greenSlider setMaxValue: 1.0]; + [_greenSlider setMinValue: 0.0]; + [_greenSlider setTarget: self]; + [_greenSlider setAction: @selector(sliderChanged:)]; + [_greenSlider setAutoresizingMask: CPViewWidthSizable]; + + //green value input box + var greenValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 58, 45, 20)]; + [greenValue setAutoresizingMask: CPViewMinXMargin]; + + _greenValue = _redValue.cloneNode(false); + _greenValue.onchange = updateFunction; + + greenValue._DOMElement.appendChild(_greenValue); + [_contentView addSubview: greenValue]; + + _blueLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 81, 15, 20)]; + [_blueLabel setStringValue: "B"]; + [_blueLabel setTextColor:[CPColor whiteColor]]; + + _blueSlider = [[CPSlider alloc] initWithFrame: CPRectMake(15, 81, aFrame.size.width - 70, 20)]; + [_blueSlider setMaxValue: 1.0]; + [_blueSlider setMinValue: 0.0]; + [_blueSlider setTarget: self]; + [_blueSlider setAction: @selector(sliderChanged:)]; + [_blueSlider setAutoresizingMask: CPViewWidthSizable]; + + //blue value input box + var blueValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 81, 45, 20)]; + [blueValue setAutoresizingMask: CPViewMinXMargin]; + + _blueValue = _redValue.cloneNode(false); + _blueValue.onchange = updateFunction; + + blueValue._DOMElement.appendChild(_blueValue); + [_contentView addSubview: blueValue]; + + _hsbLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 120, 100, 20)]; + [_hsbLabel setStringValue: "HSB"]; + [_hsbLabel setTextColor:[CPColor whiteColor]]; + + _hueLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 145, 15, 20)]; + [_hueLabel setStringValue: "H"]; + [_hueLabel setTextColor:[CPColor whiteColor]]; + + _hueSlider = [[CPSlider alloc] initWithFrame: CPRectMake(15, 145, aFrame.size.width - 70, 20)]; + [_hueSlider setMaxValue: 359.0]; + [_hueSlider setMinValue: 0.0]; + [_hueSlider setTarget: self]; + [_hueSlider setAction: @selector(sliderChanged:)]; + [_hueSlider setAutoresizingMask: CPViewWidthSizable]; + + //red value input box + var hueValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 145, 45, 20)]; + [hueValue setAutoresizingMask: CPViewMinXMargin]; + + _hueValue = _redValue.cloneNode(false); + _hueValue.onchange = updateFunction; + + hueValue._DOMElement.appendChild(_hueValue); + [_contentView addSubview: hueValue]; + + _saturationLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 168, 15, 20)]; + [_saturationLabel setStringValue: "S"]; + [_saturationLabel setTextColor:[CPColor whiteColor]]; + + _saturationSlider = [[CPSlider alloc] initWithFrame: CPRectMake(15, 168, aFrame.size.width - 70, 20)]; + [_saturationSlider setMaxValue: 100.0]; + [_saturationSlider setMinValue: 0.0]; + [_saturationSlider setTarget: self]; + [_saturationSlider setAction: @selector(sliderChanged:)]; + [_saturationSlider setAutoresizingMask: CPViewWidthSizable]; + + //green value input box + var saturationValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 168, 45, 20)]; + [saturationValue setAutoresizingMask: CPViewMinXMargin]; + + _saturationValue = _redValue.cloneNode(false); + _saturationValue.onchange = updateFunction; + + saturationValue._DOMElement.appendChild(_saturationValue); + [_contentView addSubview: saturationValue]; + + _brightnessLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 191, 15, 20)]; + [_brightnessLabel setStringValue: "B"]; + [_brightnessLabel setTextColor:[CPColor whiteColor]]; + + _brightnessSlider = [[CPSlider alloc] initWithFrame: CPRectMake(15, 191, aFrame.size.width - 70, 20)]; + [_brightnessSlider setMaxValue: 100.0]; + [_brightnessSlider setMinValue: 0.0]; + [_brightnessSlider setTarget: self]; + [_brightnessSlider setAction: @selector(sliderChanged:)]; + [_brightnessSlider setAutoresizingMask: CPViewWidthSizable]; + + //blue value input box + var brightnessValue = [[CPView alloc] initWithFrame: CPRectMake(aFrame.size.width - 45, 191, 45, 20)]; + [brightnessValue setAutoresizingMask: CPViewMinXMargin]; + + _brightnessValue = _redValue.cloneNode(false); + _brightnessValue.onchange = updateFunction; + + brightnessValue._DOMElement.appendChild(_brightnessValue); + [_contentView addSubview: brightnessValue]; + + _hexLabel = [[CPTextField alloc] initWithFrame: CPRectMake(0, 230, 100, 20)]; + [_hexLabel setStringValue: "Hex"]; + [_hexLabel setTextColor:[CPColor whiteColor]]; + + //hex input box + _hexValue = _redValue.cloneNode(false); + _hexValue.style.top = "255px"; + _hexValue.style.width = "80px"; + _hexValue.style.left = "0px"; + _hexValue.onkeypress = function(aDOMEvent) + { + aDOMEvent = aDOMEvent || window.event; + if (aDOMEvent.keyCode == 13) + { + var newColor = [CPColor colorWithHexString: this.value]; + + if(newColor) + { + [self setColor: newColor]; + [[self colorPanel] setColor: newColor]; + } + + if(aDOMEvent.preventDefault) + aDOMEvent.preventDefault(); + else if(aDOMEvent.stopPropagation) + aDOMEvent.stopPropagation(); + + this.blur(); + } + }; + + _contentView._DOMElement.appendChild(_hexValue); + + [_contentView addSubview: _rgbLabel]; + [_contentView addSubview: _redLabel]; + [_contentView addSubview: _greenLabel]; + [_contentView addSubview: _blueLabel]; + [_contentView addSubview: _redSlider]; + [_contentView addSubview: _greenSlider]; + [_contentView addSubview: _blueSlider]; + + [_contentView addSubview: _hsbLabel]; + [_contentView addSubview: _hueLabel]; + [_contentView addSubview: _saturationLabel]; + [_contentView addSubview: _brightnessLabel]; + [_contentView addSubview: _hueSlider]; + [_contentView addSubview: _saturationSlider]; + [_contentView addSubview: _brightnessSlider]; + + [_contentView addSubview: _hexLabel]; +} + +- (CPView)provideNewView:(BOOL)initialRequest +{ + if (initialRequest) + [self initView]; + + return _contentView; +} + +- (int)currentMode +{ + return CPSliderColorPickerMode; +} + +- (BOOL)supportsMode:(int)mode +{ + return (mode == CPSliderColorPickerMode) ? YES : NO; +} + +-(void)sliderChanged:(id)sender +{ + var newColor; + + switch(sender) + { + case _hueSlider: + case _saturationSlider: + case _brightnessSlider: newColor = [CPColor colorWithHue: [_hueSlider value] + saturation: [_saturationSlider value] + brightness: [_brightnessSlider value]]; + + [self updateRGBSliders: newColor]; + break; + + case _redSlider: + case _greenSlider: + case _blueSlider: newColor = [CPColor colorWithCalibratedRed: [_redSlider value] + green: [_greenSlider value] + blue: [_blueSlider value] + alpha: 1.0]; + + [self updateHSBSliders: newColor]; + break; + } + + [self updateLabels]; + [self updateHex: newColor]; + [[self colorPanel] setColor: newColor]; +} + +-(void)setColor:(CPColor)aColor +{ + [self updateRGBSliders: aColor]; + [self updateHSBSliders: aColor]; + [self updateHex: aColor]; + [self updateLabels]; +} + +-(void)updateHSBSliders:(CPColor)aColor +{ + var hsb = [aColor hsbComponents]; + + [_hueSlider setValue: hsb[0]]; + [_saturationSlider setValue: hsb[1]]; + [_brightnessSlider setValue: hsb[2]]; +} + +- (void)updateHex:(CPColor)aColor +{ + _hexValue.value = [aColor hexString]; +} + +- (void)updateRGBSliders:(CPColor)aColor +{ + var rgb = [aColor components]; + + [_redSlider setValue: rgb[0]]; + [_greenSlider setValue: rgb[1]]; + [_blueSlider setValue: rgb[2]]; +} + +- (void)updateLabels +{ + _hueValue.value = ROUND([_hueSlider value]); + _saturationValue.value = ROUND([_saturationSlider value]); + _brightnessValue.value = ROUND([_brightnessSlider value]); + + _redValue.value = ROUND([_redSlider value] * 255); + _greenValue.value = ROUND([_greenSlider value] * 255); + _blueValue.value = ROUND([_blueSlider value] * 255); +} + + +@end diff --git a/AppKit/CPStringDrawing.j b/AppKit/CPStringDrawing.j new file mode 100644 index 000000000..1d3644073 --- /dev/null +++ b/AppKit/CPStringDrawing.j @@ -0,0 +1,67 @@ +/* + * CPStringDrawing.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + + +var CPStringReferenceElement = nil; + +@implementation CPString (CPStringDrawing) + +- (CPString)cssString +{ + return self; +} + +- (CGSize)sizeWithFont:(CPFont)aFont +{ + if (!CPStringReferenceElement) + { + CPStringReferenceElement = document.createElement("span"); + + var style = CPStringReferenceElement.style; + + style.position = "absolute"; + style.whiteSpace = "pre"; + style.visibility = "visible"; + style.padding = "0px"; + style.margin = "0px"; + + style.left = "-100000px"; + style.top = "-100000px"; + style.zIndex = "10000"; + style.background = "red"; + + document.getElementsByTagName("body")[0].appendChild(CPStringReferenceElement); + } + + CPStringReferenceElement.style.font = [aFont ? aFont : [CPFont systemFontOfSize:12.0] cssString]; + + if (CPFeatureIsCompatible(CPJavascriptInnerTextFeature)) + CPStringReferenceElement.innerText = self; + else if (CPFeatureIsCompatible(CPJavascriptTextContentFeature)) + CPStringReferenceElement.textContent = self; + + return CGSizeMake(CPStringReferenceElement.clientWidth, CPStringReferenceElement.clientHeight); +} + +@end diff --git a/AppKit/CPTabView.j b/AppKit/CPTabView.j new file mode 100644 index 000000000..5eb3dd1a4 --- /dev/null +++ b/AppKit/CPTabView.j @@ -0,0 +1,627 @@ +/* + * CPTabView.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPImageView.j" +import "CPTabViewItem.j" +import "CPView.j" + +#include "CoreGraphics/CGGeometry.h" + + +CPTopTabsBezelBorder = 0; +//CPLeftTabsBezelBorder = 1; +//CPBottomTabsBezelBorder = 2; +//CPRightTabsBezelBorder = 3; +CPNoTabsBezelBorder = 4; +CPNoTabsLineBorder = 5; +CPNoTabsNoBorder = 6; + +var CPTabViewBezelBorderLeftImage = nil, + CPTabViewBackgroundCenterImage = nil, + CPTabViewBezelBorderRightImage = nil, + CPTabViewBezelBorderColor = nil, + CPTabViewBezelBorderBackgroundColor = nil; + +var LEFT_INSET = 7.0, + RIGHT_INSET = 7.0; + +var CPTabViewDidSelectTabViewItemSelector = 1, + CPTabViewShouldSelectTabViewItemSelector = 2, + CPTabViewWillSelectTabViewItemSelector = 4, + CPTabViewDidChangeNumberOfTabViewItemsSelector = 8; + +@implementation CPTabView : CPView +{ + CPView _labelsView; + CPView _backgroundView; + CPView _separatorView; + + CPView _auxiliaryView; + CPView _contentView; + + CPArray _tabViewItems; + CPTabViewItem _selectedTabViewItem; + + CPTabViewType _tabViewType; + + id _delegate; + unsigned _delegateSelectors; +} + ++ (void)initialize +{ + if (self != CPTabView) + return; + + var bundle = [CPBundle bundleForClass:self], + + emptyImage = [[CPImage alloc] initByReferencingFile:@"" size:CGSizeMake(7.0, 0.0)], + backgroundImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/CPTabViewBezelBackgroundCenter.png"] size:CGSizeMake(1.0, 1.0)], + + bezelBorderLeftImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/CPTabViewBezelBorderLeft.png"] size:CGSizeMake(7.0, 1.0)], + bezerBorderImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/CPTabViewBezelBorder.png"] size:CGSizeMake(1.0, 1.0)], + bezelBorderRightImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/CPTabViewBezelBorderRight.png"] size:CGSizeMake(7.0, 1.0)]; + + CPTabViewBezelBorderBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices: + [ + emptyImage, + emptyImage, + emptyImage, + + bezelBorderLeftImage, + backgroundImage, + bezelBorderRightImage, + + bezelBorderLeftImage, + bezerBorderImage, + bezelBorderRightImage + ]]]; + + CPTabViewBezelBorderColor = [CPColor colorWithPatternImage:bezerBorderImage]; +} + ++ (CPColor)bezelBorderColor +{ + return CPTabViewBezelBorderColor; +} + +- (id)initWithFrame:(CGRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _tabViewType = CPTopTabsBezelBorder; + _tabViewItems = []; + } + + return self; +} + +- (void)viewDidMoveToWindow +{ + if (_tabViewType != CPTopTabsBezelBorder || _labelsView) + return; + + [self _createBezelBorder]; + [self layoutSubviews]; +} + +- (void)_createBezelBorder +{ + var bounds = [self bounds]; + + _labelsView = [[_CPTabLabelsView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(bounds), 0.0)]; + + [_labelsView setTabView:self]; + [_labelsView setAutoresizingMask:CPViewWidthSizable]; + + [self addSubview:_labelsView]; + + _backgroundView = [[CPView alloc] initWithFrame:CGRectMakeZero()]; + + [_backgroundView setBackgroundColor:CPTabViewBezelBorderBackgroundColor]; + + [_backgroundView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; + + [self addSubview:_backgroundView]; + + _separatorView = [[CPView alloc] initWithFrame:CGRectMakeZero()]; + + [_separatorView setBackgroundColor:[[self class] bezelBorderColor]]; + [_separatorView setAutoresizingMask:CPViewWidthSizable | CPViewMaxYMargin]; + + [self addSubview:_separatorView]; +} + +- (void)layoutSubviews +{ + if (_tabViewType == CPTopTabsBezelBorder) + { + var backgroundRect = [self bounds], + labelsViewHeight = [_CPTabLabelsView height]; + + backgroundRect.origin.y += labelsViewHeight; + backgroundRect.size.height -= labelsViewHeight; + + [_backgroundView setFrame:backgroundRect]; + + var auxiliaryViewHeight = 5.0; + + if (_auxiliaryView) + { + auxiliaryViewHeight = CGRectGetHeight([_auxiliaryView frame]); + + [_auxiliaryView setFrame:CGRectMake(LEFT_INSET, labelsViewHeight, CGRectGetWidth(backgroundRect) - LEFT_INSET - RIGHT_INSET, auxiliaryViewHeight)]; + } + + [_separatorView setFrame:CGRectMake(LEFT_INSET, labelsViewHeight + auxiliaryViewHeight, CGRectGetWidth(backgroundRect) - LEFT_INSET - RIGHT_INSET, 1.0)]; + } + + // CPNoTabsNoBorder + [_contentView setFrame:[self contentRect]]; +} + +// Adding and Removing Tabs + +- (void)addTabViewItem:(CPTabViewItem)aTabViewItem +{ + [self insertTabViewItem:aTabViewItem atIndex:[_tabViewItems count]]; +} + +- (void)insertTabViewItem:(CPTabViewItem)aTabViewItem atIndex:(unsigned)anIndex +{ + [_tabViewItems insertObject:aTabViewItem atIndex:anIndex]; + + [_labelsView tabView:self didAddTabViewItem:aTabViewItem]; + + if ([_tabViewItems count] == 1) + [self selectFirstTabViewItem:self]; + + if (_delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector) + [_delegate tabViewDidChangeNumberOfTabViewItems:self]; +} + +- (void)removeTabViewItem:(CPTabViewItem)aTabViewItem +{ + [_tabViewItems removeObjectIdenticalTo:aTabViewItem]; + + [_labelsView tabView:self didRemoveTabViewItem:aTabViewItem]; + + if (_delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector) + [_delegate tabViewDidChangeNumberOfTabViewItems:self]; +} + +// Accessing Tabs + +- (int)indexOfTabViewItem:(CPTabViewItem)aTabViewItem +{ + return [_tabViewItems indexOfObjectIdenticalTo:aTabViewItem]; +} + +- (int)indexOfTabViewItemWithIdentifier:(CPString)anIdentifier +{ + var index = 0, + count = [_tabViewItems count]; + + for (; index < count; ++index) + if ([[_tabViewItems[index] identifier] isEqualTo:anIdentifier]) + return index; + + return index; +} + +- (unsigned)numberOfTabViewItems +{ + return [_tabViewItems count]; +} + +- (CPTabViewItem)tabViewItemAtIndex:(unsigned)anIndex +{ + return _tabViewItems[anIndex]; +} + +- (CPArray)tabViewItems +{ + return _tabViewItems; +} + +// Selecting a Tab + +- (void)selectFirstTabViewItem:(id)aSender +{ + var count = [_tabViewItems count]; + + if (count) + [self selectTabViewItemAtIndex:0]; +} + +- (void)selectLastTabViewItem:(id)aSender +{ + var count = [_tabViewItems count]; + + if (count) + [self selectTabViewItemAtIndex:count - 1]; +} + +- (void)selectNextTabViewItem:(id)aSender +{ + if (!_selectedTabViewItem) + return; + + var index = [self indexOfTabViewItem:_selectedTabViewItem], + count = [_tabViewItems count]; + + [self selectTabViewItemAtIndex:index + 1 % count]; +} + +- (void)selectPreviousTabViewItem:(id)aSender +{ + if (!_selectedTabViewItem) + return; + + var index = [self indexOfTabViewItem:_selectedTabViewItem], + count = [_tabViewItems count]; + + [self selectTabViewItemAtIndex:index == 0 ? count : index - 1]; +} + +- (void)selectTabViewItem:(CPTabViewItem)aTabViewItem +{ + if ((_delegateSelectors & CPTabViewShouldSelectTabViewItemSelector) && ![_delegate tabView:self shouldSelectTabViewItem:aTabViewItem]) + return; + + if (_delegateSelectors & CPTabViewWillSelectTabViewItemSelector) + [_delegate tabView:self willSelectTabViewItem:aTabViewItem]; + + if (_selectedTabViewItem) + { + _selectedTabViewItem._tabState = CPBackgroundTab; + [_labelsView tabView:self didChangeStateOfTabViewItem:_selectedTabViewItem]; + + [_contentView removeFromSuperview]; + [_auxiliaryView removeFromSuperview]; + } + _selectedTabViewItem = aTabViewItem; + + _selectedTabViewItem._tabState = CPSelectedTab; + + _contentView = [_selectedTabViewItem view]; + [_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; + + _auxiliaryView = [_selectedTabViewItem auxiliaryView]; + [_auxiliaryView setAutoresizingMask:CPViewWidthSizable]; + + [self addSubview:_contentView]; + + if (_auxiliaryView) + [self addSubview:_auxiliaryView]; + + [_labelsView tabView:self didChangeStateOfTabViewItem:_selectedTabViewItem]; + + [self layoutSubviews]; + + if (_delegateSelectors & CPTabViewDidSelectTabViewItemSelector) + [_delegate tabView:self didSelectTabViewItem:aTabViewItem]; +} + +- (void)selectTabViewItemAtIndex:(unsigned)anIndex +{ + [self selectTabViewItem:_tabViewItems[anIndex]]; +} + +- (void)selectedTabViewItem +{ + return _selectedTabViewItem; +} + +// + +- (void)setTabViewType:(CPTabViewType)aTabViewType +{ + if (_tabViewType == aTabViewType) + return; + + _tabViewType = aTabViewType; + + if (_tabViewType == CPNoTabsBezelBorder || _tabViewType == CPNoTabsLineBorder || _tabViewType == CPNoTabsNoBorder) + [_labelsView removeFromSuperview]; + else if (![_labelsView superview]) + [self addSubview:_lablesView]; + + if (_tabViewType == CPNoTabsLineBorder || _tabViewType == CPNoTabsNoBorder) + [_backgroundView removeFromSuperview]; + else if (![_backgroundView superview]) + [self addSubview:_backgroundView]; + + [self layoutSubviews]; +} + +- (CPTabViewType)tabViewType +{ + return _tabViewType; +} + +// Determining the Size + +- (CGRect)contentRect +{ + var contentRect = CGRectMakeCopy([self bounds]); + + if (_tabViewType == CPTopTabsBezelBorder) + { + var labelsViewHeight = [_CPTabLabelsView height], + auxiliaryViewHeight = _auxiliaryView ? CGRectGetHeight([_auxiliaryView frame]) : 5.0, + separatorViewHeight = 1.0; + + contentRect.origin.y += labelsViewHeight + auxiliaryViewHeight + separatorViewHeight; + contentRect.size.height -= labelsViewHeight + auxiliaryViewHeight + separatorViewHeight * 2.0; // 2 for the bottom border as well. + + contentRect.origin.x += LEFT_INSET; + contentRect.size.width -= LEFT_INSET + RIGHT_INSET; + } + + return contentRect; +} + +- (void)setDelegate:(id)aDelegate +{ + if (_delegate == aDelegate) + return; + + _delegate = aDelegate; + + _delegateSelectors = 0; + + if ([_delegate respondsToSelector:@selector(tabView:shouldSelectTabViewItem:)]) + _delegateSelectors |= CPTabViewShouldSelectTabViewItemSelector; + + if ([_delegate respondsToSelector:@selector(tabView:willSelectTabViewItem:)]) + _delegateSelectors |= CPTabViewWillSelectTabViewItemSelector; + + if ([_delegate respondsToSelector:@selector(tabView:didSelectTabViewItem:)]) + _delegateSelectors |= CPTabViewDidSelectTabViewItemSelector; + + if ([_delegate respondsToSelector:@selector(tabViewDidChangeNumberOfTabViewItems:)]) + _delegateSelectors |= CPTabViewDidChangeNumberOfTabViewItemsSelector; +} + +// + +- (void)mouseDown:(CPEvent)anEvent +{ + var location = [_labelsView convertPoint:[anEvent locationInWindow] fromView:nil], + tabViewItem = [_labelsView representedTabViewItemAtPoint:location]; + + if (tabViewItem) + [self selectTabViewItem:tabViewItem]; +} + +@end + +var _CPTabLabelsViewBackgroundColor = nil, + _CPTabLabelsViewInsideMargin = 10.0, + _CPTabLabelsViewOutsideMargin = 15.0; + +@implementation _CPTabLabelsView : CPView +{ + CPTabView _tabView; + CPDictionary _tabLabels; +} + ++ (void)initialize +{ + if (self != [_CPTabLabelsView class]) + return; + + var bundle = [CPBundle bundleForClass:self]; + + _CPTabLabelsViewBackgroundColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices: + [ + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelsViewLeft.png"] size:CGSizeMake(12.0, 26.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelsViewCenter.png"] size:CGSizeMake(1.0, 26.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelsViewRight.png"] size:CGSizeMake(12.0, 26.0)] + ] isVertical:NO]]; +} + ++ (float)height +{ + return 26.0; +} + +- (id)initWithFrame:(CGRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _tabLabels = []; + + [self setBackgroundColor:_CPTabLabelsViewBackgroundColor]; + + [self setFrameSize:CGSizeMake(CGRectGetWidth(aFrame), 26.0)]; + } + + return self; +} + +- (void)setTabView:(CPTabView)aTabView +{ + _tabView = aTabView; +} + +- (CPTabView)tabView +{ + return _tabView; +} + +- (void)tabView:(CPTabView)aTabView didAddTabViewItem:(CPTabViewItem)aTabViewItem +{ + var label = [[_CPTabLabel alloc] initWithFrame:CGRectMakeZero()]; + + [label setTabViewItem:aTabViewItem]; + + _tabLabels.push(label); + + [self addSubview:label]; + + [self layoutSubviews]; +} + +- (void)tabView:(CPTabView)aTabView didRemoveTabViewItem:(CPTabViewItem)aTabViewItem +{ + var index = [aTabView indexOfTabViewItem:aTabViewItem], + label = _tabLabels[index]; + + [_tabLabels removeObjectAtIndex:index]; + + [label removeFromSuperview]; + + [self layoutSubviews]; +} + + -(void)tabView:(CPTabView)aTabView didChangeStateOfTabViewItem:(CPTabViewItem)aTabViewItem + { + [_tabLabels[[aTabView indexOfTabViewItem:aTabViewItem]] setTabState:[aTabViewItem tabState]]; + } + +- (CPTabViewItem)representedTabViewItemAtPoint:(CGPoint)aPoint +{ + var index = 0, + count = _tabLabels.length; + + for (; index < count; ++index) + { + var label = _tabLabels[index]; + + if (CGRectContainsPoint([label frame], aPoint)) + return [label tabViewItem]; + } + + return nil; +} + +- (void)layoutSubviews +{ + var index = 0, + count = _tabLabels.length, + width = (_CGRectGetWidth([self bounds]) - (count - 1) * _CPTabLabelsViewInsideMargin - 2 * _CPTabLabelsViewOutsideMargin) / count, + x = _CPTabLabelsViewOutsideMargin; + + for (; index < count; ++index) + { + var label = _tabLabels[index], + frame = _CGRectMake(x, 8.0, width, 18.0); + + [label setFrame:frame]; + + x = _CGRectGetMaxX(frame) + _CPTabLabelsViewInsideMargin; + } +} + +- (void)setFrameSize:(CGSize)aSize +{ + if (CGSizeEqualToSize([self frame].size, aSize)) + return; + + [super setFrameSize:aSize]; + + [self layoutSubviews]; +} + +@end + +var _CPTabLabelBackgroundColor = nil, + _CPTabLabelSelectedBackgroundColor = nil; + +@implementation _CPTabLabel : CPView +{ + CPTabViewItem _tabViewItem; + CPTextField _labelField; +} + ++ (void)initialize +{ + if (self != [_CPTabLabel class]) + return; + + var bundle = [CPBundle bundleForClass:self]; + + _CPTabLabelBackgroundColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices: + [ + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelBackgroundLeft.png"] size:CGSizeMake(6.0, 18.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelBackgroundCenter.png"] size:CGSizeMake(1.0, 18.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelBackgroundRight.png"] size:CGSizeMake(6.0, 18.0)] + ] isVertical:NO]]; + + _CPTabLabelSelectedBackgroundColor = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices: + [ + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelSelectedLeft.png"] size:CGSizeMake(3.0, 18.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelSelectedCenter.png"] size:CGSizeMake(1.0, 18.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTabView/_CPTabLabelSelectedRight.png"] size:CGSizeMake(3.0, 18.0)] + ] isVertical:NO]]; +} + +- (id)initWithFrame:(CGRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _labelField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()]; + + [_labelField setAlignment:CPCenterTextAlignment]; + [_labelField setFrame:CGRectMake(5.0, 0.0, CGRectGetWidth(aFrame) - 10.0, 20.0)]; + [_labelField setAutoresizingMask:CPViewWidthSizable]; + [_labelField setFont:[CPFont boldSystemFontOfSize:11.0]]; + + [self addSubview:_labelField]; + + [self setTabState:CPBackgroundTab]; + } + + return self; +} + +- (void)setTabState:(CPTabState)aTabState +{ + [self setBackgroundColor:aTabState == CPSelectedTab ? _CPTabLabelSelectedBackgroundColor : _CPTabLabelBackgroundColor]; +} + +- (void)setTabViewItem:(CPTabViewItem)aTabViewItem +{ + _tabViewItem = aTabViewItem; + + [self update]; +} + +- (CPTabViewItem)tabViewItem +{ + return _tabViewItem; +} + +- (void)update +{ + [_labelField setStringValue:[_tabViewItem label]]; +} + +@end diff --git a/AppKit/CPTabViewItem.j b/AppKit/CPTabViewItem.j new file mode 100644 index 000000000..a5f7306e1 --- /dev/null +++ b/AppKit/CPTabViewItem.j @@ -0,0 +1,113 @@ +/* + * CPTabViewItem.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + +import + + +CPSelectedTab = 0; +CPBackgroundTab = 1; +CPPressedTab = 2; + +@implementation CPTabViewItem : CPObject +{ + id _identifier; + CPString _label; + + CPView _view; + CPView _auxiliaryView; +} + +- (id)initWithIdentifier:(id)anIdentifier +{ + self = [super init]; + + if (self) + _identifier = anIdentifier; + + return self; +} + +// Working With Labels + +- (void)setLabel:(CPString)aLabel +{ + _label = aLabel; +} + +- (CPString)label +{ + return _label; +} + +// Checking the Tab Display State + +- (CPTabState)tabState +{ + return _tabState; +} + +// Assigning an Identifier Object + +- (void)setIdentifier:(id)anIdentifier +{ + _identifier = anIdentifier; +} + +- (id)identifier +{ + return _identifier; +} + +// Assigning a View + +- (void)setView:(CPView)aView +{ + _view = aView; +} + +- (CPView)view +{ + return _view; +} + +// Assigning an Auxiliary View + +- (void)setAuxiliaryView:(CPView)anAuxiliaryView +{ + _auxiliaryView = anAuxiliaryView; +} + +- (CPView)auxiliaryView +{ + return _auxiliaryView; +} + +// Accessing the Parent Tab View + +- (CPView)tabView +{ + return _tabView; +} + +@end diff --git a/AppKit/CPTableColumn.j b/AppKit/CPTableColumn.j new file mode 100644 index 000000000..84872362f --- /dev/null +++ b/AppKit/CPTableColumn.j @@ -0,0 +1,171 @@ +/* + * CPTableColumn.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + + +CPTableColumnNoResizing = 0; +CPTableColumnAutoresizingMask = 1; +CPTableColumnUserResizingMask = 2; + +@implementation CPTableColumn : CPObject +{ + CPString _identifier; + + CPTableView _tableView; + + float _width; + float _minWidth; + float _maxWidth; + + unsigned _resizingMask; +} + +- (id)initWithIdentifier:(CPString)anIdentifier +{ + self = [super init]; + + if (self) + { + _identifier = anIdentifier; + + _width = 40.0; + _minWidth = 8.0; + _maxWidth = 1000.0; + + // FIXME + _dataCell = [[CPTextField alloc] initWithFrame:CPRectMakeZero()]; + } + + return self; +} + +- (void)setIdentifier:(CPString)anIdentifier +{ + _identifier = anIdentifier; +} + +- (CPString)identifier +{ + return _identifier; +} + +// Setting the NSTableView + +- (void)setTabelView:(CPTableView)aTableView +{ + _tableView = aTableView; +} + +- (CPTableView)tableView +{ + return _tableView; +} + +// Controlling size + +- (void)setWidth:(float)aWidth +{ + _width = aWidth; +} + +- (float)width +{ + return _width; +} + +- (void)setMinWidth:(float)aWidth +{ + if (_width < (_minWidth = aWidth)) + [self setWidth:_minWidth]; +} + +- (float)minWidth +{ + return _minWidth; +} + +- (float)setMaxWidth:(float)aWidth +{ + if (_width > (_maxmimumWidth = aWidth)) + [self setWidth:_maxWidth]; +} + +- (void)setResizingMask:(unsigned)aMask +{ + _resizingMask = aMask; +} + +- (unsigned)resizingMask +{ + return _resizingMask; +} + +- (void)sizeToFit +{ + var width = CPRectGetWidth([_headerView frame]); + + if (width < _minWidth) + [self setMinWidth:width]; + else if (width > _maxWidth) + [self setMaxWidth:width] + + if (_width != width) + [self setWidth:width]; +} + +- (void)setEditable:(BOOL)aFlag +{ + _isEditable = aFlag; +} + +- (BOOL)isEditable +{ + return _isEditable; +} + +- (void)setHeaderView:(CPView)aHeaderView +{ + _headerView = aHeaderView; +} + +- (CPView)headerView +{ + return _headerView; +} + +- (void)setDataCell:(id)aDataCell +{ + _dataCell = aDataCell; +} + +- (id)dataCell +{ + return _dataCell; +} + +- (Class)dataCellForRow:(int)aRowIndex +{ + return [self dataCell]; +} + +@end diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j new file mode 100644 index 000000000..ed5d5aee4 --- /dev/null +++ b/AppKit/CPTableView.j @@ -0,0 +1,339 @@ +/* + * CPTableView.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPControl.j" +import "CPTableColumn.j" + + +var CPTableViewCellPlaceholder = nil; + +@implementation CPTableView : CPControl +{ + id _dataSource; + + CPScrollView _scrollView; + CPTableHeaderView _headerView; + + CPArray _tableColumns; + + unsigned _numberOfRows; + unsigned _numberOfColumns; + + CPArray _tableCells; + CPArray _tableColumnViews; + + CPSize _intercellSpacing; +} + ++ (void)initialize +{ + if (self != [CPTableView class]) + return; + + CPTableViewCellPlaceholder = [[CPObject alloc] init]; +} + +- (id)initWithFrame:(CPRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + /*_scrollView = [[CPView alloc] initWithFrame:CPRectMakeZero()]; + _headerView = [[CPView alloc] initWithFrame:CPRectMakeZero()]; + + [_scrollView setBackgroundColor:[CPColor redColor]]; + [_headerView setBackgroundColor:[CPColor blueColor]]; + + [self addSubview:_scrollView]; + [self addSubview:_headerView]; + + [self tile];*/ + + //[self setBackgroundColor:[CPColor redColor]]; + + _rowHeight = 17.0; + + _tableCells = [[CPArray alloc] init]; + _tableColumns = [[CPArray alloc] init]; + _tableColumnViews = [[CPArray alloc] init]; + + _intercellSpacing = CPSizeMake(3.0, 2.0); + } + + return self; +} + +- (float)columnHeight +{ + var bounds = [self bounds], + height = _numberOfRows * (_rowHeight + _intercellSpacing.height); + + return CPRectGetHeight(bounds) > height ? CPRectGetHeight(bounds) : height; +} + +- (void)loadTableCellsInRect:(CPRect)aRect +{ + if (!_dataSource) + return; + + // Use a ambitious estimate for our starting row. + var rows = CPMakeRange(MAX(Math.floor((CPRectGetMinY(aRect) + _intercellSpacing.height) / (_rowHeight + _intercellSpacing.height)), 0), 1); + + // Use a conservative estimate for the final row. + rows.length = MIN(_numberOfRows, Math.ceil(CPRectGetMaxY(aRect) / (_rowHeight + _intercellSpacing.height))) - rows.location; + + var columns = CPMakeRange(0, 1); + + // Iterate through all our columns until we find one that intersects the rect. + while (columns.location < _numberOfColumns && !CPRectIntersectsRect([_tableColumnViews[columns.location] frame], aRect)) + ++columns.location; + + // Now iterate through our columns until we find one that doesn't intersect our rect. + while (CPMaxRange(columns) < _numberOfColumns && CPRectIntersectsRect([_tableColumnViews[CPMaxRange(columns)] frame], aRect)) + ++columns.length; + + var row = rows.location, + column = 0; + + for (; row < CPMaxRange(rows); ++row) + for (column = columns.location; column < CPMaxRange(columns); ++column) + { + if (!_tableCells[column][row] || _tableCells[column][row] == CPTableViewCellPlaceholder) + { + _tableCells[column][row] = [[_tableColumns[column] dataCellForRow:row] copy]; + + [_tableCells[column][row] setFrame:CPRectMake(0.0, row * (_rowHeight + _intercellSpacing.height), [_tableColumns[column] width], _rowHeight)]; + //[_tableCells[column][row] setBackgroundColor:[CPColor blueColor]]; + [_tableColumnViews[column] addSubview:_tableCells[column][row]]; + } + + [_tableCells[column][row] setObjectValue:[_dataSource tableView:self objectValueForTableColumn:_tableColumns[column] row:row]]; + } +} + +// Setting display attributes + +- (void)setIntercellSpacing:(CPSize)aSize +{ + if (_intercellSpacing.width != aSize.width) + { + var i = 1, + delta = aSize.width - _intercellSpacing.width; + total = delta; + + for (; i < _numberOfColumns; ++i, total += delta) + { + var origin = [_tableColumnViews[i] frame].origin; + [_tableColumnViews[i] setFrameOrigin:CPPointMake(origin.x + total, origin.y)]; + } + } + + if (_intercellSpacing.height != aSize.height) + { + var i = 0; + + for (; i < _numberOfColumns; ++i, total += delta) + { + [_tableColumnViews[i] setFrameSize:CPSizeMake([_tableColumnViews[i] width], _numberOfRows * (_rowHeight + _intercellSpacing.height))]; + + var j = 1, + y = _rowHeight + _intercellSpacing.height; + + for (; j < _numberOfRows; ++i, y += _rowHeight + _intercellSpacing.height) + { + if (_tableCells[i][j] == CPTableViewCellPlaceholder) + continue; + + [_tableCells[i][j] setFrameOrigin:CPPointMake(0.0, y)]; + } + } + } + + _intercellSpacing = CPSizeCreateCopy(aSize); +} + +- (CPSize)intercellSpacing +{ + return _intercellSpacing; +} + +- (void)setRowHeight:(unsigned)aRowHeight +{ + if (_rowHeight == aRowHeight) + return; + + _rowHeight = aRowHeight; + + var row = 0, + column = 0; + + for (; row < _numberOfRows; ++row) + for (column = 0; column < _numberOfColumns; ++column) + [_tableCells[column][row] setFrameOrigin:CPPointMake(0.0, row * (_rowHeight + _intercellSpacing.height))]; +} + +- (unsigned)rowHeight +{ + return _rowHeight; +} + +- (void)addTableColumn:(CPTableColumn)aTableColumn +{ + var i = 0, + x = _numberOfColumns ? CPRectGetMaxX([self rectOfColumn:_numberOfColumns - 1]) + _intercellSpacing.width : 0.0, + tableColumnView = [[CPView alloc] initWithFrame:CPRectMake(x, 0.0, [aTableColumn width], [self columnHeight])], + tableColumnCells = [[CPArray alloc] init]; + + [_tableColumns addObject:aTableColumn]; + [_tableColumnViews addObject:tableColumnView]; + +// [tableColumnView setBackgroundColor:[CPColor greenColor]]; + + [self addSubview:tableColumnView]; + + [_tableCells addObject:tableColumnCells]; + + for (; i < _numberOfRows; ++i) + _tableCells[_numberOfColumns][i] = CPTableViewCellPlaceholder; + + ++_numberOfColumns; +} + +- (void)removeTableColumn:(CPTableColumn)aTableColumn +{ + var frame = [self frame], + width = [aTableColumn width] + _intercellSpacing.width, + index = [_tableColumns indexOfObjectIdenticalTo:aTableColumn]; + + // Remove the column view and all the cell views from the view hierarchy. + [_tableColumnViews[i] removeFromSuperview]; + + [_tableCells removeObjectAtIndex:index]; + [_tableColumns removeObjectAtIndex:index]; + [_tabelColumnViews removeObjectAtIndex:index]; + + // Shift remaining column views to the left. + for (; index < _numberOfColumns; ++ index) + [_tableColumnViews[index] setFrameOrigin:CPPointMake(CPRectGetMinX([_tableColumnViews[index] frame]) - width, 0.0)] + + // Resize ourself. + [self setFrameSize:CPSizeMake(CPRectGetWidth(frame) - width, CPRectGetHeight(frame))]; +} + +- (void)moveColumn:(unsigned)fromIndex toColumn:(unsinged)toIndex +{ + if (fromIndex == toIndex) + return; +// FIXME: IMPLEMENT +} + +- (CPArray)tableColumns +{ + return _tableColumns; +} + +// Getting the dimensions of the table + +- (int)numberOfColumns +{ + return _numberOfColumns; +} + +- (int)numberOfRows +{ + return _numberOfRows; +} + +- (void)tile +{ + var HEIGHT = 10.0; + + [_headerView setFrame:CPRectMake(0.0, 0.0, CPRectGetWidth([self bounds]), HEIGHT)]; + [_scrollView setFrame:CPRectMake(0.0, HEIGHT, CPRectGetWidth([self bounds]), CPRectGetHeight([self bounds]) - HEIGHT)]; +} + +- (void)setDataSource:(id)aDataSource +{ + _dataSource = aDataSource; + + [self reloadData]; +} + +- (id)dataSource +{ + return _dataSource; +} + +- (void)setFrameSize:(CPSize)aSize +{ + var oldColumnHeight = [self columnHeight]; + + [super setFrameSize:aSize]; + + var columnHeight = [self columnHeight]; + + if (columnHeight != oldColumnHeight) + { + var i = 0; + + for (; i < _numberOfColumns; ++i) + [_tableColumnViews[i] setFrameSize:CPSizeMake([_tableColumns[i] width], columnHeight)]; + } + + [self tile]; +} + +- (void)noteNumberOfRowsChanged +{ + var numberOfRows = [_dataSource numberOfRowsInTableView:self]; + + if (_numberOfRows != numberOfRows) + { + _numberOfRows = numberOfRows; + [self sizeToFit]; + } +} + +- (CPRect)rectOfRow:(int)aRowIndex +{ + return CPRectMake(0.0, aRowIndex * (_rowHeight + _intercellSpacing.height), CPRectGetWidth([self bounds]), _rowHeight); +} + +- (CPRect)rectOfColumn:(int)aColumnIndex +{ + return CPRectCreateCopy([_tableColumnViews[aColumnIndex] frame]); +} + +- (void)sizeToFit +{ + [self tile]; +} + +- (void)reloadData +{ + _numberOfRows = [_dataSource numberOfRowsInTableView:self]; + + [self loadTableCellsInRect:[self bounds]]; +} + +@end diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j new file mode 100644 index 000000000..67064bb9e --- /dev/null +++ b/AppKit/CPTextField.j @@ -0,0 +1,419 @@ +/* + * CPTextField.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPControl.j" +import "CPStringDrawing.j" + +#include "Platform/Platform.h" +#include "Platform/DOM/CPDOMDisplayServer.h" + + +CPLineBreakByWordWrapping = 0, +CPLineBreakByCharWrapping = 1, +CPLineBreakByClipping = 2, +CPLineBreakByTruncatingHead = 3, +CPLineBreakByTruncatingTail = 4, +CPLineBreakByTruncatingMiddle = 5; + +CPTextFieldSquareBezel = 0; +CPTextFieldRoundedBezel = 1; + +var TOP_PADDING = 4.0, + BOTTOM_PADDING = 3.0; + HORIZONTAL_PADDING = 3.0; + +#if PLATFORM(DOM) +var CPTextFieldDOMInputElement = nil; +#endif + +var _CPTextFieldSquareBezelColor = nil; + +@implementation CPString (CPTextFieldAdditions) + +- (CPString)string +{ + return self; +} + +@end + +@implementation CPTextField : CPControl +{ + BOOL _isBordered; + BOOL _isBezeled; + CPTextFieldBezelStyle _bezelStyle; + + BOOL _isEditable; + BOOL _isSelectable; + + id _value; + + CPLineBreakMode _lineBreakMode; +#if PLATFORM(DOM) + DOMElement _DOMTextElement; +#endif +} + +#if PLATFORM(DOM) ++ (DOMElement)_inputElement +{ + if (!CPTextFieldDOMInputElement) + { + CPTextFieldDOMInputElement = document.createElement("input"); + CPTextFieldDOMInputElement.style.position = "absolute"; + CPTextFieldDOMInputElement.style.top = "0px"; + CPTextFieldDOMInputElement.style.left = "0px"; + CPTextFieldDOMInputElement.style.width = "100%" + CPTextFieldDOMInputElement.style.height = "100%"; + CPTextFieldDOMInputElement.style.border = "0px"; + CPTextFieldDOMInputElement.style.padding = "0px"; + CPTextFieldDOMInputElement.style.whiteSpace = "pre"; + CPTextFieldDOMInputElement.style.background = "transparent"; + CPTextFieldDOMInputElement.style.outline = "none"; + CPTextFieldDOMInputElement.style.paddingLeft = HORIZONTAL_PADDING - 1.0 + "px"; + CPTextFieldDOMInputElement.style.paddingTop = TOP_PADDING - 2.0 + "px"; + } + + return CPTextFieldDOMInputElement; +} +#endif + +- (id)initWithFrame:(CPRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _value = @""; + +#if PLATFORM(DOM) + _DOMTextElement = document.createElement("div"); + _DOMTextElement.style.position = "absolute"; + _DOMTextElement.style.top = TOP_PADDING + "px"; + _DOMTextElement.style.left = HORIZONTAL_PADDING + "px"; + _DOMTextElement.style.width = MAX(0.0, CGRectGetWidth(aFrame) - 2.0 * HORIZONTAL_PADDING) + "px"; + _DOMTextElement.style.height = MAX(0.0, CGRectGetHeight(aFrame) - TOP_PADDING - BOTTOM_PADDING) + "px"; + _DOMTextElement.style.whiteSpace = "pre"; + _DOMTextElement.style.cursor = "default"; + _DOMTextElement.style.zIndex = 100; + + _DOMElement.appendChild(_DOMTextElement); +#endif + [self setAlignment:CPLeftTextAlignment]; + } + + return self; +} + +// Setting the Bezel Style + +- (void)setBezeled:(BOOL)shouldBeBezeled +{ + if (_isBezeled == shouldBeBezeled) + return; + + _isBezeled = shouldBeBezeled; + + [self _updateBackground]; +} + +- (BOOL)isBezeled +{ + return _isBezeled; +} + +- (void)setBezelStyle:(CPTextFieldBezelStyle)aBezelStyle +{ + if (_bezelStyle == aBezelStyle) + return; + + _bezelStyle = aBezelStyle; + + [self _updateBackground]; +} + +- (CPTextFieldBezelStyle)bezelStyle +{ + return _bezelStyle; +} + +- (void)setBordered:(BOOL)shouldBeBordered +{ + if (_isBordered == shouldBeBordered) + return; + + _isBordered = shouldBeBordered; + + [self _updateBackground]; +} + +- (BOOL)isBordered +{ + return _isBordered; +} + +- (void)_updateBackground +{ + if (_isBordered && _bezelStyle == CPTextFieldSquareBezel && _isBezeled) + { + if (!_CPTextFieldSquareBezelColor) + { + var bundle = [CPBundle bundleForClass:[CPTextField class]]; + + _CPTextFieldSquareBezelColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices: + [ + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTextField/CPTextFieldBezelSquare0.png"] size:CGSizeMake(2.0, 3.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTextField/CPTextFieldBezelSquare1.png"] size:CGSizeMake(1.0, 3.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTextField/CPTextFieldBezelSquare2.png"] size:CGSizeMake(2.0, 3.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTextField/CPTextFieldBezelSquare3.png"] size:CGSizeMake(2.0, 1.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTextField/CPTextFieldBezelSquare4.png"] size:CGSizeMake(1.0, 1.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTextField/CPTextFieldBezelSquare5.png"] size:CGSizeMake(2.0, 1.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTextField/CPTextFieldBezelSquare6.png"] size:CGSizeMake(2.0, 2.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTextField/CPTextFieldBezelSquare7.png"] size:CGSizeMake(1.0, 2.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPTextField/CPTextFieldBezelSquare8.png"] size:CGSizeMake(2.0, 2.0)] + ]]]; + } + + [self setBackgroundColor:_CPTextFieldSquareBezelColor]; + } + else + [self setBackgroundColor:nil]; +} + +- (BOOL)acceptsFirstResponder +{ + return _isEditable; +} + +- (BOOL)becomeFirstResponder +{ + var string = [self stringValue]; + + [self setStringValue:@""]; + + var element = [[self class] _inputElement]; + + element.value = string; + element.style.color = _DOMElement.style.color; + element.style.font = _DOMElement.style.font; + element.style.zIndex = 1000; + element.style.width = CGRectGetWidth([self bounds]) - 3.0 + "px"; +// element.style.left = _DOMTextElement.style.left; +// element.style.top = _DOMTextElement.style.top; + + _DOMElement.appendChild(element); + window.setTimeout(function() { element.focus(); }, 0.0); +// element.onblur = function() { objj_debug_print_backtrace(); } + //element.select(); + + element.onkeypress = function(aDOMEvent) + { + aDOMEvent = aDOMEvent || window.event; + + if (aDOMEvent.keyCode == 13) + { + if(aDOMEvent.preventDefault) + aDOMEvent.preventDefault(); + else if(aDOMEvent.stopPropagation) + aDOMEvent.stopPropagation(); + + element.blur(); + + [self sendAction:[self action] to:[self target]]; + [[self window] makeFirstResponder:nil]; + } + }; + + [[CPDOMWindowBridge sharedDOMWindowBridge] _propagateCurrentDOMEvent:YES]; + + return YES; +} + +- (BOOL)resignFirstResponder +{ + var element = [[self class] _inputElement]; + + _DOMElement.removeChild(element); + [self setStringValue:element.value]; + + return YES; +} + +- (void)setEditable:(BOOL)shouldBeEditable +{ + _isEditable = shouldBeEditable; +} + +- (BOOL)isEditable +{ + return _isEditable; +} + +- (void)setFrameSize:(CGSize)aSize +{ + [super setFrameSize:aSize]; + + CPDOMDisplayServerSetStyleSize(_DOMTextElement, _frame.size.width - 2.0 * HORIZONTAL_PADDING, _frame.size.height - TOP_PADDING - BOTTOM_PADDING); +} + +- (BOOL)isSelectable +{ + return _isSelectable; +} + +- (void)setSelectable:(BOOL)aFlag +{ + _isSelectable = aFlag; +} + +- (void)setAlignment:(int)anAlignment +{ + if ([self alignment] == anAlignment) + return; + + [super setAlignment:anAlignment]; + +#if PLATFORM(DOM) + switch ([self alignment]) + { + case CPLeftTextAlignment: _DOMTextElement.style.textAlign = "left"; + break; + case CPRightTextAlignment: _DOMTextElement.style.textAlign = "right"; + break; + case CPCenterTextAlignment: _DOMTextElement.style.textAlign = "center"; + break; + case CPJustifiedTextAlignment: _DOMTextElement.style.textAlign = "justify"; + break; + case CPNaturalTextAlignment: _DOMTextElement.style.textAlign = ""; + break; + } +#endif +} + +- (void)setLineBreakMode:(CPLineBreakMode)aLineBreakMode +{ + _lineBreakMode = aLineBreakMode; + +#if PLATFORM(DOM) + switch (aLineBreakMode) + { + case CPLineBreakByTruncatingTail: _DOMTextElement.style.textOverflow = "ellipsis"; + _DOMTextElement.style.whiteSpace = "nowrap"; + _DOMTextElement.style.overflow = "hidden"; + break; + + case CPLineBreakByWordWrapping: _DOMTextElement.style.whiteSpace = "normal"; + _DOMTextElement.style.overflow = "hidden"; + _DOMTextElement.style.textOverflow = "clip"; + break; + } +#endif +} + +- (CPString)stringValue +{ + // All of this needs to be better. +#if PLATFORM(DOM) + if ([[self window] firstResponder] == self) + return [[self class] _inputElement].value; +#endif + + return [_value string]; +} + +- (void)setStringValue:(CPString)aStringValue +{ + _value = aStringValue; + +#if PLATFORM(DOM) + var cssString = _value ? [_value cssString] : @""; + + if (CPFeatureIsCompatible(CPJavascriptInnerTextFeature)) + _DOMTextElement.innerText = cssString; + else if (CPFeatureIsCompatible(CPJavascriptTextContentFeature)) + _DOMTextElement.textContent = cssString; +#endif +} + +- (void)sizeToFit +{ +#if PLATFORM(DOM) + var size = [_value ? _value : @" " sizeWithFont:[self font]]; + + [self setFrameSize:CGSizeMake(size.width + 2 * HORIZONTAL_PADDING, size.height + TOP_PADDING + BOTTOM_PADDING)]; +#endif +} + +@end + +var CPTextFieldIsSelectableKey = @"CPTextFieldIsSelectableKey", + CPTextFieldLineBreakModeKey = @"CPTextFieldLineBreakModeKey", + CPTextFieldStringValueKey = @"CPTextFieldStringValueKey"; + +@implementation CPTextField (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ +#if PLATFORM(DOM) + _DOMTextElement = document.createElement("div"); +#endif + + self = [super initWithCoder:aCoder]; + + if (self) + { + var bounds = [self bounds]; + + _value = @""; + +#if PLATFORM(DOM) + _DOMTextElement.style.position = "absolute"; + _DOMTextElement.style.top = TOP_PADDING + "px"; + _DOMTextElement.style.left = HORIZONTAL_PADDING + "px"; + _DOMTextElement.style.width = MAX(0.0, CGRectGetWidth(bounds) - 2.0 * HORIZONTAL_PADDING) + "px"; + _DOMTextElement.style.height = MAX(0.0, CGRectGetHeight(bounds) - TOP_PADDING - BOTTOM_PADDING) + "px"; + _DOMTextElement.style.whiteSpace = "pre"; + _DOMTextElement.style.cursor = "default"; + + _DOMElement.appendChild(_DOMTextElement); +#endif + + [self setSelectable:[aCoder decodeBoolForKey:CPTextFieldIsSelectableKey]]; + [self setLineBreakMode:[aCoder decodeIntForKey:CPTextFieldLineBreakModeKey]]; + + [self setStringValue:[aCoder decodeObjectForKey:CPTextFieldStringValueKey]]; + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [super encodeWithCoder:aCoder]; + + [aCoder encodeBool:_isSelectable forKey:CPTextFieldIsSelectableKey]; + [aCoder encodeInt:_lineBreakMode forKey:CPTextFieldLineBreakModeKey]; + + [aCoder encodeObject:_value forKey:CPTextFieldStringValueKey]; +} + +@end diff --git a/AppKit/CPToolbar.j b/AppKit/CPToolbar.j new file mode 100644 index 000000000..ba07ae10b --- /dev/null +++ b/AppKit/CPToolbar.j @@ -0,0 +1,585 @@ +/* + * CPToolbar.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + +import "CPPopUpButton.j" +import "CPToolbarItem.j" + +CPToolbarDisplayModeDefault = 0; +CPToolbarDisplayModeIconAndLabel = 1; +CPToolbarDisplayModeIconOnly = 2; +CPToolbarDisplayModeLabelOnly = 3; + +var CPToolbarsByIdentifier = nil; +var CPToolbarConfigurationsByIdentifier = nil; + +var _CPToolbarItemVisibilityPriorityCompare = function(lhs, rhs) +{ + var lhsVisibilityPriority = [lhs visibilityPriority], + rhsVisibilityPriority = [rhs visibilityPriority]; + + if (lhsVisibilityPriority == rhsVisibilityPriority) + return CPOrderedSame; + + if (lhsVisibilityPriority > rhsVisibilityPriority) + return CPOrderedAscending; + + return CPOrderedDescending; +} + +@implementation CPToolbar : CPObject +{ + CPString _identifier; + CPToolbarDisplayMode _displayMode; + BOOL _showsBaselineSeparator; + BOOL _allowsUserCustomization; + BOOL _isVisible; + BOOL _needsReloadOfItems; + + id _delegate; + CPView _toolbarView; + + CPArray _itemIdentifiers; + CPArray _allowedItemIdentifiers; + + CPArray _items; + CPArray _labels; + + CPMutableDictionary _itemIndexes; +} + ++ (void)initialize +{ + if (self != [CPToolbar class]) + return; + + CPToolbarsByIdentifier = [CPDictionary dictionary]; + CPToolbarConfigurationsByIdentifier = [CPDictionary dictionary]; +} + +- (id)initWithIdentifier:(CPString)anIdentifier +{ + self = [super init]; + + if (self) + { + _items = []; + _labels = []; + + _identifier = anIdentifier; + _isVisible = YES; + + var toolbarsSharingIdentifier = [CPToolbarsByIdentifier objectForKey:_identifier]; + + if (!toolbarsSharingIdentifier) + { + toolbarsSharingIdentifier = [] + [CPToolbarsByIdentifier setObject:toolbarsSharingIdentifier forKey:_identifier]; + } + + [toolbarsSharingIdentifier addObject:self]; + } + + return self; +} + +- (void)setDisplayMode:(CPToolbarDisplayMode)aDisplayMode +{ + +} + +- (CPString)identifier +{ + return _identifier; +} + +- (id)delegate +{ + return _delegate; +} + +- (BOOL)isVisible +{ + return _isVisible; +} + +- (void)setVisible:(BOOL)aFlag +{ + if (_isVisible == aFlag) + return; + + _isVisible = aFlag; + + [_window _setToolbarVisible:_isVisible]; + [self _reloadToolbarItems]; +} + +- (void)setDelegate:(id)aDelegate +{ + if (_delegate == aDelegate) + return; + + _delegate = aDelegate; + + // When _delegate is nil, this will be cleared out. + _itemIdentifiers = nil; + _allowedItemIdentifiers = [_delegate toolbarAllowedItemIdentifiers:self]; + + [self _reloadToolbarItems]; +} + +- (void)_loadConfiguration +{ + +} + +- (CPView)_toolbarView +{ + if (!_toolbarView) + { + _toolbarView = [[_CPToolbarView alloc] initWithFrame:CPRectMake(0.0, 0.0, 1200.0, 59.0)]; + [_toolbarView setAutoresizingMask:CPViewWidthSizable]; + + [_toolbarView setToolbar:self]; + } + + return _toolbarView; +} + +- (void)_reloadToolbarItems +{ + if (![_toolbarView superview] || !_delegate) + return; + + var count = [_itemIdentifiers count]; + + if (!count) + { + _itemIdentifiers = [[_delegate toolbarDefaultItemIdentifiers:self] mutableCopy]; + + count = [_itemIdentifiers count]; + } + + [[_toolbarView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; + + _items = []; + _labels = []; + + var index = 0; + + for (; index < count; ++index) + { + var identifier = _itemIdentifiers[index], + item = [CPToolbarItem _standardItemWithItemIdentifier:identifier]; + + if (!item) + item = [[_delegate toolbar:self itemForItemIdentifier:identifier willBeInsertedIntoToolbar:YES] copy]; + + if (item == nil) + [CPException raise:CPInvalidArgumentException + format:@"_delegate %@ returned nil toolbar item returned for identifier %@", _delegate, identifier]; + + [_items addObject:item]; + } + + // Store items sorted by priority. We want items to be removed first at the end of the array, + // items to be removed last at the front. + + _itemsSortedByVisibilityPriority = [_items sortedArrayUsingFunction:_CPToolbarItemVisibilityPriorityCompare context:NULL]; + + [_toolbarView reloadToolbarItems]; +} + +- (void)items +{ + return _items; +} + +- (CPArray)visibleItems +{ + return [_toolbarView visibleItems]; +} + +- (int)indexOfItem:(CPToolbarItem)anItem +{ + var info = [_itemIndexes objectForKey:[anItem hash]]; + + if (!info) + return CPNotFound; + + return info.index; +} + +- (CPArray)itemsSortedByVisibilityPriority +{ + return _itemsSortedByVisibilityPriority; +} + +@end + + +var _CPToolbarViewBackgroundColor = nil, + _CPToolbarViewExtraItemsImage = nil, + _CPToolbarViewExtraItemsAlternateImage = nil; + +var TOOLBAR_TOP_MARGIN = 5.0, + TOOLBAR_ITEM_MARGIN = 10.0, + TOOLBAR_EXTRA_ITEMS_WIDTH = 20.0; + +var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth) +{ + return { index:anIndex, view:aView, label:aLabel, minWidth:aMinWidth }; +} + +@implementation _CPToolbarView : CPView +{ + CPToolbar _toolbar; + + CPIndexSet _flexibleWidthIndexes; + CPIndexSet _visibleFlexibleWidthIndexes; + + CPMutableDictionary _itemInfos; + + CPArray _visibleItems; + CPArray _invisibleItems; + + CPPopUpButton _additionalItemsButton; +} + ++ (void)initialize +{ + if (self != [_CPToolbarView class]) + return; + + var bundle = [CPBundle bundleForClass:self]; + + _CPToolbarViewBackgroundColor = [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"_CPToolbarView/_CPToolbarViewBackground.png"] size:CGSizeMake(1.0, 59.0)]]; + + _CPToolbarViewExtraItemsImage = [[CPImage alloc] initWithContentsOfFile: [bundle pathForResource:"_CPToolbarView/_CPToolbarViewExtraItemsImage.png"] size: CPSizeMake(10.0, 15.0)]; + + _CPToolbarViewExtraItemsAlternateImage = [[CPImage alloc] initWithContentsOfFile: [bundle pathForResource:"_CPToolbarView/_CPToolbarViewExtraItemsAlternateImage.png"] size:CGSizeMake(10.0, 15.0)]; +} + +- (id)initWithFrame:(CGRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _minWidth = 0; + + [self setBackgroundColor:_CPToolbarViewBackgroundColor]; + + _additionalItemsButton = [[CPPopUpButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 10.0, 15.0) pullsDown:YES]; + + [_additionalItemsButton setImagePosition:CPImageOnly]; + [[_additionalItemsButton menu] setShowsStateColumn:NO]; + + [_additionalItemsButton setAlternateImage:_CPToolbarViewExtraItemsAlternateImage]; + } + + return self; +} + +- (void)setToolbar:(CPToolbar)aToolbar +{ + _toolbar = aToolbar; +} + +- (CPToolbar)toolbar +{ + return _toolbar; +} + +// This *should* be roughly O(3N) = O(N) +- (void)resizeSubviewsWithOldSize:(CGSize)aSize +{ + [self layoutSubviews]; +} + +- (void)layoutSubviews +{ + // We begin by recalculating the visible items. + var items = [_toolbar items], + width = CGRectGetWidth([self bounds]), + minWidth = _minWidth, + flexibleItemIndexes = [CPIndexSet indexSet], + // FIXME: This should be a CPSet. + invisibleItemsSortedByPriority = []; + + _visibleItems = items; + + // We only have hidden items if our actual width is smaller than our + // minimum width for hiding items. + if (width < minWidth) + { + width -= TOOLBAR_EXTRA_ITEMS_WIDTH; + + _visibleItems = [_visibleItems copy]; + + var itemsSortedByVisibilityPriority = [_toolbar itemsSortedByVisibilityPriority], + count = itemsSortedByVisibilityPriority.length; + + // While our items take up too much space... + while (minWidth > width) + { + var item = itemsSortedByVisibilityPriority[count--]; + + minWidth -= [self minWidthForItem:item] + TOOLBAR_ITEM_MARGIN; + + [_visibleItems removeObjectIdenticalTo:item]; + [invisibleItemsSortedByPriority addObject:item]; + + [[self viewForItem:item] setHidden:YES]; + [[self labelForItem:item] setHidden:YES]; + } + } + + // Determine all the items that have flexible width. + var index = _visibleItems.length; + + while (index--) + { + var item = _visibleItems[index]; + + if ([item minSize].width != [item maxSize].width) + [flexibleItemIndexes addIndex:index]; + + [[self viewForItem:item] setHidden:NO]; + [[self labelForItem:item] setHidden:NO]; + } + + var remainingSpace = width - minWidth, + proportionate = 0.0; + + // Continue to dstribute space proportionately while we have it, + // and there are flexible items left that want it. (Those with max + // widths may eventually not want it anymore). + while (remainingSpace && [flexibleItemIndexes count]) + { + // Divy out the space. + proportionate += remainingSpace / [flexibleItemIndexes count]; + + // Reset the remaining space to 0 + remainingSpace = 0.0; + + var index = CPNotFound; + + while ((index = [flexibleItemIndexes indexGreaterThanIndex:index]) != CPNotFound) + { + var item = _visibleItems[index]; + view = [self viewForItem:item], + frame = [view frame], + proposedWidth = [item minSize].width + proportionate, + constrainedWidth = MIN(proposedWidth, [item maxSize].width); + + if (constrainedWidth < proposedWidth) + { + [flexibleItemIndexes removeIndex:index]; + + remainingSpace += proposedWidth - constrainedWidth; + } + + [view setFrameSize:CGSizeMake(constrainedWidth, CGRectGetHeight(frame))]; + } + } + + // Now that all the visible items are the correct width, position them accordingly. + var count = _visibleItems.length, + x = TOOLBAR_ITEM_MARGIN; + + for (index = 0; index < count; ++index) + { + var item = _visibleItems[index], + view = [self viewForItem:item], + + viewFrame = [view frame], + viewWidth = CGRectGetWidth(viewFrame), + + label = [self labelForItem:item], + labelFrame = [label frame], + labelWidth = CGRectGetWidth(labelFrame), + + itemWidth = MAX([self minWidthForItem:item], viewWidth); + + [view setFrameOrigin:CGPointMake(x + (itemWidth - viewWidth) / 2.0, TOOLBAR_TOP_MARGIN)]; + [label setFrameOrigin:CGPointMake(x + (itemWidth - labelWidth) / 2.0, TOOLBAR_TOP_MARGIN + CGRectGetHeight(viewFrame))]; + + x += itemWidth + TOOLBAR_ITEM_MARGIN; + } + + if ([invisibleItemsSortedByPriority count]) + { + var index = 0, + count = [items count]; + + _invisibleItems = []; + + for (; index < count; ++index) + { + var item = items[index]; + + if ([invisibleItemsSortedByPriority indexOfObjectIdenticalTo:item] != CPNotFound) + [_invisibleItems addObject:item]; + } + + [_additionalItemsButton setFrameOrigin:CGPointMake(width + 5.0, (CGRectGetHeight([self bounds]) - CGRectGetHeight([_additionalItemsButton frame])) / 2.0)]; + + [self addSubview:_additionalItemsButton]; + + [_additionalItemsButton removeAllItems]; + + var index = 0, + count = [_invisibleItems count]; + + [_additionalItemsButton addItemWithTitle:@"Additional Items"]; + [[_additionalItemsButton itemArray][0] setImage:_CPToolbarViewExtraItemsImage]; + + for (; index < count; ++index) + { + var item = _invisibleItems[index]; + + [_additionalItemsButton addItemWithTitle:[item label]]; + + var menuItem = [_additionalItemsButton itemArray][index + 1]; + + [menuItem setImage:[item image]]; + + [menuItem setTarget:[item target]]; + [menuItem setAction:[item action]]; + } + } + else + [_additionalItemsButton removeFromSuperview]; + +} + +- (int)indexOfItem:(CPToolbarItem)anItem +{ + var info = [_itemInfos objectForKey:[anItem hash]]; + + if (!info) + return CPNotFound; + + return info.index; +} + +- (CPView)viewForItem:(CPToolbarItem)anItem +{ + var info = [_itemInfos objectForKey:[anItem hash]]; + + if (!info) + return nil; + + return info.view; +} + +- (CPTextField)labelForItem:(CPToolbarItem)anItem +{ + var info = [_itemInfos objectForKey:[anItem hash]]; + + if (!info) + return nil; + + return info.label; +} + +- (float)minWidthForItem:(CPToolbarItem)anItem +{ + var info = [_itemInfos objectForKey:[anItem hash]]; + + if (!info) + return 0; + + return info.minWidth; +} + +- (void)reloadToolbarItems +{ + // Get rid of all our current subviews. + var subviews = [self subviews], + count = subviews.length; + + while (count--) + [subviews removeObjectAtIndex:count]; + + // Populate with new subviews. + var items = [_toolbar items], + index = 0; + + count = items.length; + + _itemInfos = [CPDictionary dictionary]; + _minWidth = TOOLBAR_ITEM_MARGIN; + + for (; index < count; ++index) + { + var item = items[index], + view = [item view]; + + // If this item doesn't have a custom view, create a standard one. + if (!view) + { + view = [[CPButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 32.0, 32.0)]; + + [view setBordered:NO]; + + [view setImage:[item image]]; + [view setAlternateImage:[item alternateImage]]; + + [view setTarget:[item target]]; + [view setAction:[item action]]; + + [view setImagePosition:CPImageOnly]; + } + + [self addSubview:view]; + + // Create a lable for this item. + var label = [[CPTextField alloc] initWithFrame:CGRectMakeZero()]; + + [label setStringValue:[item label]]; + [label setFont:[CPFont systemFontOfSize:11.0]]; + [label sizeToFit]; + + [label setTarget:[item target]]; + [label setAction:[item action]]; + + [self addSubview:label]; + + var minSize = [item minSize], + minWidth = MAX(minSize.width, CGRectGetWidth([label frame])); + + [_itemInfos setObject:_CPToolbarItemInfoMake(index, view, label, minWidth) forKey:[item hash]]; + + _minWidth += minWidth + TOOLBAR_ITEM_MARGIN; + + // If the minSize is different than the maxSize, then this item has flexible width. + //if (minSize.width != [item maxSize].width) + // [_flexibleWidthIndexes addIndex:index]; + } + + [self layoutSubviews]; +} + +@end diff --git a/AppKit/CPToolbarItem.j b/AppKit/CPToolbarItem.j new file mode 100644 index 000000000..1a3dc9926 --- /dev/null +++ b/AppKit/CPToolbarItem.j @@ -0,0 +1,300 @@ +/* + * CPToolbarItem.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import + +import +import + + +CPToolbarItemVisibilityPriorityStandard = 0; +CPToolbarItemVisibilityPriorityLow = -1000; +CPToolbarItemVisibilityPriorityHigh = 1000; +CPToolbarItemVisibilityPriorityUser = 2000; + +CPToolbarSeparatorItemIdentifier = @"CPToolbarSeparatorItemIdentifier"; +CPToolbarSpaceItemIdentifier = @"CPToolbarSpaceItemIdentifier"; +CPToolbarFlexibleSpaceItemIdentifier = @"CPToolbarFlexibleSpaceItemIdentifier"; +CPToolbarShowColorsItemIdentifier = @"CPToolbarShowColorsItemIdentifier"; +CPToolbarShowFontsItemIdentifier = @"CPToolbarShowFontsItemIdentifier"; +CPToolbarCustomizeToolbarItemIdentifier = @"CPToolbarCustomizeToolbarItemIdentifier"; +CPToolbarPrintItemIdentifier = @"CPToolbarPrintItemIdentifier"; + +@implementation CPToolbarItem : CPObject +{ + CPString _itemIdentifier; + + CPToolbar _toolbar; + + CPString _label; + CPString _paletteLabel; + CPString _toolTip; + int _tag; + id _target; + SEL _action; + BOOL _isEnabled; + CPImage _image; + CPImage _alternateImage; + CPView _view; + CGSize _minSize; + CGSize _maxSize; + + int _visibilityPriority; +} + +// Creating a Toolbar Item + +- (id)initWithItemIdentifier:(CPString)anItemIdentifier +{ + self = [super init]; + + if (self) + { + _itemIdentifier = anItemIdentifier; + + _minSize = CGSizeMakeZero(); + _maxSize = CGSizeMakeZero(); + + _visibilityPriority = CPToolbarItemVisibilityPriorityStandard; + } + + return self; +} + +// Managing Attributes + +- (CPString)itemIdentifier +{ + return _itemIdentifier; +} + +- (CPToolbar)toolbar +{ + return _toolbar; +} + +- (CPString)label +{ + return _label; +} + +- (void)setLabel:(CPString)aLabel +{ + _label = aLabel; +} + +- (CPString)paletteLabel +{ + return _paletteLabel; +} + +- (void)setPaletteLabel:(CPString)aPaletteLabel +{ + _paletteLabel = aPaletteLabel; +} + +- (CPString)toolTip +{ + return _toolTip; +} + +- (void)setToolTip:(CPString)aToolTip +{ + _toolTip = aToolTip; +} + +- (int)tag +{ + return _tag; +} + +- (void)setTag:(int)aTag +{ + _tag = aTag; +} + +- (id)target +{ + return _target; +} + +- (void)setTarget:(id)aTarget +{ + _target = aTarget; + + [_view setTarget:aTarget]; +} + +- (SEL)action +{ + return _action; +} + +- (void)setAction:(SEL)anAction +{ + _action = anAction; + + [_view setAction:anAction]; +} + +- (BOOL)isEnabled +{ + return _isEnabled; +} + +- (void)setEnabled:(BOOL)aFlag +{ + _isEnabled = aFlag; +} + +- (CPImage)image +{ + return _image; +} + +- (void)setImage:(CPImage)anImage +{ + _image = anImage; + + [_view setImage:anImage]; +} + +- (void)setAlternateImage:(CPImage)anImage +{ + _alternateImage = anImage; + + [_view setAlternateImage:anImage]; +} + +- (CPImage)alternateImage +{ + return _alternateImage; +} + +- (CPView)view +{ + return _view; +} + +- (void)setView:(CPView)aView +{ + _view = aView; +} + +- (CGSize)minSize +{ + return _minSize; +} + +- (void)setMinSize:(CGSize)aMinSize +{ + _minSize = CGSizeCreateCopy(aMinSize); +} + +- (CGSize)maxSize +{ + return _maxSize; +} + +- (void)setMaxSize:(CGSize)aMaxSize +{ + _maxSize = CGSizeCreateCopy(aMaxSize); +} + +// Visibility Priority + +- (int)visibilityPriority +{ + return _visibilityPriority; +} + +- (void)setVisibilityPriority:(int)aVisibilityPriority +{ + _visibilityPriority = aVisibilityPriority; +} + +@end + +@implementation CPToolbarItem (CPCopying) + +- (id)copy +{ + var copy = [[[self class] alloc] initWithItemIdentifier:_itemIdentifier]; + + [copy setLabel:_label]; + [copy setPaletteLabel:_paletteLabel]; + [copy setToolTip:_toolTip]; + + [copy setTag:_tag]; + [copy setTarget:_target]; + [copy setAction:_action]; + + [copy setEnabled:_isEnabled]; + [copy setImage:_image]; + [copy setAlternateImage:_alternateImage]; + + if (_view) + [copy setView:[CPKeyedUnarchiver unarchiveObjectWithData:[CPKeyedArchiver archivedDataWithRootObject:_view]]]; + + [copy setMinSize:_minSize]; + [copy setMaxSize:_maxSize]; + + [copy setVisibilityPriority:_visibilityPriority]; + + return copy; +} + +@end + +// Standard toolbar identifiers + +@implementation CPToolbarItem (Standard) + ++ (CPToolbarItem)_standardItemWithItemIdentifier:(CPString)anItemIdentifier +{ + var item = [[CPToolbarItem alloc] initWithItemIdentifier:anItemIdentifier]; + + switch (anItemIdentifier) + { + case CPToolbarSeparatorItemIdentifier: return nil; + + case CPToolbarSpaceItemIdentifier: [item setMinSize:CGSizeMake(32.0, 32.0)]; + [item setMaxSize:CGSizeMake(32.0, 32.0)]; + + return item; + + case CPToolbarFlexibleSpaceItemIdentifier: [item setMinSize:CGSizeMake(32.0, 32.0)]; + [item setMaxSize:CGSizeMake(10000.0, 32.0)]; + + return item; + + case CPToolbarShowColorsItemIdentifier: return nil; + case CPToolbarShowFontsItemIdentifier: return nil; + case CPToolbarCustomizeToolbarItemIdentifier: return nil; + case CPToolbarPrintItemIdentifier: return nil; + } + + return nil; +} + +@end diff --git a/AppKit/CPView.j b/AppKit/CPView.j new file mode 100644 index 000000000..51cf412de --- /dev/null +++ b/AppKit/CPView.j @@ -0,0 +1,1380 @@ +/* + * CPView.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import + +import "CGAffineTransform.j" +import "CGGeometry.j" + +import "CPColor.j" +import "CPDOMDisplayServer.j" +import "CPGeometry.j" +import "CPResponder.j" +import "CPGraphicsContext.j" + +#include "Platform/Platform.h" +#include "CoreGraphics/CGAffineTransform.h" +#include "CoreGraphics/CGGeometry.h" +#include "Platform/DOM/CPDOMDisplayServer.h" + + +CPViewNotSizable = 0; +CPViewMinXMargin = 1; +CPViewWidthSizable = 2; +CPViewMaxXMargin = 4; +CPViewMinYMargin = 8; +CPViewHeightSizable = 16; +CPViewMaxYMargin = 32; + +CPViewBoundsDidChangeNotification = @"CPViewBoundsDidChangeNotification"; +CPViewFrameDidChangeNotification = @"CPViewFrameDidChangeNotification"; + +var _DOMOriginUpdateMask = 1 << 0, + _DOMSizeUpdateMask = 1 << 1; + +var _CPViewNotificationCenter = nil; + +#if PLATFORM(DOM) +var DOMCanvasElementZIndex = -1, + DOMBackgroundElementZIndex = -2, + DOMElementPrototype = nil, + + BackgroundTrivialColor = 0, + BackgroundVerticalThreePartImage = 1, + BackgroundHorizontalThreePartImage = 2, + BackgroundNinePartImage = 3; +#endif + +@implementation CPView : CPResponder +{ + CPWindow _window; + + CPView _superview; + CPArray _subviews; + + CPGraphicsContext _graphicsContext; + + CGRect _frame; + CGRect _bounds; + CGAffineTransform _boundsTransform; + CGAffineTransform _inverseBoundsTransform; + + CPArray _registeredDraggedTypes; + + BOOL _isHidden; + BOOL _hitTests; + + BOOL _postsFrameChangedNotifications; + BOOL _postsBoundsChangedNotifications; + BOOL _inhibitFrameAndBoundsChangedNotifications; + + CPString _displayHash; + +#if PLATFORM(DOM) + DOMElement _DOMElement; + CPArray _DOMImageParts; + CPArray _DOMImageSizes; + + unsigned _backgroundType; + + DOMElement _DOMGraphicsElement; +#endif + + float _opacity; + CPColor _backgroundColor; + + BOOL _autoresizesSubviews; + unsigned _autoresizingMask; + + CALayer _layer; + BOOL _wantsLayer; + + // Full Screen State + BOOL _isInFullScreenMode; + + _CPViewFullScreenModeState _fullScreenModeState; +} + ++ (void)initialize +{ + if (self != [CPView class]) + return; + +#if PLATFORM(DOM) + DOMElementPrototype = document.createElement("div"); + + var style = DOMElementPrototype.style; + + style.overflow = "hidden"; + style.position = "absolute"; + style.visibility = "visible"; + style.zIndex = 0; +#endif + + _CPViewNotificationCenter = [CPNotificationCenter defaultCenter]; +} + +- (id)initWithFrame:(CPRect)aFrame +{ + self = [super init]; + + if (self) + { + var width = _CGRectGetWidth(aFrame), + height = _CGRectGetHeight(aFrame); + + _subviews = []; + + _frame = _CGRectMakeCopy(aFrame); + _bounds = _CGRectMake(0.0, 0.0, width, height); + + _registeredDraggedTypes = []; + + _autoresizingMask = CPViewNotSizable; + _autoresizesSubviews = YES; + + _opacity = 1.0; + _isHidden = NO; + _hitTests = YES; + + _displayHash = [self hash]; + +#if PLATFORM(DOM) + _DOMElement = DOMElementPrototype.cloneNode(false); + + CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, _CGRectGetMinX(aFrame), _CGRectGetMinY(aFrame)); + CPDOMDisplayServerSetStyleSize(_DOMElement, width, height); + + _DOMImageParts = []; + _DOMImageSizes = []; +#endif + } + + return self; +} + +- (CPView)superview +{ + return _superview; +} + +- (CPArray)subviews +{ + return _subviews; +} + +- (CPWindow)window +{ + return _window; +} + +- (void)addSubview:(CPView)aSubview +{ + [self _insertSubview:aSubview atIndex:CPNotFound]; +} + +- (void)addSubview:(CPView)aSubview positioned:(CPWindowOrderingMode)anOrderingMode relativeTo:(CPView)anotherView +{ + var index = anotherView ? [_subviews indexOfObjectIdenticalTo:anotherView] : CPNotFound; + + // In other words, if no view, then either all the way at the bottom or all the way at the top. + if (index == CPNotFound) + index = (anOrderingMode == CPWindowAbove) ? [_subviews count] : 0; + + // else, if we have a view, above if above. + else if (anOrderingMode == CPWindowAbove) + ++index; + + [self _insertSubview:aSubview atIndex:index]; +} + +- (void)_insertSubview:(CPView)aSubview atIndex:(int)anIndex +{ + // We will have to adjust the z-index of all views starting at this index. + var count = _subviews.length; + + // If this is already one of our subviews, remove it. + if (aSubview._superview == self) + { + var index = [_subviews indexOfObjectIdenticalTo:aSubview]; + + if (index == anIndex || index == count - 1 && anIndex == count) + return; + + [_subviews removeObjectAtIndex:index]; + +#if PLATFORM(DOM) + CPDOMDisplayServerRemoveChild(_DOMElement, aSubview._DOMElement); +#endif + + if (anIndex > index) + --anIndex; + } + else + { + // Remove the view from its previous superview. + [aSubview removeFromSuperview]; + + // Set the subview's window to our own. + [aSubview _setWindow:_window]; + + // Notify the subview that it will be moving. + [aSubview viewWillMoveToSuperview:self]; + + // Set ourselves as the superview. + aSubview._superview = self; + } + + if (anIndex == CPNotFound || anIndex >= count) + { + _subviews.push(aSubview); + +#if PLATFORM(DOM) + // Attach the actual node. + CPDOMDisplayServerAppendChild(_DOMElement, aSubview._DOMElement); +#endif + } + else + { + _subviews.splice(anIndex, 0, aSubview); + +#if PLATFORM(DOM) + // Attach the actual node. + CPDOMDisplayServerInsertBefore(_DOMElement, aSubview._DOMElement, _subviews[anIndex + 1]._DOMElement); +#endif + } + + [aSubview setNextResponder:self]; + [aSubview viewDidMoveToSuperview]; + + [self didAddSubview:aSubview]; +} + +- (void)didAddSubview:(CPView)aSubview +{ +} + +- (void)removeFromSuperview +{ + if (!_superview) + return; + + [_superview willRemoveSubview:self]; + + [[_superview subviews] removeObject:self]; + +#if PLATFORM(DOM) + CPDOMDisplayServerRemoveChild(_superview._DOMElement, _DOMElement); +#endif + _superview = nil; + + [self _setWindow:nil]; +} + +- (void)replaceSubview:(CPView)aSubview with:(CPView)aView +{ + if (aSubview._superview != self) + return; + + var index = [_subviews indexOfObjectIdenticalTo:aSubview]; + + [aSubview removeFromSuperview]; + + [aView _insertSubview:aView atIndex:index]; +} + +- (void)_setWindow:(CPWindow)aWindow +{ + // FIXME: check _window == aWindow? If not, comment why! + if ([_window firstResponder] == self) + [_window makeFirstResponder:nil]; + + // Notify the view and its subviews + [self viewWillMoveToWindow:aWindow]; + [_subviews makeObjectsPerformSelector:@selector(_setWindow:) withObject:aWindow]; + + _window = aWindow; + + [self viewDidMoveToWindow]; +} + +- (BOOL)isDescendantOf:(CPView)aView +{ + var view = self; + + do + { + if (view == aView) + return YES; + } while(view = [view superview]) + + return NO; +} + +- (void)viewDidMoveToSuperview +{ + if (_graphicsContext) + [self setNeedsDisplay:YES]; +} + +- (void)viewDidMoveToWindow +{ +} + +- (void)viewWillMoveToSuperview:(CPView)aView +{ +} + +- (void)viewWillMoveToWindow:(CPWindow)aWindow +{ +} + +- (void)willRemoveSubview:(CPView)aView +{ +} + +- (CPMenuItem)enclosingMenuItem +{ + var view = self; + + while (![view isKindOfClass:[_CPMenuItemView class]]) + view = [view superview]; + + if (view) + return view._menuItem; + + return nil; +/* var view = self, + enclosingMenuItem = _enclosingMenuItem; + + while (!enclosingMenuItem && (view = view._enclosingMenuItem)) + view = [view superview]; + + return enclosingMenuItem;*/ +} + +- (BOOL)isFlipped +{ + return YES; +} + +- (void)setFrame:(CPRect)aFrame +{ + if (_CGRectEqualToRect(_frame, aFrame)) + return; + + _inhibitFrameAndBoundsChangedNotifications = YES; + + [self setFrameOrigin:aFrame.origin]; + [self setFrameSize:aFrame.size]; + + _inhibitFrameAndBoundsChangedNotifications = NO; + + if (_postsFrameChangedNotifications) + [_CPViewNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; +} + +- (CGRect)frame +{ + return _CGRectMakeCopy(_frame); +} + +- (void)setFrameOrigin:(CPPoint)aPoint +{ + var origin = _frame.origin; + + if (!aPoint || _CGPointEqualToPoint(origin, aPoint)) + return; + + origin.x = aPoint.x; + origin.y = aPoint.y; + + if (_postsFrameChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications) + [_CPViewNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; + +#if PLATFORM(DOM) + CPDOMDisplayServerSetStyleLeftTop(_DOMElement, _superview ? _superview._boundsTransform : NULL, origin.x, origin.y); +#endif +} + +- (void)setFrameSize:(CGSize)aSize +{ + var size = _frame.size; + + if (!aSize || _CGSizeEqualToSize(size, aSize)) + return; + + var oldSize = _CGSizeMakeCopy(size); + + size.width = aSize.width; + size.height = aSize.height; + + if (YES) + { + _bounds.size.width = aSize.width; + _bounds.size.height = aSize.height; + } + + if (_postsFrameChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications) + [_CPViewNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; + + if (_layer) + [_layer _owningViewBoundsChanged]; + + if (_autoresizesSubviews) + [self resizeSubviewsWithOldSize:oldSize]; + +#if PLATFORM(DOM) + CPDOMDisplayServerSetStyleSize(_DOMElement, size.width, size.height); + + if (_backgroundType == BackgroundTrivialColor) + return; + + var images = [[_backgroundColor patternImage] imageSlices]; + + if (_backgroundType == BackgroundVerticalThreePartImage) + { + CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], size.width, size.height - _DOMImageSizes[0].height - _DOMImageSizes[2].height); + } + + else if (_backgroundType == BackgroundHorizontalThreePartImage) + { + CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], size.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width, size.height); + } + + else if (_backgroundType == BackgroundNinePartImage) + { + var width = size.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width, + height = size.height - _DOMImageSizes[0].height - _DOMImageSizes[6].height; + + CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], width, _DOMImageSizes[0].height); + CPDOMDisplayServerSetStyleSize(_DOMImageParts[3], _DOMImageSizes[3].width, height); + CPDOMDisplayServerSetStyleSize(_DOMImageParts[4], width, height); + CPDOMDisplayServerSetStyleSize(_DOMImageParts[5], _DOMImageSizes[5].width, height); + CPDOMDisplayServerSetStyleSize(_DOMImageParts[7], width, _DOMImageSizes[7].height); + } +#endif +} + +- (void)setBounds:(CGRect)bounds +{ + if (_CGRectEqualToRect(_bounds, bounds)) + return; + + _inhibitFrameAndBoundsChangedNotifications = YES; + + [self setBoundsOrigin:bounds.origin]; + [self setBoundsSize:bounds.size]; + + _inhibitFrameAndBoundsChangedNotifications = NO; + + if (_postsBoundsChangedNotifications) + [_CPViewNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; +} + +- (CGRect)bounds +{ + return _CGRectMakeCopy(_bounds); +} + +- (void)setBoundsOrigin:(CGPoint)aPoint +{ + var origin = _bounds.origin; + + if (_CGPointEqualToPoint(origin, aPoint)) + return; + + origin.x = aPoint.x; + origin.y = aPoint.y; + + if (origin.x != 0 || origin.y != 0) + { + _boundsTransform = _CGAffineTransformMakeTranslation(-origin.x, -origin.y); + _inverseBoundsTransform = CGAffineTransformInvert(_boundsTransform); + } + else + { + _boundsTransform = nil; + _inverseBoundsTransform = nil; + } + +#if PLATFORM(DOM) + var index = _subviews.length; + + while (index--) + { + var view = _subviews[index], + origin = view._frame.origin; + + CPDOMDisplayServerSetStyleLeftTop(view._DOMElement, _boundsTransform, origin.x, origin.y); + } +#endif + + if (_postsBoundsChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications) + [_CPViewNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; +} + +- (void)setBoundsSize:(CGSize)aSize +{ + var size = _bounds.size; + + if (_CGSizeEqualToSize(size, aSize)) + return; + + var frameSize = _frame.size; + + if (!_CGSizeEqualToSize(size, frameSize)) + { + var origin = _bounds.origin; + + origin.x /= size.width / frameSize.width; + origin.y /= size.height / frameSize.height; + } + + size.width = aSize.width; + size.height = aSize.height; + + if (!_CGSizeEqualToSize(size, frameSize)) + { + var origin = _bounds.origin; + + origin.x *= size.width / frameSize.width; + origin.y *= size.height / frameSize.height; + } + + if (_postsBoundsChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications) + [_CPViewNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; +} + +- (void)resizeWithOldSuperviewSize:(CPSize)aSize +{ + var mask = _autoresizingMask; + + if(mask == CPViewNotSizable) + return; + + var frame = _superview._frame, + newFrame = _CGRectMakeCopy(_frame), + dX = (_CGRectGetWidth(frame) - aSize.width) / + (((mask & CPViewMinXMargin) ? 1 : 0) + (mask & CPViewWidthSizable ? 1 : 0) + (mask & CPViewMaxXMargin ? 1 : 0)), + dY = (_CGRectGetHeight(frame) - aSize.height) / + ((mask & CPViewMinYMargin ? 1 : 0) + (mask & CPViewHeightSizable ? 1 : 0) + (mask & CPViewMaxYMargin ? 1 : 0)); + + if (mask & CPViewMinXMargin) + newFrame.origin.x += dX; + if (mask & CPViewWidthSizable) + newFrame.size.width += dX; + + if (mask & CPViewMinYMargin) + newFrame.origin.y += dY; + if (mask & CPViewHeightSizable) + newFrame.size.height += dY; + + [self setFrame:newFrame]; +} + +- (void)resizeSubviewsWithOldSize:(CPSize)aSize +{ + var count = _subviews.length; + + while (count--) + [_subviews[count] resizeWithOldSuperviewSize:aSize]; +} + +- (void)setAutoresizesSubviews:(BOOL)aFlag +{ + _autoresizesSubviews = aFlag; +} + +- (BOOL)autoresizesSubviews +{ + return _autoresizesSubviews; +} + +- (void)setAutoresizingMask:(unsigned)aMask +{ + _autoresizingMask = aMask; +} + +- (unsigned)autoresizingMask +{ + return _autoresizingMask; +} + +// Fullscreen Mode + +- (BOOL)enterFullScreenMode:(CPScreen)aScreen withOptions:(CPDictionary)options +{ + _fullScreenModeState = _CPViewFullScreenModeStateMake(self); + + var fullScreenWindow = [[CPWindow alloc] initWithContentRect:[[CPDOMWindowBridge sharedDOMWindowBridge] contentBounds] styleMask:CPBorderlessWindowMask]; + + [fullScreenWindow setLevel:CPScreenSaverWindowLevel]; + [fullScreenWindow setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; + + var contentView = [fullScreenWindow contentView]; + + [contentView setBackgroundColor:[CPColor blackColor]]; + [contentView addSubview:self]; + + [self setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; + [self setFrame:CGRectMakeCopy([contentView bounds])]; + + [fullScreenWindow makeKeyAndOrderFront:self]; + + [fullScreenWindow makeFirstResponder:self]; + + _isInFullScreenMode = YES; + + return YES; +} + +- (void)exitFullScreenModeWithOptions:(CPDictionary)options +{ + if (!_isInFullScreenMode) + return; + + _isInFullScreenMode = NO; + + [self setFrame:_fullScreenModeState.frame]; + [self setAutoresizingMask:_fullScreenModeState.autoresizingMask]; + [_fullScreenModeState.superview _insertSubview:self atIndex:_fullScreenModeState.index]; + + [[self window] orderOut:self]; +} + +- (BOOL)isInFullScreenMode +{ + return _isInFullScreenMode; +} + +- (void)setHidden:(BOOL)aFlag +{ + if(_isHidden == aFlag) + return; +// FIXME: Should we return to visibility? This breaks in FireFox, Opera, and IE. +// _DOMElement.style.visibility = (_isHidden = aFlag) ? "hidden" : "visible"; + _isHidden = aFlag; +#if PLATFORM(DOM) + _DOMElement.style.display = _isHidden ? "none" : "block"; +#endif +} + +- (BOOL)isHidden +{ + return _isHidden; +} + +- (void)setAlphaValue:(float)anAlphaValue +{ + if (_opacity == anAlphaValue) + return; + + _opacity = anAlphaValue; + +#if PLATFORM(DOM) + _DOMElement.style.opacity = anAlphaValue; + + if (anAlphaValue == 1.0) + try { _DOMElement.style.removeAttribute("filter") } catch (anException) { } + else + _DOMElement.style.filter = "alpha(opacity=" + anAlphaValue * 100 + ")"; +#endif +} + +- (float)alphaValue +{ + return _opacity; +} + +- (void)setOpacity:(float)anOpacity +{ + [self setAlphaValue:anOpacity]; +} + +- (float)opacity +{ + return _opacity; +} + +- (BOOL)isHiddenOrHasHiddenAncestor +{ + var view = self; + + while (![view isHidden]) + view = [view superview]; + + return view != nil; +} + +- (BOOL)acceptsFirstMouse:(CPEvent)anEvent +{ + return YES; +} + +- (BOOL)hitTests +{ + return YES; +} + +- (void)setHitTests:(BOOL)shouldHitTest +{ + _hitTests = shouldHitTest; +} + +- (CPView)hitTest:(CPPoint)aPoint +{ + if(_isHidden || !_hitTests || !CPRectContainsPoint(_frame, aPoint)) + return nil; + + var view = nil, + i = _subviews.length, + adjustedPoint = _CGPointMake(aPoint.x - _CGRectGetMinX(_frame), aPoint.y - _CGRectGetMinY(_frame)); + + if (_inverseBoundsTransform) + adjustedPoint = _CGPointApplyAffineTransform(adjustedPoint, _inverseBoundsTransform); + + while (i--) + if (view = [_subviews[i] hitTest:adjustedPoint]) + return view; + + return self; +} + +- (BOOL)mouseDownCanMoveWindow +{ + return ![self isOpaque]; +} + +- (void)mouseDown:(CPEvent)anEvent +{ + if ([self mouseDownCanMoveWindow]) + [super mouseDown:anEvent]; +} + +- (void)setBackgroundColor:(CPColor)aColor +{ + if (_backgroundColor == aColor) + return; + + _backgroundColor = aColor; + +#if PLATFORM(DOM) + var patternImage = [_backgroundColor patternImage], + amount = 0; + + if ([patternImage isThreePartImage]) + { + _backgroundType = [patternImage isVertical] ? BackgroundVerticalThreePartImage : BackgroundHorizontalThreePartImage; + + amount = 3 - _DOMImageParts.length; + } + else if ([patternImage isNinePartImage]) + { + _backgroundType = BackgroundNinePartImage; + + amount = 9 - _DOMImageParts.length; + } + else + { + _backgroundType = BackgroundTrivialColor; + + amount = 0 - _DOMImageParts.length; + } + + if (amount > 0) + while (amount--) + { + var DOMElement = DOMElementPrototype.cloneNode(false); + + DOMElement.style.zIndex = -1000; + + _DOMImageParts.push(DOMElement); + _DOMElement.appendChild(DOMElement); + } + else + { + amount = -amount; + + while (amount--) + _DOMElement.removeChild(_DOMImageParts.pop()); + } + + if (_backgroundType == BackgroundTrivialColor) + + // Opera doesn't like DOM properties set to nil. + // https://trac.280north.com/ticket/7 + _DOMElement.style.background = _backgroundColor ? [_backgroundColor cssString] : ""; + + else + { + var slices = [patternImage imageSlices], + count = slices.length, + frameSize = _frame.size; + + while (count--) + { + var image = slices[count], + size = _DOMImageSizes[count] = image ? [image size] : _CGSizeMakeZero(); + + CPDOMDisplayServerSetStyleSize(_DOMImageParts[count], size.width, size.height); + + _DOMImageParts[count].style.background = image ? "url(\"" + [image filename] + "\")" : ""; + } + + if (_backgroundType == BackgroundNinePartImage) + { + var width = frameSize.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width, + height = frameSize.height - _DOMImageSizes[0].height - _DOMImageSizes[6].height; + + CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], width, _DOMImageSizes[0].height); + CPDOMDisplayServerSetStyleSize(_DOMImageParts[3], _DOMImageSizes[3].width, height); + CPDOMDisplayServerSetStyleSize(_DOMImageParts[4], width, height); + CPDOMDisplayServerSetStyleSize(_DOMImageParts[5], _DOMImageSizes[5].width, height); + CPDOMDisplayServerSetStyleSize(_DOMImageParts[7], width, _DOMImageSizes[7].height); + + CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[0], NULL, 0.0, 0.0); + CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[1], NULL, _DOMImageSizes[0].width, 0.0); + CPDOMDisplayServerSetStyleRightTop(_DOMImageParts[2], NULL, 0.0, 0.0); + CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[3], NULL, 0.0, _DOMImageSizes[1].height); + CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[4], NULL, _DOMImageSizes[0].width, _DOMImageSizes[0].height); + CPDOMDisplayServerSetStyleRightTop(_DOMImageParts[5], NULL, 0.0, _DOMImageSizes[1].height); + CPDOMDisplayServerSetStyleLeftBottom(_DOMImageParts[6], NULL, 0.0, 0.0); + CPDOMDisplayServerSetStyleLeftBottom(_DOMImageParts[7], NULL, _DOMImageSizes[6].width, 0.0); + CPDOMDisplayServerSetStyleRightBottom(_DOMImageParts[8], NULL, 0.0, 0.0); + } + else if (_backgroundType == BackgroundVerticalThreePartImage) + { + CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], frameSize.width, frameSize.height - _DOMImageSizes[0].height - _DOMImageSizes[2].height); + + CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[0], NULL, 0.0, 0.0); + CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[1], NULL, 0.0, _DOMImageSizes[0].height); + CPDOMDisplayServerSetStyleLeftBottom(_DOMImageParts[2], NULL, 0.0, 0.0); + } + else if (_backgroundType == BackgroundHorizontalThreePartImage) + { + CPDOMDisplayServerSetStyleSize(_DOMImageParts[1], frameSize.width - _DOMImageSizes[0].width - _DOMImageSizes[2].width, frameSize.height); + + CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[0], NULL, 0.0, 0.0); + CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[1], NULL, _DOMImageSizes[0].width, 0.0); + CPDOMDisplayServerSetStyleRightTop(_DOMImageParts[2], NULL, 0.0, 0.0); + } + } +#endif +} + +- (CPColor)backgroundColor +{ + return _backgroundColor; +} + +// Converting Coordinates + +- (CGPoint)convertPoint:(CGPoint)aPoint fromView:(CPView)aView +{ + return CGPointApplyAffineTransform(aPoint, _CPViewGetTransform(aView, self)); +} + +- (CGPoint)convertPoint:(CGPoint)aPoint toView:(CPView)aView +{ + return CGPointApplyAffineTransform(aPoint, _CPViewGetTransform(self, aView)); +} + +- (CGSize)convertSize:(CGSize)aSize fromView:(CPView)aView +{ + return CGSizeApplyAffineTransform(aSize, _CPViewGetTransform(aView, self)); +} + +- (CGSize)convertSize:(CGSize)aSize toView:(CPView)aView +{ + return CGSizeApplyAffineTransform(aSize, _CPViewGetTransform(self, aView)); +} + +- (CGRect)convertRect:(CGRect)aRect fromView:(CPView)aView +{ + return CGRectApplyAffineTransform(aRect, _CPViewGetTransform(aView, self)); +} + +- (CGRect)convertRect:(CGRect)aRect toView:(CPView)aView +{ + return CGRectApplyAffineTransform(aRect, _CPViewGetTransform(self, aView)); +} + +- (void)setPostsFrameChangedNotifications:(BOOL)shouldPostFrameChangedNotifications +{ + if (_postsFrameChangedNotifications == shouldPostFrameChangedNotifications) + return; + + _postsFrameChangedNotifications = shouldPostFrameChangedNotifications; + + if (_postsFrameChangedNotifications) + [_CPViewNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self]; +} + +- (BOOL)postsFrameChangedNotifications +{ + return _postsFrameChangedNotifications; +} + +- (void)setPostsBoundsChangedNotifications:(BOOL)shouldPostBoundsChangedNotifications +{ + if (_postsBoundsChangedNotifications == shouldPostBoundsChangedNotifications) + return; + + _postsBoundsChangedNotifications = shouldPostBoundsChangedNotifications; + + if (_postsBoundsChangedNotifications) + [_CPViewNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self]; +} + +- (BOOL)postsBoundsChangedNotifications +{ + return _postsBoundsChangedNotifications; +} + +- (void)dragImage:(CPImage)anImage at:(CPPoint)aLocation offset:(CPSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack +{ + [_window dragImage:anImage at:[self convertPoint:aLocation toView:nil] offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack]; +} + +- (void)dragView:(CPView)aView at:(CPPoint)aLocation offset:(CPSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack +{ + [_window dragView:aView at:[self convertPoint:aLocation toView:nil] offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack]; +} + +- (void)registerForDraggedTypes:(CPArray)pasteboardTypes +{ + _registeredDraggedTypes = [pasteboardTypes copy]; +} + +- (CPArray)registeredDraggedTypes +{ + return _registeredDraggedTypes; +} + +- (void)unregisterDraggedTypes +{ + _registeredDraggedTypes = nil; +} + +// + +- (void)drawRect:(CPRect)aRect +{ + +} + +// Focus + +- (void)lockFocus +{ + // If we don't yet have a graphics context, then we must first create a + // canvas element, then use its 2d context. + if (!_graphicsContext) + { + var context = CGBitmapGraphicsContextCreate(); + +#if PLATFORM(DOM) + _DOMGraphicsElement = context.DOMElement; + + _DOMGraphicsElement.style.position = "absolute"; + _DOMGraphicsElement.style.top = "0px"; + _DOMGraphicsElement.style.left = "0px"; + _DOMGraphicsElement.style.zIndex = DOMCanvasElementZIndex; + + _DOMGraphicsElement.width = CPRectGetWidth(_frame); + _DOMGraphicsElement.height = CPRectGetHeight(_frame); + + _DOMGraphicsElement.style.width = CPRectGetWidth(_frame) + "px"; + _DOMGraphicsElement.style.height = CPRectGetHeight(_frame) + "px"; + + _DOMElement.appendChild(_DOMGraphicsElement); +#endif + _graphicsContext = [CPGraphicsContext graphicsContextWithGraphicsPort:context flipped:YES]; + } + + [CPGraphicsContext setCurrentContext:_graphicsContext]; + + CGContextSaveGState([_graphicsContext graphicsPort]); +} + +- (void)unlockFocus +{ + var graphicsPort = [_graphicsContext graphicsPort]; + + CGContextRestoreGState(graphicsPort); + + [CPGraphicsContext setCurrentContext:nil]; +} + +// Displaying + +- (void)setNeedsDisplay:(BOOL)aFlag +{ + if (aFlag) + [self display]; +} + +- (void)setNeedsDisplayInRect:(CPRect)aRect +{ + [self displayRect:aRect]; +} + +- (void)displayIfNeeded +{ +} + +- (void)display +{ + [self displayRect:_bounds]; +} + +- (void)displayRect:(CPRect)aRect +{ + [self lockFocus]; + [self drawRect:aRect]; + [self unlockFocus]; +} + +- (BOOL)isOpaque +{ + return NO; +} + +- (CGRect)visibleRect +{ + if (!_superview) + return _bounds; + + return CGRectIntersection([self convertRect:[_superview visibleRect] fromView:_superview], _bounds); +} + +// Scrolling + +- (CPScrollView)_enclosingClipView +{ + var superview = _superview, + clipViewClass = [CPClipView class]; + + while(superview && ![superview isKindOfClass:clipViewClass]) + superview = superview._superview; + + return superview; +} + +- (void)scrollPoint:(CGPoint)aPoint +{ + var clipView = [self _enclosingClipView]; + + if (!clipView) + return; + + [clipView scrollToPoint:[self convertPoint:aPoint toView:clipView]]; +} + +- (BOOL)scrollRectToVisible:(CGRect)aRect +{ + var visibleRect = [self visibleRect]; + + // Make sure we have a rect that exists. + aRect = CGRectIntersection(aRect, _bounds); + + // If aRect is empty or is already visible then no scrolling required. + if (_CGRectIsEmpty(aRect) || CGRectContainsRect(visibleRect, aRect)) + return NO; + + var enclosingClipView = [self _enclosingClipView]; + + // If we're not in a clip view, then there isn't much we can do. + if (!enclosingClipView) + return NO; + + var scrollPoint = _CGPointMakeCopy(visibleRect.origin); + + // One of the following has to be true since our current visible rect didn't contain aRect. + if (_CGRectGetMinX(aRect) <= _CGRectGetMinX(visibleRect)) + scrollPoint.x = _CGRectGetMinX(aRect); + else if (_CGRectGetMaxX(aRect) > _CGRectGetMaxX(visibleRect)) + scrollPoint.x += _CGRectGetMaxX(aRect) - _CGRectGetMaxX(visibleRect); + + if (_CGRectGetMinY(aRect) <= _CGRectGetMinY(visibleRect)) + scrollPoint.y = CGRectGetMinY(aRect); + else if (_CGRectGetMaxY(aRect) > _CGRectGetMaxY(visibleRect)) + scrollPoint.y += _CGRectGetMaxY(aRect) - _CGRectGetMaxY(visibleRect); + + [enclosingClipView scrollToPoint:CGPointMake(scrollPoint.x, scrollPoint.y)]; + + return YES; +} + +- (BOOL)autoscroll:(CPEvent)anEvent +{ + // FIXME: Implement. + return NO; +} + +- (CGRect)adjustScroll:(CGRect)proposedVisibleRect +{ + return proposedVisibleRect; +} + +- (void)scrollRect:(CGRect)aRect by:(float)anAmount +{ + +} + +- (CPScrollView)enclosingScrollView +{ + var superview = _superview, + scrollViewClass = [CPScrollView class]; + + while(superview && ![superview isKindOfClass:scrollViewClass]) + superview = superview._superview; + + return superview; +} + +- (void)scrollClipView:(CPClipView)aClipView toPoint:(CGPoint)aPoint +{ + [aClipView scrollToPoint:aPoint]; +} + +- (void)reflectScrolledClipView:(CPClipView)aClipView +{ +} + +@end + +@implementation CPView (CoreAnimationAdditions) + +- (void)setLayer:(CALayer)aLayer +{ + if (_layer == aLayer) + return; + + if (_layer) + { + _layer._owningView = nil; +#if PLATFORM(DOM) + _DOMElement.removeChild(_layer._DOMElement); +#endif + } + + _layer = aLayer; + + if (_layer) + { + var bounds = CGRectMakeCopy([self bounds]); + + [_layer _setOwningView:self]; + +#if PLATFORM(DOM) + _layer._DOMElement.style.zIndex = 100; + + _DOMElement.appendChild(_layer._DOMElement); +#endif + } +} + +- (CALayer)layer +{ + return _layer; +} + +- (void)setWantsLayer:(BOOL)aFlag +{ + _wantsLayer = aFlag; +} + +- (CALayer)wantsLayer +{ + return _wantsLayer; +} + +@end + +var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", + CPViewAutoresizesSubviewsKey = @"CPViewAutoresizesSubviews", + CPViewBackgroundColorKey = @"CPViewBackgroundColor", + CPViewBoundsKey = @"CPViewBoundsKey", + CPViewFrameKey = @"CPViewFrameKey", + CPViewHitTestsKey = @"CPViewHitTestsKey", + CPViewIsHiddenKey = @"CPViewIsHiddenKey", + CPViewOpacityKey = @"CPViewOpacityKey", + CPViewSubviewsKey = @"CPViewSubviewsKey", + CPViewSuperviewKey = @"CPViewSuperviewKey", + CPViewWindowKey = @"CPViewWindowKey"; + +@implementation CPView (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + // We create the DOMElement "early" because there is a change that we + // will decode our superview before we are done decoding, at which point + // we have to have an element to place in the tree. Perhaps there is + // a more "elegant" way to do this...? +#if PLATFORM(DOM) + _DOMElement = DOMElementPrototype.cloneNode(false); +#endif + + self = [super initWithCoder:aCoder]; + + if (self) + { + _frame = [aCoder decodeRectForKey:CPViewFrameKey]; + _bounds = [aCoder decodeRectForKey:CPViewBoundsKey]; + + _window = [aCoder decodeObjectForKey:CPViewWindowKey]; + _subviews = [aCoder decodeObjectForKey:CPViewSubviewsKey]; + _superview = [aCoder decodeObjectForKey:CPViewSuperviewKey]; + + _autoresizingMask = [aCoder decodeIntForKey:CPViewAutoresizingMaskKey]; + _autoresizesSubviews = [aCoder decodeBoolForKey:CPViewAutoresizesSubviewsKey]; + + _hitTests = [aCoder decodeObjectForKey:CPViewHitTestsKey]; + _isHidden = [aCoder decodeObjectForKey:CPViewIsHiddenKey]; + _opacity = [aCoder decodeIntForKey:CPViewOpacityKey]; + + // DOM SETUP +#if PLATFORM(DOM) + _DOMImageParts = []; + _DOMImageSizes = []; + + CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, _CGRectGetMinX(_frame), _CGRectGetMinY(_frame)); + CPDOMDisplayServerSetStyleSize(_DOMElement, _CGRectGetWidth(_frame), _CGRectGetHeight(_frame)); + + var index = 0, + count = _subviews.length; + + for (; index < count; ++index) + { + CPDOMDisplayServerAppendChild(_DOMElement, _subviews[index]._DOMElement); + } +#endif + _displayHash = [self hash]; + + [self setBackgroundColor:[aCoder decodeObjectForKey:CPViewBackgroundColorKey]]; + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [super encodeWithCoder:aCoder]; + + [aCoder encodeRect:_frame forKey:CPViewFrameKey]; + [aCoder encodeRect:_bounds forKey:CPViewBoundsKey]; + + [aCoder encodeConditionalObject:_window forKey:CPViewWindowKey]; + [aCoder encodeObject:_subviews forKey:CPViewSubviewsKey]; + [aCoder encodeConditionalObject:_superview forKey:CPViewSuperviewKey]; + + [aCoder encodeInt:_autoresizingMask forKey:CPViewAutoresizingMaskKey]; + [aCoder encodeBool:_autoresizesSubviews forKey:CPViewAutoresizesSubviewsKey]; + + [aCoder encodeObject:_backgroundColor forKey:CPViewBackgroundColorKey]; + + [aCoder encodeBool:_hitTests forKey:CPViewHitTestsKey]; + [aCoder encodeBool:_isHidden forKey:CPViewIsHiddenKey]; + [aCoder encodeFloat:_opacity forKey:CPViewOpacityKey]; +} + +@end + +var _CPViewFullScreenModeStateMake = function(aView) +{ + var superview = aView._superview; + + return { autoresizingMask:aView._autoresizingMask, frame:CGRectMakeCopy(aView._frame), index:(superview ? [superview._subviews indexOfObjectIdenticalTo:aView] : 0), superview:superview }; +} + +var _CPViewGetTransform = function(/*CPView*/ fromView, /*CPView */ toView) +{ + var transform = CGAffineTransformMakeIdentity(); + + if (fromView) + { + var view = fromView; + + // If we have a fromView, "climb up" the view tree until + // we hit the root node or we hit the toLayer. + while (view && view != toView) + { + var frame = view._frame; + + transform.tx += _CGRectGetMinX(frame); + transform.ty += _CGRectGetMinY(frame); + + if (view._boundsTransform) + { + _CGAffineTransformConcatTo(transform, view._boundsTransform, transform); + } + + view = view._superview; + } + + // If we hit toView, then we're done. + if (view == toView) + return transform; + } + + // FIXME: For now we can do things this way, but eventually we need to do them the "hard" way. + var view = toView; + + while (view) + { + var frame = view._frame; + + transform.tx -= _CGRectGetMinX(frame); + transform.ty -= _CGRectGetMinY(frame); + + if (view._boundsTransform) + { + _CGAffineTransformConcatTo(transform, view._inverseBoundsTransform, transform); + } + + view = view._superview; + } + +/* var views = [], + view = toView; + + while (view) + { + views.push(view); + view = view._superview; + } + + var index = views.length; + + while (index--) + { + var frame = views[index]._frame; + + transform.tx -= _CGRectGetMinX(frame); + transform.ty -= _CGRectGetMinY(frame); + }*/ + + return transform; +} diff --git a/AppKit/CPWindow.j b/AppKit/CPWindow.j new file mode 100644 index 000000000..e639b12f4 --- /dev/null +++ b/AppKit/CPWindow.j @@ -0,0 +1,1259 @@ +/* + * CPWindow.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import + +import "CGGeometry.j" +import "CPAnimation.j" +import "CPResponder.j" + +#include "Platform/Platform.h" +#include "Platform/DOM/CPDOMDisplayServer.h" + +#include "CoreGraphics/CGGeometry.h" + + +CPBorderlessWindowMask = 0; +CPTitledWindowMask = 1 << 0; +CPClosableWindowMask = 1 << 1; +CPMiniaturizableWindowMask = 1 << 2; +CPResizableWindowMask = 1 << 3; +CPTexturedBackgroundWindowMask = 1 << 8; + +CPBorderlessBridgeWindowMask = 1 << 20; +CPHUDBackgroundWindowMask = 1 << 21; + +CPWindowNotSizable = 0; +CPWindowMinXMargin = 1; +CPWindowWidthSizable = 2; +CPWindowMaxXMargin = 4; +CPWindowMinYMargin = 8; +CPWindowHeightSizable = 16; +CPWindowMaxYMargin = 32; + +CPNormalWindowLevel = 4; +CPFloatingWindowLevel = 5; +CPSubmenuWindowLevel = 6; +CPTornOffMenuWindowLevel = 6; +CPMainMenuWindowLevel = 8; +CPStatusWindowLevel = 9; +CPModalPanelWindowLevel = 10; +CPPopUpMenuWindowLevel = 11; +CPDraggingWindowLevel = 12; +CPScreenSaverWindowLevel = 13; + +CPWindowOut = 0; +CPWindowAbove = 1; +CPWindowBelow = 2; + +CPWindowWillCloseNotification = @"CPWindowWillCloseNotification"; +CPWindowDidBecomeMainNotification = @"CPWindowDidBecomeMainNotification"; +CPWindowDidResignMainNotification = @"CPWindowDidResignMainNotification"; + + +var SHADOW_MARGIN_LEFT = 20.0, + SHADOW_MARGIN_RIGHT = 19.0, + SHADOW_MARGIN_TOP = 10.0, + SHADOW_MARGIN_BOTTOM = 10.0, + SHADOW_DISTANCE = 5.0, + + _CPWindowShadowColor = nil; + +var CPWindowSaveImage = nil, + CPWindowSavingImage = nil; + +@implementation CPWindow : CPResponder +{ + int _windowNumber; + unsigned _styleMask; + CGRect _frame; + int _level; + BOOL _isVisible; + BOOL _isAnimating; + BOOL _hasShadow; + BOOL _isMovableByWindowBackground; + + BOOL _isDocumentEdited; + BOOL _isDocumentSaving; + + CPNinePartImageView _shadowView; + + CPView _windowView; + CPView _contentView; + CPView _toolbarView; + + CPView _mouseOverView; + CPView _leftMouseDownView; + CPView _rightMouseDownView; + + CPToolbar _toolbar; + CPResponder _firstResponder; + id _delegate; + + CPString _title; + + BOOL _acceptsMouseMovedEvents; + + CPWindowController _windowController; + + CGSize _minSize; + CGSize _maxSize; + + CGRect _resizeFrame; + CGPoint _mouseDraggedPoint; + + CPUndoManager _undoManager; + CPURL _representedURL; + + // Bridge Support + DOMElement _DOMElement; + CPDOMWindowBridge _bridge; + unsigned _autoresizingMask; + + BOOL _delegateRespondsToWindowWillReturnUndoManagerSelector; +} + ++ (void)initialize +{ + if (self != [CPWindow class]) + return; + + var bundle = [CPBundle bundleForClass:[CPWindow class]]; + + CPWindowResizeIndicatorImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindowResizeIndicator.png"] size:CGSizeMake(12.0, 12.0)]; + + CPWindowSavingImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif"] size:CGSizeMake(16.0, 16.0)] +} + +- (id)initWithContentRect:(CGRect)aContentRect styleMask:(unsigned int)aStyleMask +{ + return [self initWithContentRect:aContentRect styleMask:aStyleMask bridge:[CPDOMWindowBridge sharedDOMWindowBridge]]; +} + +- (id)initWithContentRect:(CGRect)aContentRect styleMask:(unsigned int)aStyleMask bridge:(CPDOMWindowBridge)aBridge +{ + self = [super init]; + + if (self) + { + // Set up our window number. + _windowNumber = [CPApp._windows count]; + CPApp._windows[_windowNumber] = self; + + _styleMask = aStyleMask; + + _frame = [self frameRectForContentRect:aContentRect]; + + _level = CPNormalWindowLevel; + _hasShadow = NO; + + _minSize = CGSizeMake(0.0, 0.0); + _maxSize = CGSizeMake(1000000.0, 1000000.0); + + if (_styleMask & CPBorderlessBridgeWindowMask) + _autoresizingMask = CPWindowWidthSizable | CPWindowHeightSizable; + + // Create our border view which is the actual root of our view hierarchy. + _windowView = [[_CPWindowView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame)) forStyleMask:_styleMask]; + + [_windowView _setWindow:self]; + [_windowView setNextResponder:self]; + + [self setMovableByWindowBackground:aStyleMask & CPHUDBackgroundWindowMask]; + + // Create a generic content view. + [self setContentView:[[CPView alloc] initWithFrame:CGRectMakeZero()]]; + + _firstResponder = self; + + _DOMElement = document.createElement("div"); + + _DOMElement.style.position = "absolute"; + _DOMElement.style.visibility = "visible"; + _DOMElement.style.zIndex = 0; + + CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, _CGRectGetMinX(_frame), _CGRectGetMinY(_frame)); + CPDOMDisplayServerSetStyleSize(_DOMElement, 1, 1); + + CPDOMDisplayServerAppendChild(_DOMElement, _windowView._DOMElement); + + [self setBridge:aBridge]; + + [self setNextResponder:CPApp]; + } + + return self; +} + +- (unsigned)styleMask +{ + return _styleMask; +} + ++ (CGRect)frameRectForContentRect:(CGRect)aContentRect styleMask:(unsigned)aStyleMask +{ + var frame = CGRectMakeCopy(aContentRect); + + return frame; +} + +- (CGRect)contentRectForFrameRect:(CGRect)aFrame +{ + // FIXME: EXTRA RECT COPY + var contentRect = CGRectMakeCopy([_windowView bounds]); + + if (_styleMask & CPHUDBackgroundWindowMask) + { + contentRect.origin.x += 7.0; + contentRect.origin.y += 30.0; + contentRect.size.width -= 14.0; + contentRect.size.height -= 40.0; + } + + else if (_styleMask & CPBorderlessBridgeWindowMask) + { + // The full width, like borderless. + } + + if ([_toolbar isVisible]) + { + var toolbarHeight = CGRectGetHeight([_toolbarView frame]); + + contentRect.origin.y += toolbarHeight; + contentRect.size.height -= toolbarHeight; + } + + return contentRect; +} + +- (CGRect)frameRectForContentRect:(CGRect)aContentRect +{ + if (_styleMask & CPBorderlessBridgeWindowMask) + return _bridge ? [_bridge visibleFrame] : CGRectMakeZero(); + + var frame = [[self class] frameRectForContentRect:aContentRect styleMask:_styleMask]; + + return frame; +} + +- (CGRect)frame +{ + return _frame; +} + +- (void)setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate +{ + if (shouldAnimate) + { + var animation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:aFrame]; + + [animation startAnimation]; + } + else + { + [self setFrameOrigin:aFrame.origin]; + [self setFrameSize:aFrame.size]; + } +} + +- (void)setFrame:(CGRect)aFrame +{ + [self setFrame:aFrame display:YES animate:NO]; +} + +- (void)setFrameOrigin:(CGPoint)anOrigin +{ + var origin = _frame.origin; + + if (_CGPointEqualToPoint(origin, anOrigin)) + return; + + origin.x = anOrigin.x; + origin.y = anOrigin.y; + +#if PLATFORM(DOM) + CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, origin.x, origin.y); +#endif +} + +- (void)setFrameSize:(CGSize)aSize +{ + aSize = _CGSizeMake(MIN(MAX(aSize.width, _minSize.width), _maxSize.width), MIN(MAX(aSize.height, _minSize.height), _maxSize.height)); + + if (_CGSizeEqualToSize(_frame.size, aSize)) + return; + + _frame.size = aSize; + + [_windowView setFrameSize:aSize]; + + if (_hasShadow) + [_shadowView setFrameSize:_CGSizeMake(SHADOW_MARGIN_LEFT + aSize.width + SHADOW_MARGIN_RIGHT, SHADOW_MARGIN_BOTTOM + aSize.height + SHADOW_MARGIN_TOP + SHADOW_DISTANCE)]; + + if (!_isAnimating && [_delegate respondsToSelector:@selector(windowDidResize:)]) + [_delegate windowDidResize:self]; +} + +- (void)trackMoveWithEvent:(CPEvent)anEvent +{ + var type = [anEvent type]; + + if (type == CPLeftMouseUp) + return; + + else if (type == CPLeftMouseDown) + _mouseDraggedPoint = [self convertBaseToBridge:[anEvent locationInWindow]]; + + else if (type == CPLeftMouseDragged) + { + var location = [self convertBaseToBridge:[anEvent locationInWindow]]; + + [self setFrameOrigin:CGPointMake(_CGRectGetMinX(_frame) + (location.x - _mouseDraggedPoint.x), _CGRectGetMinY(_frame) + (location.y - _mouseDraggedPoint.y))]; + + _mouseDraggedPoint = location; + } + + [CPApp setTarget:self selector:@selector(trackMoveWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES]; +} + +- (void)trackResizeWithEvent:(CPEvent)anEvent +{ + var location = [anEvent locationInWindow], + type = [anEvent type]; + + if (type == CPLeftMouseUp) + return; + + else if (type == CPLeftMouseDown) + _resizeFrame = CGRectMake(location.x, location.y, CGRectGetWidth(_frame), CGRectGetHeight(_frame)); + + else if (type == CPLeftMouseDragged) + [self setFrameSize:CGSizeMake(CGRectGetWidth(_resizeFrame) + location.x - CGRectGetMinX(_resizeFrame), CGRectGetHeight(_resizeFrame) + location.y - CGRectGetMinY(_resizeFrame))]; + + [CPApp setTarget:self selector:@selector(trackResizeWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES]; +} + +- (void)orderFront:(id)aSender +{ + [_bridge order:CPWindowAbove window:self relativeTo:nil]; +} + +- (void)orderBack:(id)aSender +{ + //[_bridge order:CPWindowBelow +} + +- (void)orderOut:(id)aSender +{ + if ([_delegate respondsToSelector:@selector(windowWillClose:)]) + [_delegate windowWillClose:self]; + + [_bridge order:CPWindowOut window:self relativeTo:nil]; + + if ([CPApp keyWindow] == self) + { + [self resignKeyWindow]; + + CPApp._keyWindow = nil; + } +} + +- (void)orderWindow:(CPWindowOrderingMode)aPlace relativeTo:(int)otherWindowNumber +{ + [_bridge order:aPlace window:self relativeTo:CPApp._windows[otherWindowNumber]]; +} + +- (void)setLevel:(int)aLevel +{ + _level = aLevel; +} + +- (int)level +{ + return _level; +} + +- (BOOL)isVisible +{ + return _isVisible; +} + +- (BOOL)showsResizeIndicator +{ + return [_windowView showsResizeIndicator]; +} + +- (void)setShowsResizeIndicator:(BOOL)shouldShowResizeIndicator +{ + [_windowView setShowsResizeIndicator:shouldShowResizeIndicator]; +} + +- (CGSize)resizeIndicatorOffset +{ + return _resizeIndicatorOffset; +} + +- (void)setResizeIndicatorOffset:(CGSize)aSize +{ + _resizeIndicatorOffset = CGSizeCreateCopy(aSize); + + if (_showsResizeIndicator) + { + _resizeIndicator.style.top = (CGRectGetMaxY(_windowView._frame) - 13.0 + _resizeIndicatorOffset.height) + "px"; + _resizeIndicator.style.left = (CGRectGetMaxX(_windowView._frame) - 13.0 + _resizeIndicatorOffset.width) + "px"; + } +} + +- (void)setContentView:(CPView)aView +{ + if (_contentView) + [_contentView removeFromSuperview]; + + _contentView = aView; + [_contentView setFrame:[self contentRectForFrameRect:_frame]]; + + [_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; + [_windowView addSubview:_contentView]; +} + +- (CPView)contentView +{ + return _contentView; +} + +- (void)setBackgroundColor:(CPColor)aColor +{ + [_windowView setBackgroundColor:aColor]; +} + +- (CPColor)backgroundColor +{ + return [_windowView backgroundColor]; +} + +- (void)setMinSize:(CGSize)aSize +{ + if (CGSizeEqualToSize(_minSize, aSize)) + return; + + _minSize = CGSizeCreateCopy(aSize); + + var size = CGSizeMakeCopy([self frame].size), + needsFrameChange = NO; + + if (size.width < _minSize.width) + { + size.width = _minSize.width; + needsFrameChange = YES; + } + + if (size.height < _minSize.height) + { + size.height = _minSize.height; + needsFrameChange = YES; + } + + if (needsFrameChange) + [self setFrameSize:size]; +} + +- (CGSize)minSize +{ + return _minSize; +} + +- (void)setMaxSize:(CGSize)aSize +{ + if (CGSizeEqualToSize(_maxSize, aSize)) + return; + + _maxSize = CGSizeCreateCopy(aSize); + + var size = CGSizeMakeCopy([self frame].size), + needsFrameChange = NO; + + if (size.width > _maxSize.width) + { + size.width = _maxSize.width; + needsFrameChange = YES; + } + + if (size.height > _maxSize.height) + { + size.height = _maxSize.height; + needsFrameChange = YES; + } + + if (needsFrameChange) + [self setFrameSize:size]; +} + +- (CGSize)maxSize +{ + return _maxSize; +} + +- (BOOL)hasShadow +{ + return _hasShadow; +} + +- (void)setHasShadow:(BOOL)shouldHaveShadow +{ + if (_hasShadow == shouldHaveShadow) + return; + + _hasShadow = shouldHaveShadow; + + if (_hasShadow) + { + var bounds = [_windowView bounds]; + + _shadowView = [[CPView alloc] initWithFrame:CGRectMake(-SHADOW_MARGIN_LEFT, -SHADOW_MARGIN_TOP + SHADOW_DISTANCE, + SHADOW_MARGIN_LEFT + CGRectGetWidth(bounds) + SHADOW_MARGIN_RIGHT, SHADOW_MARGIN_TOP + CGRectGetHeight(bounds) + SHADOW_MARGIN_BOTTOM)]; + + if (!_CPWindowShadowColor) + { + var bundle = [CPBundle bundleForClass:[self class]]; + + _CPWindowShadowColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices: + [ + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow0.png"] size:CGSizeMake(20.0, 19.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow1.png"] size:CGSizeMake(1.0, 19.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow2.png"] size:CGSizeMake(19.0, 19.0)], + + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow3.png"] size:CGSizeMake(20.0, 1.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow4.png"] size:CGSizeMake(1.0, 1.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow5.png"] size:CGSizeMake(19.0, 1.0)], + + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow6.png"] size:CGSizeMake(20.0, 18.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow7.png"] size:CGSizeMake(1.0, 18.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow8.png"] size:CGSizeMake(19.0, 18.0)] + ]]]; + } + + [_shadowView setBackgroundColor:_CPWindowShadowColor]; + [_shadowView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; + + CPDOMDisplayServerInsertBefore(_DOMElement, _shadowView._DOMElement, _windowView._DOMElement); + } + else + { + CPDOMDisplayServerRemoveChild(_DOMElement, _shadowView._DOMElement); + + _shadowView = nil; + } +} + +- (void)setDelegate:(id)aDelegate +{ + _delegate = aDelegate; + + _delegateRespondsToWindowWillReturnUndoManagerSelector = [_delegate respondsToSelector:@selector(windowWillReturnUndoManager:)]; + + if ([_delegate respondsToSelector:@selector(windowDidBecomeMain:)]) + [defaultCenter + addObserver:_delegate + selector:@selector(windowDidBecomeMain:) + name:CPWindowDidBecomeMainNotification + object:self]; + + if ([_delegate respondsToSelector:@selector(windowDidResignMain:)]) + [defaultCenter + addObserver:_delegate + selector:@selector(windowDidResignMain:) + name:CPWindowDidResignMainNotification + object:self]; +} + +- (id)delegate +{ + return _delegate; +} + +- (void)setWindowController:(CPWindow)aWindowController +{ + _windowController = aWindowController; +} + +- (CPWindowController)windowController +{ + return _windowController; +} + +- (void)doCommandBySelector:(SEL)aSelector +{ + if ([_delegate respondsToSelector:aSelector]) + [_delegate performSelector:aSelector]; + else + [super doCommandBySelector:aSelector]; +} + +- (BOOL)acceptsFirstResponder +{ + return YES; +} + +- (void)makeFirstResponder:(CPResponder)aResponder +{ + if (_firstResponder == aResponder) + return YES; + + if(![_firstResponder resignFirstResponder]) + return NO; + + if(!aResponder || ![aResponder acceptsFirstResponder] || ![aResponder becomeFirstResponder]) + { + _firstResponder = self; + + return NO; + } + + _firstResponder = aResponder; + + return YES; +} + +- (CPResponder)firstResponder +{ + return _firstResponder; +} + +- (BOOL)acceptsMouseMovedEvents +{ + return _acceptsMouseMovedEvents; +} + +- (void)setAcceptsMouseMovedEvents:(BOOL)shouldAcceptMouseMovedEvents +{ + _acceptsMouseMovedEvents = shouldAcceptMouseMovedEvents; +} + +// Managing Titles + +- (CPString)title +{ + return _title; +} + +- (void)setTitle:(CPString)aTitle +{ + _title = aTitle; + + [_windowView setTitle:aTitle]; + + [self _synchronizeMenuBarTitleWithWindowTitle]; +} + +- (void)setTitleWithRepresentedFilename:(CPString)aFilePath +{ + [self setRepresentedFilename:aFilePath]; + [self setTitle:[aFilePath lastPathComponent]]; +} + +- (void)setRepresentedFilename:(CPString)aFilePath +{ + // FIXME: urls vs filepaths and all. + [self setRepresentedURL:aFilePath]; +} + +- (CPString)representedFilename +{ + return _representedURL; +} + +- (void)setRepresentedURL:(CPURL)aURL +{ + _representedURL = aURL; +} + +- (CPURL)representedURL +{ + return _representedURL; +} + +// Moving + +- (void)setMovableByWindowBackground:(BOOL)shouldBeMovableByWindowBackground +{ + _isMovableByWindowBackground = shouldBeMovableByWindowBackground; +} + +- (BOOL)isMovableByWindowBackground +{ + return _isMovableByWindowBackground; +} + +- (void)center +{ + var size = [self frame].size, + bridgeSize = [_bridge contentBounds].size; + + [self setFrameOrigin:CGPointMake((bridgeSize.width - size.width) / 2.0, (bridgeSize.height - size.height) / 2.0)]; +} + +- (void)sendEvent:(CPEvent)anEvent +{ + var type = [anEvent type], + point = [anEvent locationInWindow]; + + switch (type) + { + case CPKeyUp: return [[self firstResponder] keyUp:anEvent]; + case CPKeyDown: return [[self firstResponder] keyDown:anEvent]; + + case CPScrollWheel: return [[_windowView hitTest:point] scrollWheel:anEvent]; + + case CPLeftMouseUp: if (!_leftMouseDownView) + return [[_windowView hitTest:point] mouseUp:anEvent]; + + [_leftMouseDownView mouseUp:anEvent] + + _leftMouseDownView = nil; + + return; + case CPLeftMouseDown: _leftMouseDownView = [_windowView hitTest:point]; + + if (_leftMouseDownView != _firstResponder && [_leftMouseDownView acceptsFirstResponder]) + [self makeFirstResponder:_leftMouseDownView]; + + var theWindow = [anEvent window]; + + if ([theWindow isKeyWindow] || [theWindow becomesKeyOnlyIfNeeded]) + return [_leftMouseDownView mouseDown:anEvent]; + else + { + // FIXME: delayed ordering? + [self makeKeyAndOrderFront:self]; + + if ([_leftMouseDownView acceptsFirstMouse:anEvent]) + return [_leftMouseDownView mouseDown:anEvent] + } + break; + case CPLeftMouseDragged: if (!_leftMouseDownView) + return [[_windowView hitTest:point] mouseDragged:anEvent]; + + return [_leftMouseDownView mouseDragged:anEvent]; + + case CPRightMouseUp: return [_rightMouseDownView mouseUp:anEvent]; + case CPRightMouseDown: _rightMouseDownView = [_windowView hitTest:point]; + return [_rightMouseDownView mouseDown:anEvent]; + case CPRightMouseDragged: return [_rightMouseDownView mouseDragged:anEvent]; + + case CPMouseMoved: if (!_acceptsMouseMovedEvents) + return; + + var hitTestView = [_windowView hitTest:point]; + + if (hitTestView != _mouseOverView) + { + if (_mouseOverView) + [_mouseOverView mouseExited:[CPEvent mouseEventWithType:CPMouseExited location:point + modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0]]; + + if (hitTestView) + [hitTestView mouseEntered:[CPEvent mouseEventWithType:CPMouseEntered location:point + modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0]]; + + _mouseOverView = hitTestView; + } + + [_mouseOverView mouseMoved:anEvent]; + } +} + +- (int)windowNumber +{ + return _windowNumber; +} + +- (void)becomeKeyWindow +{ + if (_firstResponder != self && [_firstResponder respondsToSelector:@selector(becomeKeyWindow)]) + [_firstResponder becomeKeyWindow]; +} + +- (BOOL)canBecomeKeyWindow +{ + return YES; +} + +- (BOOL)isKeyWindow +{ + return [CPApp keyWindow] == self; +} + +- (void)makeKeyAndOrderFront:(id)aSender +{ + [self orderFront:self]; + + [self makeKeyWindow]; + [self makeMainWindow]; +} + +- (void)makeKeyWindow +{ + if (![self canBecomeKeyWindow]) + return; + + [CPApp._keyWindow resignKeyWindow]; + + CPApp._keyWindow = self; + + [self becomeKeyWindow]; +} + +- (void)resignKeyWindow +{ + if (_firstResponder != self && [_firstResponder respondsToSelector:@selector(resignKeyWindow)]) + [_firstResponder resignKeyWindow]; + + if ([_delegate respondsToSelector:@selector(windowDidResignKey:)]) + [_delegate windowDidResignKey:self]; +} + +- (void)dragImage:(CPImage)anImage at:(CGPoint)imageLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack +{ + [[CPDragServer sharedDragServer] dragImage:anImage fromWindow:self at:[self convertBaseToBridge:imageLocation] offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack]; +} + +- (void)dragView:(CPView)aView at:(CGPoint)imageLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack +{ + [[CPDragServer sharedDragServer] dragView:aView fromWindow:self at:[self convertBaseToBridge:imageLocation] offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack]; +} + +// Accessing Editing Status + +- (void)setDocumentEdited:(BOOL)isDocumentEdited +{ + if (_isDocumentEdited == isDocumentEdited) + return; + + _isDocumentEdited = isDocumentEdited; + + [CPMenu _setMenuBarIconImageAlphaValue:_isDocumentEdited ? 0.5 : 1.0]; +} + +- (BOOL)isDocumentEdited +{ + return _isDocumentEdited; +} + +- (void)setDocumentSaving:(BOOL)isDocumentSaving +{ + if (_isDocumentSaving == isDocumentSaving) + return; + + _isDocumentSaving = isDocumentSaving; + + [self _synchronizeSaveMenuWithDocumentSaving]; + + [_windowView windowDidChangeDocumentSaving]; +} + +- (BOOL)isDocumentSaving +{ + return _isDocumentSaving; +} + +- (void)_synchronizeSaveMenuWithDocumentSaving +{ + if (![self isMainWindow]) + return; + + var mainMenu = [CPApp mainMenu], + index = [mainMenu indexOfItemWithTitle:_isDocumentSaving ? @"Save" : @"Saving..."]; + + if (index == CPNotFound) + return; + + var item = [mainMenu itemAtIndex:index]; + + if (_isDocumentSaving) + { + CPWindowSaveImage = [item image]; + + [item setTitle:@"Saving..."]; + [item setImage:CPWindowSavingImage]; + [item setEnabled:NO]; + } + else + { + [item setTitle:@"Save"]; + [item setImage:CPWindowSaveImage]; + [item setEnabled:YES]; + } +} + +// Closing Windows + +- (void)performClose:(id)aSender +{ + if ([_delegate respondsToSelector:@selector(windowShouldClose:)] && ![_delegate windowShouldClose:self] || + [self respondsToSelector:@selector(windowShouldClose:)] && ![self windowShouldClose:self]) + return; + + [self close]; +} + +- (void)close +{ + [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillCloseNotification object:self]; + + [self orderOut:nil]; +} + +// Managing Main Status + +- (BOOL)isMainWindow +{ + return [CPApp mainWindow] == self; +} + +- (BOOL)canBecomeMainWindow +{ + // FIXME: Also check if we can resize and titlebar. + if ([self isVisible]) + return YES; + + return NO; +} + +- (void)makeMainWindow +{ + if (![self canBecomeMainWindow]) + return; + + [CPApp._mainWindow resignMainWindow]; + + CPApp._mainWindow = self; + + [self becomeMainWindow]; +} + +- (void)becomeMainWindow +{ + [self _synchronizeMenuBarTitleWithWindowTitle]; + [self _synchronizeSaveMenuWithDocumentSaving]; + + [[CPNotificationCenter defaultCenter] + postNotificationName:CPWindowDidBecomeMainNotification + object:self]; +} + +- (void)resignMainWindow +{ + [[CPNotificationCenter defaultCenter] + postNotificationName:CPWindowDidResignMainNotification + object:self]; +} + +// Managing Toolbars + +- (CPToolbar)toolbar +{ + return _toolbar; +} + +- (void)setToolbar:(CPView)aToolbar +{ + if (_toolbar == aToolbar) + return; + + // Cleanup old toolbar + if (_toolbar) + { + [self _setToolbarVisible:NO]; + + _toolbar._window = nil; + _toolbarView = nil; + } + + if (_toolbar = aToolbar) + { + // Set up new toolbar + _toolbar = aToolbar; + _toolbar._window = self; + + if ([_toolbar isVisible]) + [self _setToolbarVisible:YES]; + + [_toolbar _reloadToolbarItems]; + } +} + +- (void)_setToolbarVisible:(BOOL)aFlag +{ + if (aFlag) + { + if (!_toolbarView) + _toolbarView = [_toolbar _toolbarView]; + + [_toolbarView setFrame:CGRectMake(0.0, 0.0, CGRectGetWidth([_windowView bounds]), CGRectGetHeight([_toolbarView frame]))]; + [_windowView addSubview:_toolbarView]; + } + else + [_toolbarView removeFromSuperview]; + + [_contentView setFrame:[self contentRectForFrameRect:[_windowView bounds]]]; +} + +// Managing Sheets + +- (void)_setAttachedSheetFrameOrigin +{ + // Position the sheet above the contentRect. + var contentRect = [[self contentView] frame], + sheetFrame = CGRectMakeCopy([_attachedSheet frame]); + + sheetFrame.origin.y = CGRectGetMinY(_frame) + CGRectGetMinY(contentRect); + sheetFrame.origin.x = CGRectGetMinX(_frame) + FLOOR((CGRectGetWidth(_frame) - CGRectGetWidth(sheetFrame)) / 2.0); + + [_attachedSheet setFrameOrigin:sheetFrame.origin]; +} + +- (void)_animateAttachedSheet +{ +/* NSWindow *sheet = [sheetContext sheet]; + NSRect sheetFrame; + + [_sheetContext autorelease]; + _sheetContext=[sheetContext retain]; + + [self _setSheetOrigin]; + sheetFrame = [sheet frame]; + + [(NSWindowBackgroundView *)[sheet _backgroundView] setBorderType:NSButtonBorder]; + [[sheet contentView] setAutoresizesSubviews:NO]; + [[sheet contentView] setAutoresizingMask:NSViewNotSizable]; + +// [(NSWindowBackgroundView *)[sheet _backgroundView] cacheImageForAnimation]; + + [_attachedSheet setFrame:CPRectMake(CGRectGetMinX(sheetFrame), CGRectGetMinY(sheetFrame), CGRectGetWidth(sheetFrame), 0.0) display:YES]; + [sheet setFrame:NSMakeRect(sheetFrame.origin.x, NSMaxY([self frame]), sheetFrame.size.width, 0) display:YES]; + [self _setSheetOriginAndFront]; + + [sheet setFrame:sheetFrame display:YES animate:YES];*/ +} + +- (void)_attachSheet:(CPWindow)aSheet modalDelegate:(id)aModalDelegate didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo +{ + // Set this as our attached sheet. + _attachedSheet = aSheet; + + // If a window is ever run as a sheet, then it's sheet bit is set to YES. + aSheet._isSheet = YES; + + [self _setAttachedSheetFrameOrigin]; + + // Place this window above ourselves. + [_bridge order:CPWindowAbove window:aSheet relativeTo:self]; +} + +- (CPWindow)attachedSheet +{ + return _attachedSheet; +} + +- (BOOL)isSheet +{ + return _isSheet; +} + +// + +- (BOOL)becomesKeyOnlyIfNeeded +{ + return NO; +} + +- (BOOL)worksWhenModal +{ + return NO; +} + +@end + +@implementation CPWindow (MenuBar) + +- (void)_synchronizeMenuBarTitleWithWindowTitle +{ + // Windows with Documents automatically update the native window title and the menu bar title. + if (![_windowController document] || ![self isMainWindow]) + return; + + [CPMenu setMenuBarTitle:_title]; +} + +@end + +@implementation CPWindow (BridgeSupport) + +- (void)setBridge:(CPDOMWindowBridge)aBridge +{ + if (_bridge == aBridge) + return; + + if (_bridge) + { + [self orderOut:self]; + // FIXME: If the bridge changes, then we have to recreate all of our subviews' DOM Elements. + } + + _bridge = aBridge; + + if (_styleMask & CPBorderlessBridgeWindowMask) + [self setFrame:[aBridge contentBounds]]; +} + +- (void)resizeWithOldBridgeSize:(CGSize)aSize +{ + if (_styleMask & CPBorderlessBridgeWindowMask) + return [self setFrame:[_bridge visibleFrame]]; + + if (_autoresizingMask == CPWindowNotSizable) + return; + + var frame = [_bridge contentBounds], + newFrame = CGRectMakeCopy(_frame), + dX = (CGRectGetWidth(frame) - aSize.width) / + (((_autoresizingMask & CPWindowMinXMargin) ? 1 : 0) + (_autoresizingMask & CPWindowWidthSizable ? 1 : 0) + (_autoresizingMask & CPWindowMaxXMargin ? 1 : 0)), + dY = (CGRectGetHeight(frame) - aSize.height) / + ((_autoresizingMask & CPWindowMinYMargin ? 1 : 0) + (_autoresizingMask & CPWindowHeightSizable ? 1 : 0) + (_autoresizingMask & CPWindowMaxYMargin ? 1 : 0)); + + if (_autoresizingMask & CPWindowMinXMargin) + newFrame.origin.x += dX; + if (_autoresizingMask & CPWindowWidthSizable) + newFrame.size.width += dX; + + if (_autoresizingMask & CPWindowMinYMargin) + newFrame.origin.y += dY; + if (_autoresizingMask & CPWindowHeightSizable) + newFrame.size.height += dY; + + [self setFrame:newFrame]; +} + +- (void)setAutoresizingMask:(unsigned)anAutoresizingMask +{ + _autoresizingMask = anAutoresizingMask; +} + +- (unsigned)autoresizingMask +{ + return _autoresizingMask; +} + +- (CGPoint)convertBaseToBridge:(CGPoint)aPoint +{ + var origin = [self frame].origin; + + return CGPointMake(aPoint.x + origin.x, aPoint.y + origin.y); +} + +- (CGPoint)convertBridgeToBase:(CGPoint)aPoint +{ + var origin = [self frame].origin; + + return CGPointMake(aPoint.x - origin.x, aPoint.y - origin.y); +} + +// Undo and Redo Support + +- (CPUndoManager)undoManager +{ + if (_delegateRespondsToWindowWillReturnUndoManagerSelector) + return [_delegate windowWillReturnUndoManager:self]; + + if (!_undoManager) + _undoManager = [[CPUndoManager alloc] init]; + + return _undoManager; +} + +- (void)undo:(id)aSender +{ + [[self undoManager] undo]; +} + +- (void)redo:(id)aSender +{ + [[self undoManager] redo]; +} + +@end + +var interpolate = function(fromValue, toValue, progress) +{ + return fromValue + (toValue - fromValue) * progress; +} + +@implementation _CPWindowFrameAnimation : CPAnimation +{ + CPWindow _window; + + CGRect _startFrame; + CGRect _targetFrame; +} + +- (id)initWithWindow:(CPWindow)aWindow targetFrame:(CGRect)aTargetFrame +{ + self = [super initWithDuration:0.2 animationCurve:CPAnimationLinear]; + + if (self) + { + _window = aWindow; + + _targetFrame = CGRectMakeCopy(aTargetFrame); + _startFrame = CGRectMakeCopy([_window frame]); + } + + return self; +} + +- (void)startAnimation +{ + [super startAnimation]; + + _window._isAnimating = YES; +} + +- (void)setCurrentProgress:(float)aProgress +{ + [super setCurrentProgress:aProgress]; + + var value = [self currentValue]; + + if (value == 1.0) + _window._isAnimating = NO; + + [_window setFrameOrigin:CGPointMake(interpolate(CGRectGetMinX(_startFrame), CGRectGetMinX(_targetFrame), value), interpolate(CGRectGetMinY(_startFrame), CGRectGetMinY(_targetFrame), value))]; + [_window setFrameSize:CGSizeMake(interpolate(CGRectGetWidth(_startFrame), CGRectGetWidth(_targetFrame), value), interpolate(CGRectGetHeight(_startFrame), CGRectGetHeight(_targetFrame), value))]; +} + +@end + +import "CPDragServer.j" +import "CPDOMWindowBridge.j" +import "_CPWindowView.j" +import "CPView.j" diff --git a/AppKit/CPWindowController.j b/AppKit/CPWindowController.j new file mode 100644 index 000000000..e0c7b8abc --- /dev/null +++ b/AppKit/CPWindowController.j @@ -0,0 +1,215 @@ +/* + * CPWindowController.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import + +import "CPResponder.j" +import "CPWindow.j" +import "CPDocument.j" + +#include "Platform/Platform.h" + + +@implementation CPWindowController : CPResponder +{ + id _owner; + CPWindow _window; + CPDocument _document; + CPString _windowCibName; +} + +- (id)initWithWindow:(CPWindow)aWindow +{ + self = [super init]; + + if (self) + { + [self setWindow:aWindow]; + + [self setNextResponder:CPApp]; + } + + return self; +} + +- (id)initWithWindowCibName:(CPString)aWindowCibName +{ + return [self initWithWindowCibName:aWindowCibName owner:self]; +} + +- (id)initWithWindowCibName:(CPString)aWindowCibName owner:(id)anOwner +{ + self = [super init]; + + if (self) + { + _owner = anOwner; + _windowCibName = aWindowCibName; + + [self setNextResponder:CPApp]; + } + + return self; +} + +- (void)loadWindow +{ + [self windowWillLoad]; + //FIXME: ACTUALLY LOAD WINDOW!!! + [self setWindow:CPApp._keyWindow = [[CPWindow alloc] initWithContentRect:CPRectMakeZero() styleMask:CPBorderlessBridgeWindowMask|CPTitledWindowMask|CPClosableWindowMask|CPResizableWindowMask]]; + + [self windowDidLoad]; +} + +- (CFAction)showWindow:(id)aSender +{ + var theWindow = [self window]; + + if ([theWindow respondsToSelector:@selector(becomesKeyOnlyIfNeeded)] && [theWindow becomesKeyOnlyIfNeeded]) + [theWindow orderFront:aSender]; + else + [theWindow makeKeyAndOrderFront:aSender]; +} + +- (BOOL)isWindowLoaded +{ + return _window; +} + +- (CPWindow)window +{ + if (!_window) + [self loadWindow]; + + return _window; +} + +- (void)setWindow:(CPWindow)aWindow +{ + _window = aWindow; + + [_window setWindowController:self]; + [_window setNextResponder:self]; +} + +- (void)windowDidLoad +{ + [_document windowControllerDidLoadNib:self]; + + [self synchronizeWindowTitleWithDocumentName]; +} + +- (void)windowWillLoad +{ + [_document windowControllerWillLoadNib:self]; +} + +- (void)setDocument:(CPDocument)aDocument +{ + if (_document == aDocument) + return; + + var defaultCenter = [CPNotificationCenter defaultCenter]; + + if (_document) + { + [defaultCenter removeObserver:self + name:CPDocumentWillSaveNotification + object:_document]; + + [defaultCenter removeObserver:self + name:CPDocumentDidSaveNotification + object:_document]; + + [defaultCenter removeObserver:self + name:CPDocumentDidFailToSaveNotification + object:_document]; + } + + _document = aDocument; + + if (_document) + { + [defaultCenter addObserver:self + selector:@selector(_documentWillSave:) + name:CPDocumentWillSaveNotification + object:_document]; + + [defaultCenter addObserver:self + selector:@selector(_documentDidSave:) + name:CPDocumentDidSaveNotification + object:_document]; + + [defaultCenter addObserver:self + selector:@selector(_documentDidFailToSave:) + name:CPDocumentDidFailToSaveNotification + object:_document]; + + [self setDocumentEdited:[_document isDocumentEdited]]; + } + + [self synchronizeWindowTitleWithDocumentName]; +} + +- (void)_documentWillSave:(CPNotification)aNotification +{ + [[self window] setDocumentSaving:YES]; +} + +- (void)_documentDidSave:(CPNotification)aNotification +{ + [[self window] setDocumentSaving:NO]; +} + +- (void)_documentDidFailToSave:(CPNotification)aNotification +{ + [[self window] setDocumentSaving:NO]; +} + +- (CPDocument)document +{ + return _document; +} + +- (void)setDocumentEdited:(BOOL)isEdited +{ + [[self window] setDocumentEdited:isEdited]; +} + +// Setting and Getting Window Attributes + +- (void)synchronizeWindowTitleWithDocumentName +{ + if (!_document || !_window) + return; + + // [_window setRepresentedFilename:]; + [_window setTitle:[self windowTitleForDocumentDisplayName:[_document displayName]]]; +} + +- (CPString)windowTitleForDocumentDisplayName:(CPString)aDisplayName +{ + return aDisplayName; +} + +@end diff --git a/AppKit/Cib/CPCib.j b/AppKit/Cib/CPCib.j new file mode 100644 index 000000000..e535eaa78 --- /dev/null +++ b/AppKit/Cib/CPCib.j @@ -0,0 +1,128 @@ +/* + * CPCib.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import +import + +import "CPCustomView.j" +import "_CPCibObjectData.j" + + +CPCibOwner = @"CPCibOwner", +CPCibTopLevelObjects = @"CPCibTopLevelObjects"; + +var CPCibObjectDataKey = @"CPCibObjectDataKey"; + +@implementation CPCib : CPObject +{ + CPData _data; +} + +- (id)initWithContentsOfURL:(CPURL)aURL +{ + self = [super init]; + + if (self) + _data = [CPURLConnection sendSynchronousRequest:[CPURLRequest requestWithURL:aURL] returningResponse:nil error:nil]; + + return self; +} + +- (BOOL)instantiateCibWithExternalNameTable:(CPDictionary)anExternalNameTable +{ + var unarchiver = [[CPKeyedUnarchiver alloc] initForReadingWithData:_data], + objectData = [unarchiver decodeObjectForKey:CPCibObjectDataKey]; + + if (!objectData || ![objectData isKindOfClass:[_CPCibObjectData class]]) + return NO; + + var owner = [anExternalNameTable objectForKey:CPCibOwner], + topLevelObjects = [anExternalNameTable objectForKey:CPCibTopLevelObjects]; + + var objects = unarchiver._objects, + count = [objects count]; + + // The order in which objects receive the awakeFromCib message is not guaranteed. + while (count--) + { + var object = objects[count]; + + if ([object isMemberOfClass:[CPView class]]) + return object; + } + /* +// [objectData establishConnectionsWithOwner:owner topLevelObjects:topLevelObjects]; +// [objectData cibInstantiateWithOwner:owner topLevelObjects:topLevelObjects]; +// alert([objectData description]); +// alert([unarchiver._archive description]); + + NSMutableArray *t; + NSEnumerator *e; + id o; + id owner; + id rootObject; +#if 0 + NSLog(@"instantiateCibWithExternalNameTable=%@", table); +#endif + if(![decoded isKindOfClass:[NSIBObjectData class]]) + return NO; + owner=[table objectForKey:NSCibOwner]; + rootObject=[decoded rootObject]; +#if 0 + NSLog(@"establishConnections"); +#endif + [decoded establishConnectionsWithExternalNameTable:table]; +#if 0 + NSLog(@"awakeFromCib %d objects", [decodedObjects count]); +#endif +#if 0 + NSLog(@"objects 2=%@", decodedObjects); +#endif + + // FIXME: shouldn't be accessing private variables. + var objects = unarchiver._objects, + count = [objects count]; + + // The order in which objects receive the awakeFromCib message is not guaranteed. + while (count--) + { + var object = objects[count]; + + if ([object respondsToSelector:@selector(awakeFromCib)]) + [object awakeFromCib]; + } + +// if ([owner respondsToSelector:@selector(awakeFromCib)]) +// [owner awakeFromCib]; + // Display visible windows. + + return YES;*/ +} + +- (BOOL)instantiateCibWithOwner:(id)anOwner topLevelObjects:(CPArray)topLevelObjects +{ + [CPDictionary dictionaryWithObjectsAndKeys:anOwner, CPCibOwner, topLevelObjects, CPCibTopLevelObjects]; + return [self instantiate]; +} + +@end diff --git a/AppKit/Cib/CPCustomView.j b/AppKit/Cib/CPCustomView.j new file mode 100644 index 000000000..035b97e20 --- /dev/null +++ b/AppKit/Cib/CPCustomView.j @@ -0,0 +1,83 @@ +/* + * CPCustomView.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPView.j" + +@implementation CPCustomView : CPView +{ + CPString _className; +} + +@end + +var CPCustomViewClassNameKey = @"CPCustomViewClassNameKey"; + +@implementation CPCustomView (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + _className = [aCoder decodeObjectForKey:CPCustomViewClassNameKey]; + + var theClass = CPClassFromString(_className); + + // If we don't have this class, just use CPView. + // FIXME: Should we instead throw an exception? + if (!theClass) + theClass = [CPView class]; + + // If this is just a "CPView", don't bother with any funny business, just go ahead and create it with initWithCoder: + if (theClass == [CPView class]) + self = [[CPView alloc] initWithCoder:aCoder]; + + return self; + // If not, fall back to initWithFrame: +/* + var frame = [aCoder decodeRectForKey:CPViewFrameKey]; + + self = [[theClass alloc] initWithFrame:frame]; + + if (self) + { + _bounds = [aCoder decodeRectForKey:CPViewBoundsKey]; + + _window = [aCoder decodeObjectForKey:CPViewWindowKey]; + _subviews = [aCoder decodeObjectForKey:CPViewSubviewsKey]; + _superview = [aCoder decodeObjectForKey:CPViewSuperviewKey]; + + _autoresizingMask = [aCoder decodeIntForKey:CPViewAutoresizingMaskKey]; + _autoresizesSubviews = [aCoder decodeBoolForKey:CPViewAutoresizesSubviewsKey]; + + // FIXME: UGH!!!! + _index = [aCoder decodeIntForKey:FIXME_indexKey]; + + _hitTests = [aCoder decodeObjectForKey:CPViewHitTestsKey]; + _isHidden = [aCoder decodeObjectForKey:CPViewIsHiddenKey]; + _opacity = [aCoder decodeIntForKey:CPViewOpacityKey]; + + [self setBackgroundColor:[aCoder decodeObjectForKey:CPViewBackgroundColorKey]]; + + } + + return self;*/ +} + +@end diff --git a/AppKit/Cib/_CPCibLoading.j b/AppKit/Cib/_CPCibLoading.j new file mode 100644 index 000000000..6c3a46438 --- /dev/null +++ b/AppKit/Cib/_CPCibLoading.j @@ -0,0 +1,69 @@ +/* + * _CPCibLoading.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import +import + + +var CPCibOwner = @"CPCibOwner"; + +@implementation CPObject (CPCibLoading) + +-(void)awakeFromCib +{ +} + +@end + +@implementation CPBundle (CPCibLoading) + ++ (BOOL)loadCibFile:(CPString)aPath externalNameTable:(CPDictionary)aNameTable +{ + return [[[CPCib alloc] initWithContentsOfFile:aPath] instantiateCibWithExternalNameTable:aNameTable]; +} + ++ (BOOL)loadCibNamed:(CPString)aName owner:(id)anOwner +{ + var bundle = [CPBundle bundleForClass:[anOwner class]]; + + /*NSString *path; + + path=[bundle pathForResource:name ofType:@"cib"]; + if(path==nil) + path=[[NSBundle mainBundle] pathForResource:name ofType:@"cib"]; + + if(path==nil) + return NO; + */ + var path = [bundle pathForResource:aName]; + + return [CPBundle loadCibFile:aPath externalNameTable:[CPDictionary dictionaryWithObject:anOwner forKey:CPCibOwner]]; +} + +- (BOOL)loadCibFile:(CPString)aPath externalNameTable:(CPDictionary)aNameTable +{ + return [[[CPCib alloc] initWithContentsOfFile:aPath] instantiateCibWithExternalNameTable:aNameTable]; +} + +@end + diff --git a/AppKit/Cib/_CPCibObjectData.j b/AppKit/Cib/_CPCibObjectData.j new file mode 100644 index 000000000..53cad72d3 --- /dev/null +++ b/AppKit/Cib/_CPCibObjectData.j @@ -0,0 +1,181 @@ +/* + * _CPCibObjectData.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import +import + + +@implementation _CPCibObjectData : CPObject +{ + CPArray _namesKeys; + CPArray _namesValues; + + CPArray _accessibilityConnectors; + CPArray _accessibilityOidsKeys; + CPArray _accessibilityOidsValues; + + CPArray _classesKeys; + CPArray _classesValues; + + CPArray _connections; + + id _fontManager; + + CPString _framework; + + int _nextOid; + + CPArray _objectsKeys; + CPArray _objectsValues; + + CPArray _oidKeys; + CPArray _oidValues; + + CPCustomObject _rootObject; + + CPSet _visibleWindows; +} +/* +- (CPArray)topLevelObjects +{ + var count = [_objectsValues count]; + + while (count--) + { + var eachObject = _objectsValues[count]; + + if(eachObject == _fileOwner) + { + var anObject = _objectsKeys[count]; + + if (anObject != _fileOwner) + topLevelObjects.push(anObject); + } + } + + return topLevelObjects; +} +*/ + +@end + +var _CPCibObjectDataNamesKeysKey = @"_CPCibObjectDataNamesKeysKey", + _CPCibObjectDataNamesValuesKey = @"_CPCibObjectDataNamesValuesKey", + + _CPCibObjectDataAccessibilityConnectorsKey = @"_CPCibObjectDataAccessibilityConnectors", + _CPCibObjectDataAccessibilityOidsKeysKey = @"_CPCibObjectDataAccessibilityOidsKeys", + _CPCibObjectDataAccessibilityOidsValuesKey = @"_CPCibObjectDataAccessibilityOidsValues", + + _CPCibObjectDataClassesKeysKey = @"_CPCibObjectDataClassesKeysKey", + _CPCibObjectDataClassesValuesKey = @"_CPCibObjectDataClassesValuesKey", + + _CPCibObjectDataConnectionsKey = @"_CPCibObjectDataConnectionsKey", + + _CPCibObjectDataFontManagerKey = @"_CPCibObjectDataFontManagerKey", + + _CPCibObjectDataFrameworkKey = @"_CPCibObjectDataFrameworkKey", + + _CPCibObjectDataNextOidKey = @"_CPCibObjectDataNextOidKey", + + _CPCibObjectDataObjectsKeysKey = @"_CPCibObjectDataObjectsKeysKey", + _CPCibObjectDataObjectsValuesKey = @"_CPCibObjectDataObjectsValuesKey", + + _CPCibObjectDataOidKeysKey = @"_CPCibObjectDataOidKeysKey", + _CPCibObjectDataOidValuesKey = @"_CPCibObjectDataOidValuesKey", + + _CPCibObjectDataRootObjectKey = @"_CPCibObjectDataRootObjectKey", + _CPCibObjectDataVisibleWindowsKey = @"_CPCibObjectDataVisibleWindowsKey"; + +@implementation _CPCibObjectData (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super init]; + + if (self) + { + _namesKeys = [aCoder decodeObjectForKey:_CPCibObjectDataNamesKeysKey]; + _namesValues = [aCoder decodeObjectForKey:_CPCibObjectDataNamesValuesKey]; + + //CPArray _accessibilityConnectors; + //CPArray _accessibilityOidsKeys; + //CPArray _accessibilityOidsValues; + + _classesKeys = [aCoder decodeObjectForKey:_CPCibObjectDataClassesKeysKey]; + _classesValues = [aCoder decodeObjectForKey:_CPCibObjectDataClassesValuesKey]; + + _connections = [aCoder decodeObjectForKey:_CPCibObjectDataConnectionsKey]; + + //id _fontManager; + + _framework = [aCoder decodeObjectForKey:_CPCibObjectDataFrameworkKey]; + + _nextOid = [aCoder decodeIntForKey:_CPCibObjectDataNextOidKey]; + + _objectsKeys = [aCoder decodeObjectForKey:_CPCibObjectDataObjectsKeysKey]; + _objectsValues = [aCoder decodeObjectForKey:_CPCibObjectDataObjectsValuesKey]; + + _oidKeys = [aCoder decodeObjectForKey:_CPCibObjectDataOidKeysKey]; + _oidValues = [aCoder decodeObjectForKey:_CPCibObjectDataOidValuesKey]; + + _rootObject = [aCoder decodeObjectForKey:_CPCibObjectDataRootObjectKey]; + + // CPSet _visibleWindows; + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeObject:_namesKeys forKey:_CPCibObjectDataNamesKeysKey]; + [aCoder encodeObject:_namesValues forKey:_CPCibObjectDataNamesValuesKey]; + + //CPArray _accessibilityConnectors; + //CPArray _accessibilityOidsKeys; + //CPArray _accessibilityOidsValues; + + [aCoder encodeObject:_classesKeys forKey:_CPCibObjectDataClassesKeysKey]; + [aCoder encodeObject:_classesValues forKey:_CPCibObjectDataClassesValuesKey]; + + [aCoder encodeObject:_connections forKey:_CPCibObjectDataConnectionsKey]; + + //id _fontManager; + + [aCoder encodeObject:_framework forKey:_CPCibObjectDataFrameworkKey]; + + [aCoder encodeInt:_nextOid forKey:_CPCibObjectDataNextOidKey]; + + [aCoder encodeObject:_objectsKeys forKey:_CPCibObjectDataObjectsKeysKey]; + [aCoder encodeObject:_objectsValues forKey:_CPCibObjectDataObjectsValuesKey]; + + [aCoder encodeObject:_oidKeys forKey:_CPCibObjectDataOidKeysKey]; + [aCoder encodeObject:_oidValues forKey:_CPCibObjectDataOidValuesKey]; + + [aCoder encodeObject:_rootObject forKey:_CPCibObjectDataRootObjectKey]; +// CPCustomObject _fileOwner; + +// CPSet _visibleWindows; +} + +@end diff --git a/AppKit/CoreAnimation/CAAnimation.j b/AppKit/CoreAnimation/CAAnimation.j new file mode 100644 index 000000000..d46f99e1c --- /dev/null +++ b/AppKit/CoreAnimation/CAAnimation.j @@ -0,0 +1,193 @@ +/* + * CAAnimation.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import + +import "CAMediaTimingFunction.j" + + +@implementation CAAnimation : CPObject +{ + BOOL _isRemovedOnCompletion; +} + ++ (id)animation +{ + return [[self alloc] init]; +} + +- (id)init +{ + self = [super init]; + + if (self) + _isRemovedOnCompletion = YES; + + return self; +} + +- (void)shouldArchiveValueForKey:(CPString)aKey +{ + return YES; +} + ++ (id)defaultValueForKey:(CPString)aKey +{ + return nil; +} + +- (void)setRemovedOnCompletion:(BOOL)isRemovedOnCompletion +{ + _isRemovedOnCompletion = isRemovedOnCompletion; +} + +- (BOOL)removedOnCompletion +{ + return _isRemovedOnCompletion; +} + +- (BOOL)isRemovedOnCompletion +{ + return _isRemovedOnCompletion; +} + +- (CAMediaTimingFunction)timingFunction +{ + // Linear Pacing + return nil; +} + +- (void)setDelegate:(id)aDelegate +{ + _delegate = aDelegate; +} + +- (id)delegate +{ + return _delegate; +} + +- (void)runActionForKey:(CPString)aKey object:(id)anObject arguments:(CPDictionary)arguments +{ + [anObject addAnimation:self forKey:aKey]; +} + +@end + +@implementation CAPropertyAnimation : CAAnimation +{ + CPString _keyPath; + + BOOL _isCumulative; + BOOL _isAdditive; +} + ++ (id)animationWithKeyPath:(CPString)aKeyPath +{ + var animation = [self animation]; + + [animation setKeypath:aKeyPath]; + + return animation; +} + +- (void)setKeyPath:(CPString)aKeyPath +{ + _keyPath = aKeyPath; +} + +- (CPString)keyPath +{ + return _keyPath; +} + +- (void)setCumulative:(BOOL)isCumulative +{ + _isCumulative = isCumulative; +} + +- (BOOL)cumulative +{ + return _isCumulative; +} + +- (BOOL)isCumulative +{ + return _isCumulative; +} + +- (void)setAdditive:(BOOL)isAdditive +{ + _isAdditive = isAdditive; +} + +- (BOOL)additive +{ + return _isAdditive; +} + +- (BOOL)isAdditive +{ + return _isAdditive; +} + +@end + +@implementation CABasicAnimation : CAPropertyAnimation +{ + id _fromValue; + id _toValue; + id _byValue; +} + +- (void)setFromValue:(id)aValue +{ + _fromValue = aValue; +} + +- (id)fromValue +{ + return _fromValue; +} + +- (void)setToValue:(id)aValue +{ + _toValue = aValue; +} + +- (id)toValue +{ + return _toValue; +} + +- (void)setByValue:(id)aValue +{ + _byValue = aValue; +} + +- (id)byValue +{ + return _byValue; +} + +@end diff --git a/AppKit/CoreAnimation/CABackingStore.j b/AppKit/CoreAnimation/CABackingStore.j new file mode 100644 index 000000000..b70bd44cf --- /dev/null +++ b/AppKit/CoreAnimation/CABackingStore.j @@ -0,0 +1,72 @@ +/* + * CABackingStore.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CGGeometry.j" +import "CPCompatibility.j" + +#define PIXEL(pixels) pixels + "px"; + +function CABackingStoreGetContext(aBackingStore) +{ + return aBackingStore.context; +} + +if (CPFeatureIsCompatible(CPHTMLCanvasFeature)) +{ + +CABackingStoreCreate = function() +{ + var DOMElement = document.createElement("canvas"); + + DOMElement.style.position = "absolute"; + + // FIXME: Consolidate drawImage to support this. + return { context:DOMElement.getContext("2d"), buffer:DOMElement, _image:DOMElement }; +} + +CABackingStoreSetSize = function(aBackingStore, aSize) +{ + var buffer = aBackingStore.buffer; + + buffer.width = aSize.width; + buffer.height = aSize.height; + buffer.style.width = PIXEL(aSize.width); + buffer.style.height = PIXEL(aSize.height); +} +} +else +{ + +CABackingStoreCreate = function() +{ + var context = CGBitmapGraphicsContextCreate(); + + context.buffer = ""; + + return { context:context }; +} + +CABackingStoreSetSize = function(aBackingStore, aSize) +{ +} + +} \ No newline at end of file diff --git a/AppKit/CoreAnimation/CAFlashLayer.j b/AppKit/CoreAnimation/CAFlashLayer.j new file mode 100644 index 000000000..e7a5bdfba --- /dev/null +++ b/AppKit/CoreAnimation/CAFlashLayer.j @@ -0,0 +1,50 @@ +/* + * CAFlashLayer.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CALayer.j" +import "CPFlashMovie.j" + + +@implementation CAFlashLayer : CALayer +{ + CPFlashMovie _flashMovie; +} + +- (void)setFlashMovie:(CPFlashMovie)aFlashMovie +{ + if (_flashMovie == aFlashMovie) + return; + + _flashMovie = aFlashMovie; + + _DOMElement.innerHTML = ""; +} + +- (CPFlashMovie)flashMovie +{ + return _flashMovie; +} + +@end diff --git a/AppKit/CoreAnimation/CALayer.j b/AppKit/CoreAnimation/CALayer.j new file mode 100644 index 000000000..531934f57 --- /dev/null +++ b/AppKit/CoreAnimation/CALayer.j @@ -0,0 +1,980 @@ +/* + * CALayer.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + +import + +import +import + +#include "../CoreGraphics/CGGeometry.h" +#include "../CoreGraphics/CGAffineTransform.j" + + +#define DOM(aLayer) aLayer._DOMElement + +var CALayerGeometryBoundsMask = 1, + CALayerGeometryPositionMask = 2, + CALayerGeometryAnchorPointMask = 4, + CALayerGeometryAffineTransformMask = 8, + CALayerGeometryParentSublayerTransformMask = 16; +var USE_BUFFER = NO; + +var CALayerFrameOriginUpdateMask = 1, + CALayerFrameSizeUpdateMask = 2, + CALayerZPositionUpdateMask = 4, + CALayerDisplayUpdateMask = 8, + CALayerCompositeUpdateMask = 16, + CALayerDOMUpdateMask = CALayerZPositionUpdateMask | CALayerFrameOriginUpdateMask | CALayerFrameSizeUpdateMask; + +var CALayerRegisteredRunLoopUpdates = nil; + +@implementation CALayer : CPObject +{ + // Modifying the Layer Geometry + + CGRect _frame; + CGRect _bounds; + CGPoint _position; + unsigned _zPosition; + CGPoint _anchorPoint; + + CGAffineTransform _affineTransform; + CGAffineTransform _sublayerTransform; + CGAffineTransform _sublayerTransformForSublayers; + + CGRect _backingStoreFrame; + CGRect _standardBackingStoreFrame; + + BOOL _hasSublayerTransform; + BOOL _hasCustomBackingStoreFrame; + + // Style Attributes + + float _opacity; + BOOL _isHidden; + CPColor _backgroundColor; + + // Managing Layer Hierarchy + + CALayer _superlayer; + CPMutableArray _sublayers; + + // Updating Layer Display + + unsigned _runLoopUpdateMask; + BOOL _needsDisplayOnBoundsChange; + + // Modifyin the Delegate + + id _delegate; + + BOOL _delegateRespondsToDisplayLayerSelector; + BOOL _delegateRespondsToDrawLayerInContextSelector; + + // DOM Implementation + + DOMElement _DOMElement; + DOMElement _DOMContentsElement; + id _contents; + CGContext _context; + CPView _owningView; + + CGAffineTransform _transformToLayer; + CGAffineTransform _transformFromLayer; +} + ++ (CALayer)layer +{ + return [[[self class] alloc] init]; +} + +- (id)init +{ + self = [super init]; + + if (self) + { + _frame = CGRectMakeZero(); + + _backingStoreFrame = CGRectMakeZero(); + _standardBackingStoreFrame = CGRectMakeZero(); + + _bounds = CGRectMakeZero(); + _position = CGPointMakeZero(); + _zPosition = 0.0; + _anchorPoint = CGPointMake(0.5, 0.5); + _affineTransform = CGAffineTransformMakeIdentity(); + _sublayerTransform = CGAffineTransformMakeIdentity(); + + _transformToLayer = CGAffineTransformMakeIdentity(); // FIXME? does it matter? + _transformFromLayer = CGAffineTransformMakeIdentity(); + + _opacity = 1.0; + _isHidden = NO; + _masksToBounds = NO; + + _sublayers = []; + + _DOMElement = document.createElement("div"); + + _DOMElement.style.overflow = "visible"; + _DOMElement.style.position = "absolute"; + _DOMElement.style.visibility = "visible"; + _DOMElement.style.top = "0px"; + _DOMElement.style.left = "0px"; + _DOMElement.style.zIndex = 0; + _DOMElement.style.width = "0px"; + _DOMElement.style.height = "0px"; + } + + return self; +} + +// Modifying the Layer Geometry + +- (void)setBounds:(CGRect)aBounds +{ + if (CGRectEqualToRect(_bounds, aBounds)) + return; + + var oldOrigin = _bounds.origin; + + _bounds = _CGRectMakeCopy(aBounds); + + if (_hasSublayerTransform) + _CALayerUpdateSublayerTransformForSublayers(self); + + // _hasSublayerTransform == true will handle this for us. + /*else if (!CGPointEqualToPoint(_bounds.origin, oldOrigin)) + { + var index = _sublayers.length; + + // FIXME: This should climb the layer tree down. + while (index--) + _CALayerRecalculateGeometry(_sublayers[index], CALayerGeometryPositionMask); + }*/ + + _CALayerRecalculateGeometry(self, CALayerGeometryBoundsMask); +} + +- (CGRect)bounds +{ + return _bounds; +} + +- (void)setPosition:(CGPoint)aPosition +{ + if (CGPointEqualToPoint(_position, aPosition)) + return; + + _position = _CGPointMakeCopy(aPosition); + + _CALayerRecalculateGeometry(self, CALayerGeometryPositionMask); +} + +- (CGPoint)position +{ + return _position; +} + +- (void)setZPosition:(int)aZPosition +{ + if (_zPosition == aZPosition) + return; + + _zPosition = aZPosition; + + [self registerRunLoopUpdateWithMask:CALayerZPositionUpdateMask]; +} + +- (void)setAnchorPoint:(CGPoint)anAnchorPoint +{ + anAnchorPoint = _CGPointMakeCopy(anAnchorPoint); + anAnchorPoint.x = MIN(1.0, MAX(0.0, anAnchorPoint.x)); + anAnchorPoint.y = MIN(1.0, MAX(0.0, anAnchorPoint.y)); + + if (CGPointEqualToPoint(_anchorPoint, anAnchorPoint)) + return; + + _anchorPoint = anAnchorPoint; + + if (_hasSublayerTransform) + _CALayerUpdateSublayerTransformForSublayers(self); + + if (_owningView) + _position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y); + + _CALayerRecalculateGeometry(self, CALayerGeometryAnchorPointMask); +} + +- (CGPoint)anchorPoint +{ + return _anchorPoint; +} + +- (void)setAffineTransform:(CGAffineTransform)anAffineTransform +{ + if (CGAffineTransformEqualToTransform(_affineTransform, anAffineTransform)) + return; + + _affineTransform = _CGAffineTransformMakeCopy(anAffineTransform); + + _CALayerRecalculateGeometry(self, CALayerGeometryAffineTransformMask); +} + +- (CGAffineTransform)affineTransform +{ + return _affineTransform; +} + +- (void)setSublayerTransform:(CGAffineTransform)anAffineTransform +{ + if (CGAffineTransformEqualToTransform(_sublayerTransform, anAffineTransform)) + return; + + var hadSublayerTransform = _hasSublayerTransform; + + _sublayerTransform = _CGAffineTransformMakeCopy(anAffineTransform); + _hasSublayerTransform = !_CGAffineTransformIsIdentity(_sublayerTransform); + + if (_hasSublayerTransform) + { + _CALayerUpdateSublayerTransformForSublayers(self); + + var index = _sublayers.length; + + // FIXME: This should climb the layer tree down. + while (index--) + _CALayerRecalculateGeometry(_sublayers[index], CALayerGeometryParentSublayerTransformMask); + } +} + +- (CGAffineTransform)sublayerTransform +{ + return _sublayerTransform; +} + +- (CGAffineTransform)transformToLayer +{ + return _transformToLayer; +} + +- (void)setFrame:(CGRect)aFrame +{ + alert("FIXME IMPLEMENT"); +} + +// The frame defines the bounding box of the layer: the smallest +// possible rectangle that could fit this layer after transform +// properties are applied in superlayer coordinates. +- (CGRect)frame +{ + if (!_frame) + _frame = [self convertRect:_bounds toLayer:_superlayer]; + + return _frame; +} + +// The Backing Store Frame specifies the frame of the actual backing +// store used to contain this layer. Naturally, by default it is the +// same as the frame, however, users can specify their own custom +// Backing Store Frame in order to speed up certain operations, such as +// live transformation. +- (CGRect)backingStoreFrame +{ + return _backingStoreFrame; +} + +- (void)setBackingStoreFrame:(CGRect)aFrame +{ + _hasCustomBackingStoreFrame = (aFrame != nil); + + if (aFrame == nil) + aFrame = CGRectMakeCopy(_standardBackingStoreFrame); + else + { + if (_superlayer) + { + aFrame = [_superlayer convertRect:aFrame toLayer:nil]; + + var bounds = [_superlayer bounds], + frame = [_superlayer convertRect:bounds toLayer:nil]; + + aFrame.origin.x -= _CGRectGetMinX(frame); + aFrame.origin.y -= _CGRectGetMinY(frame); + } + else + aFrame = CGRectMakeCopy(aFrame); + } + + if (!CGPointEqualToPoint(_backingStoreFrame.origin, aFrame.origin)) + [self registerRunLoopUpdateWithMask:CALayerFrameOriginUpdateMask]; + + if (!CGSizeEqualToSize(_backingStoreFrame.size, aFrame.size)) + [self registerRunLoopUpdateWithMask:CALayerFrameSizeUpdateMask]; + + _backingStoreFrame = aFrame; +} + +// Providing Layer Content + +- (CGImage)contents +{ + return _contents; +} + +- (void)setContents:(CGImage)contents +{ + if (_contents == contents) + return; + + _contents = contents; + + [self composite]; +} + +- (void)composite +{ + if (USE_BUFFER && !_contents || !_context) + return; + + CGContextClearRect(_context, _CGRectMake(0.0, 0.0, _CGRectGetWidth(_backingStoreFrame), _CGRectGetHeight(_backingStoreFrame))); + + // Recomposite + var transform = _transformFromLayer; + + if (_superlayer) + { + var superlayerTransform = _CALayerGetTransform(_superlayer, nil), + superlayerOrigin = CGPointApplyAffineTransform(_superlayer._bounds.origin, superlayerTransform); + + transform = CGAffineTransformConcat(transform, superlayerTransform); + + transform.tx -= superlayerOrigin.x; + transform.ty -= superlayerOrigin.y; + } + + transform.tx -= _CGRectGetMinX(_backingStoreFrame); + transform.ty -= _CGRectGetMinY(_backingStoreFrame); + + CGContextSaveGState(_context); + CGContextConcatCTM(_context, transform);//_transformFromView); + if (USE_BUFFER) + { +// CGContextDrawImage(_context, _bounds, _contents.context); + _context.drawImage(_contents.buffer, _CGRectGetMinX(_bounds), _CGRectGetMinY(_bounds));//, _CGRectGetWidth(_standardBackingStoreFrame), _CGRectGetHeight(_standardBackingStoreFrame)); + } + else + [self drawInContext:_context]; + CGContextRestoreGState(_context); +} + +- (void)display +{ + if (!_context) + { + _context = CGBitmapGraphicsContextCreate(); + + _DOMContentsElement = _context.DOMElement; + + _DOMContentsElement.style.zIndex = -100; + + _DOMContentsElement.style.overflow = "hidden"; + _DOMContentsElement.style.position = "absolute"; + _DOMContentsElement.style.visibility = "visible"; + + _DOMContentsElement.width = ROUND(_CGRectGetWidth(_backingStoreFrame)); + _DOMContentsElement.height = ROUND(_CGRectGetHeight(_backingStoreFrame)); + + _DOMContentsElement.style.top = "0px"; + _DOMContentsElement.style.left = "0px"; + _DOMContentsElement.style.width = ROUND(_CGRectGetWidth(_backingStoreFrame)) + "px"; + _DOMContentsElement.style.height = ROUND(_CGRectGetHeight(_backingStoreFrame)) + "px"; + + _DOMElement.appendChild(_DOMContentsElement); + } + + if (USE_BUFFER) + { + if (_delegateRespondsToDisplayLayerSelector) + return [self displayInLayer:self]; + + if (_CGRectGetWidth(_backingStoreFrame) == 0.0 || _CGRectGetHeight(_backingStoreFrame) == 0.0) + return; + + if (!_contents) + _contents = CABackingStoreCreate(); + + CABackingStoreSetSize(_contents, _bounds.size); + + [self drawInContext:CABackingStoreGetContext(_contents)]; + } + + [self composite]; +} + +- (void)drawInContext:(CGContext)aContext +{ //if (!window.loop || window.nodisplay) CPLog.error("htiasd"); + if (_backgroundColor) + { + CGContextSetFillColor(aContext, _backgroundColor); + CGContextFillRect(aContext, _bounds); + } + + if (_delegateRespondsToDrawLayerInContextSelector) + [_delegate drawLayer:self inContext:aContext]; +} + + +// Style Attributes + +- (float)opacity +{ + return _opacity; +} + +- (void)setOpacity:(float)anOpacity +{ + if (_opacity == anOpacity) + return; + + _opacity = anOpacity; + + _DOMElement.style.opacity = anOpacity; + _DOMElement.style.filter = "alpha(opacity=" + anOpacity * 100 + ")"; +} + +- (void)setHidden:(BOOL)isHidden +{ + _isHidden = isHidden; + _DOMElement.style.display = isHidden ? "none" : "block"; +} + +- (BOOL)hidden +{ + return _isHidden; +} + +- (BOOL)isHidden +{ + return _isHidden; +} + +- (void)setMasksToBounds:(BOOL)masksToBounds +{ + if (_masksToBounds == masksToBounds) + return; + + _masksToBounds = masksToBounds; + _DOMElement.style.overflow = _masksToBounds ? "hidden" : "visible"; +} + +- (void)setBackgroundColor:(CPColor)aColor +{ + _backgroundColor = aColor; + + [self setNeedsDisplay]; +} + +- (CPColor)backgroundColor +{ + return _backgroundColor; +} + +// Managing Layer Hierarchy + +- (CPArray)sublayers +{ + return _sublayers; +} + +- (CALayer)superlayer +{ + return _superlayer; +} + +#define ADJUST_CONTENTS_ZINDEX(aLayer)\ +if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)\ + _DOMContentsElement.style.zIndex -= 100.0;\ + +- (void)addSublayer:(CALayer)aLayer +{ + [self insertSublayer:aLayer atIndex:_sublayers.length]; + return; + ADJUST_CONTENTS_ZINDEX(aLayer); + + [_sublayers addObject:aLayer]; + _DOMElement.appendChild(DOM(aLayer)); +} + +- (void)removeFromSuperlayer +{ + if (_owningView) + [_owningView setLayer:nil]; + + if (!_superlayer) + return; + + _superlayer._DOMElement.removeChild(_DOMElement); + [_superlayer._sublayers removeObject:self]; + + _superlayer = nil; +} + +- (void)insertSublayer:(CALayer)aLayer atIndex:(unsigned)anIndex +{ + if (!aLayer) + return; + + var superlayer = [aLayer superlayer]; + + if (superlayer == self) + { + var index = [_sublayers indexOfObjectIdenticalTo:aLayer]; + + if (index == anIndex) + return; + + [_sublayers removeObjectAtIndex:index]; + + if (index < anIndex) + --anIndex; + } + else if (superlayer != nil) + [aLayer removeFromSuperlayer]; + + ADJUST_CONTENTS_ZINDEX(aLayer); + + [_sublayers insertObject:aLayer atIndex:anIndex]; + + if (anIndex >= _sublayers.length - 1) + _DOMElement.appendChild(DOM(aLayer)); + else + _DOMElement.insertBefore(DOM(aLayer), _sublayers[anIndex + 1]._DOMElement); + + aLayer._superlayer = self; + + if (self != superlayer) + _CALayerRecalculateGeometry(aLayer, 0xFFFFFFF); +} + +- (void)insertSublayer:(CALayer)aLayer below:(CALayer)aSublayer +{ + var index = aSublayer ? [_sublayers indexOfObjectIdenticalTo:aSublayer] : 0; + + [self insertSublayer:aLayer atIndex:index == CPNotFound ? _sublayers.length : index]; +} + +- (void)insertSublayer:(CALayer)aLayer after:(CALayer)aSublayer +{ + var index = aSublayer ? [_sublayers indexOfObjectIdenticalTo:aSublayer] : _sublayers.length; + + [_sublayers insertObject:aLayer atIndex:index == CPNotFound ? _sublayers.length : index + 1]; +} + +- (void)replaceSublayer:(CALayer)aSublayer with:(CALayer)aLayer +{ + if (aSublayer == aLayer) + return; + + // FIXME: EXCEPTION + if (aSublayer._superlayer != self) + { + alert("EXCEPTION"); + return; + } + + ADJUST_CONTENTS_ZINDEX(aLayer); + + [_sublayers replaceObjectAtIndex:[_sublayers indexOfObjectIdenticalTo:aSublayer] withObject:aLayer]; + _DOMElement.replaceChild(DOM(aSublayer), DOM(aLayer)); +} + +// Updating Layer Display + ++ (void)runLoopUpdateLayers +{if (window.oops) {alert(window.latest); objj_debug_print_backtrace();} + window.loop = true; + for (hash in CALayerRegisteredRunLoopUpdates) + { + var layer = CALayerRegisteredRunLoopUpdates[hash], + mask = layer._runLoopUpdateMask; + + if (mask & CALayerDOMUpdateMask) + _CALayerUpdateDOM(layer, mask); + + if (mask & CALayerDisplayUpdateMask) + [layer display]; + + else if (mask & CALayerFrameSizeUpdateMask || mask & CALayerCompositeUpdateMask) + [layer composite]; + + layer._runLoopUpdateMask = 0; + } + window.loop= false; + CALayerRegisteredRunLoopUpdates = nil; +} + +- (void)registerRunLoopUpdateWithMask:(unsigned)anUpdateMask +{ + if (CALayerRegisteredRunLoopUpdates == nil) + { + CALayerRegisteredRunLoopUpdates = {}; + + [[CPRunLoop currentRunLoop] performSelector:@selector(runLoopUpdateLayers) + target:CALayer argument:nil order:0 modes:[CPDefaultRunLoopMode]]; + } + + _runLoopUpdateMask |= anUpdateMask; + CALayerRegisteredRunLoopUpdates[[self hash]] = self; +} + +- (void)setNeedsComposite +{ + [self registerRunLoopUpdateWithMask:CALayerCompositeUpdateMask]; +} + +- (void)setNeedsDisplay +{ + [self registerRunLoopUpdateWithMask:CALayerDisplayUpdateMask]; +} + +- (void)setNeedsDisplayOnBoundsChange:(BOOL)needsDisplayOnBoundsChange +{ + _needsDisplayOnBoundsChange = needsDisplayOnBoundsChange; +} + +- (BOOL)needsDisplayOnBoundsChange +{ + return _needsDisplayOnBoundsChange; +} + +- (void)setNeedsDisplayInRect:(CGRect)aRect +{ + _dirtyRect = aRect; + [self display]; +} + +// Mapping Between Coordinate and Time Spaces + +- (CGPoint)convertPoint:(CGPoint)aPoint fromLayer:(CALayer)aLayer +{ + return CGPointApplyAffineTransform(aPoint, _CALayerGetTransform(aLayer, self)); +} + +- (CGPoint)convertPoint:(CGPoint)aPoint toLayer:(CALayer)aLayer +{ + return CGPointApplyAffineTransform(aPoint, _CALayerGetTransform(self, aLayer)); +} + +- (CGRect)convertRect:(CGRect)aRect fromLayer:(CALayer)aLayer +{ + return CGRectApplyAffineTransform(aRect, _CALayerGetTransform(aLayer, self)); +} + +- (CGRect)convertRect:(CGRect)aRect toLayer:(CALayer)aLayer +{ + return CGRectApplyAffineTransform(aRect, _CALayerGetTransform(self, aLayer)); +} + +// Hit Testing + +- (BOOL)containsPoint:(CGPoint)aPoint +{ + return _CGRectContainsPoint(_bounds, aPoint); +} + +- (CALayer)hitTest:(CGPoint)aPoint +{ + if (_isHidden) + return nil; + + var point = CGPointApplyAffineTransform(aPoint, _transformToLayer); + //alert(point.x + " " + point.y); + + if (!_CGRectContainsPoint(_bounds, point)) + return nil; + + var layer = nil, + index = _sublayers.length; + + // FIXME: this should take into account zPosition. + while (index--) + if (layer = [_sublayers[index] hitTest:point]) + return layer; + + return self; +} + +// Modifying the Delegate + +- (void)setDelegate:(id)aDelegate +{ + if (_delegate == aDelegate) + return; + + _delegate = aDelegate; + + _delegateRespondsToDisplayLayerSelector = [_delegate respondsToSelector:@selector(displayLayer:)]; + _delegateRespondsToDrawLayerInContextSelector = [_delegate respondsToSelector:@selector(drawLayer:inContext:)]; + + if (_delegateRespondsToDisplayLayerSelector || _delegateRespondsToDrawLayerInContextSelector) + [self setNeedsDisplay]; +} + +- (id)delegate +{ + return _delegate; +} + +- (void)_setOwningView:(CPView)anOwningView +{ + _owningView = anOwningView; + + if (_owningView) + { + _owningView = anOwningView; + + _bounds.size = CGSizeMakeCopy([_owningView bounds].size); + _position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y); + } + + _CALayerRecalculateGeometry(self, CALayerGeometryPositionMask | CALayerGeometryBoundsMask); +} + +- (void)_owningViewBoundsChanged +{ + _bounds.size = CGSizeMakeCopy([_owningView bounds].size); + _position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y); + + _CALayerRecalculateGeometry(self, CALayerGeometryPositionMask | CALayerGeometryBoundsMask); +} + +- (void)_update +{ + window.loop = true; + + var mask = _runLoopUpdateMask; + + if (mask & CALayerDOMUpdateMask) + _CALayerUpdateDOM(self, mask); + + if (mask & CALayerDisplayUpdateMask) + [self display]; + + else if (mask & CALayerFrameSizeUpdateMask || mask & CALayerCompositeUpdateMask) + [self composite]; + + _runLoopUpdateMask = 0; + + window.loop = false; +} + +@end + +function _CALayerUpdateSublayerTransformForSublayers(aLayer) +{ + var bounds = aLayer._bounds, + anchorPoint = aLayer._anchorPoint, + translateX = _CGRectGetWidth(bounds) * anchorPoint.x, + translateY = _CGRectGetHeight(bounds) * anchorPoint.y; + + aLayer._sublayerTransformForSublayers = CGAffineTransformConcat( + CGAffineTransformMakeTranslation(-translateX, -translateY), + CGAffineTransformConcat(aLayer._sublayerTransform, + CGAffineTransformMakeTranslation(translateX, translateY))); +} + +function _CALayerUpdateDOM(aLayer, aMask) +{ + var DOMElementStyle = aLayer._DOMElement.style; + + if (aMask & CALayerZPositionUpdateMask) + DOMElementStyle.zIndex = aLayer._zPosition; + + var frame = aLayer._backingStoreFrame; + + if (aMask & CALayerFrameOriginUpdateMask) + { + DOMElementStyle.top = ROUND(_CGRectGetMinY(frame)) + "px"; + DOMElementStyle.left = ROUND(_CGRectGetMinX(frame)) + "px"; + } + + if (aMask & CALayerFrameSizeUpdateMask) + { + var width = MAX(0.0, ROUND(_CGRectGetWidth(frame))), + height = MAX(0.0, ROUND(_CGRectGetHeight(frame))), + DOMContentsElement = aLayer._DOMContentsElement; + + DOMElementStyle.width = width + "px"; + DOMElementStyle.height = height + "px"; + + if (DOMContentsElement) + { + DOMContentsElement.width = width; + DOMContentsElement.height = height; + DOMContentsElement.style.width = width + "px"; + DOMContentsElement.style.height = height + "px"; + } + } +} + +function _CALayerRecalculateGeometry(aLayer, aGeometryChange) +{ + var bounds = aLayer._bounds, + superlayer = aLayer._superlayer, + width = _CGRectGetWidth(bounds), + height = _CGRectGetHeight(bounds), + position = aLayer._position, + anchorPoint = aLayer._anchorPoint, + affineTransform = aLayer._affineTransform, + backingStoreFrameSize = _CGSizeMakeCopy(aLayer._backingStoreFrame), + hasCustomBackingStoreFrame = aLayer._hasCustomBackingStoreFrame; + + // Go to anchor, transform, go back to bounds. + aLayer._transformFromLayer = CGAffineTransformConcat( + CGAffineTransformMakeTranslation(-width * anchorPoint.x - _CGRectGetMinX(aLayer._bounds), -height * anchorPoint.y - _CGRectGetMinY(aLayer._bounds)), + CGAffineTransformConcat(affineTransform, + CGAffineTransformMakeTranslation(position.x, position.y))); + + if (superlayer && superlayer._hasSublayerTransform) + { + // aLayer._transformFromLayer = CGAffineTransformConcat(aLayer._transformFromLayer, superlayer._sublayerTransformForSublayers); + _CGAffineTransformConcatTo(aLayer._transformFromLayer, superlayer._sublayerTransformForSublayers, aLayer._transformFromLayer); + } + + aLayer._transformToLayer = CGAffineTransformInvert(aLayer._transformFromLayer); + + //aLayer._transformFromLayer.tx = ROUND(aLayer._transformFromLayer.tx); + //aLayer._transformFromLayer.ty = ROUND(aLayer._transformFromLayer.ty); + + aLayer._frame = nil; + aLayer._standardBackingStoreFrame = [aLayer convertRect:bounds toLayer:nil]; + + if (superlayer) + { + var bounds = [superlayer bounds], + frame = [superlayer convertRect:bounds toLayer:nil]; + + aLayer._standardBackingStoreFrame.origin.x -= _CGRectGetMinX(frame); + aLayer._standardBackingStoreFrame.origin.y -= _CGRectGetMinY(frame); + } + + // We used to use CGRectIntegral here, but what we actually want, is the largest integral + // rect that would ever contain this box, since for any width/height, there are 2 (4) + // possible integral rects for it depending on it's position. It's OK that this is sometimes + // bigger than the "optimal" bounding integral rect since that doesn't change drawing. + + var origin = aLayer._standardBackingStoreFrame.origin, + size = aLayer._standardBackingStoreFrame.size; + + origin.x = FLOOR(origin.x); + origin.y = FLOOR(origin.y); + size.width = CEIL(size.width) + 1.0; + size.height = CEIL(size.height) + 1.0; + + // FIXME: This avoids the central issue that a position change is sometimes a display and sometimes + // a div move, and sometimes both. + + // Only use this frame if we don't currently have a custom backing store frame. + if (!hasCustomBackingStoreFrame) + { + var backingStoreFrame = CGRectMakeCopy(aLayer._standardBackingStoreFrame); + + // These values get rounded in the DOM, so don't both updating them if they're + // not going to be different after rounding. + if (ROUND(_CGRectGetMinX(backingStoreFrame)) != ROUND(_CGRectGetMinX(aLayer._backingStoreFrame)) || + ROUND(_CGRectGetMinY(backingStoreFrame)) != ROUND(_CGRectGetMinY(aLayer._backingStoreFrame))) + [aLayer registerRunLoopUpdateWithMask:CALayerFrameOriginUpdateMask]; + + // Any change in size due to a geometry change is purely due to rounding error. + if ((_CGRectGetWidth(backingStoreFrame) != ROUND(_CGRectGetWidth(aLayer._backingStoreFrame)) || + _CGRectGetHeight(backingStoreFrame) != ROUND(_CGRectGetHeight(aLayer._backingStoreFrame)))) + [aLayer registerRunLoopUpdateWithMask:CALayerFrameSizeUpdateMask]; + + aLayer._backingStoreFrame = backingStoreFrame; + } + + if (aGeometryChange & CALayerGeometryBoundsMask && aLayer._needsDisplayOnBoundsChange) + [aLayer setNeedsDisplay]; + // We need to recomposite if we have a custom backing store frame, OR + // If the change is not solely composed of position and anchor points changes. + // Anchor point and position changes simply move the object, requiring + // no re-rendering. + else if (hasCustomBackingStoreFrame || (aGeometryChange & ~(CALayerGeometryPositionMask | CALayerGeometryAnchorPointMask))) + [aLayer setNeedsComposite]; + + var sublayers = aLayer._sublayers, + index = 0, + count = sublayers.length; + + for (; index < count; ++index) + _CALayerRecalculateGeometry(sublayers[index], aGeometryChange); +} + +function _CALayerGetTransform(fromLayer, toLayer) +{ + var transform = CGAffineTransformMakeIdentity(); + + if (fromLayer) + { + var layer = fromLayer; + + // If we have a fromLayer, "climb up" the layer tree until + // we hit the root node or we hit the toLayer. + while (layer && layer != toLayer) + { + var transformFromLayer = layer._transformFromLayer; + + //transform = CGAffineTransformConcat(transform, layer._transformFromLayer); + _CGAffineTransformConcatTo(transform, transformFromLayer, transform); + + layer = layer._superlayer; + } + + // If we hit toLayer, then we're done. + if (layer == toLayer) + return transform; + } + + var layers = [], + layer = toLayer; + + while (layer) + { + layers.push(layer); + layer = layer._superlayer; + } + + var index = layers.length; + + while (index--) + { + var transformToLayer = layers[index]._transformToLayer; + + _CGAffineTransformConcatTo(transform, transformToLayer, transform); + } + + return transform; +} diff --git a/AppKit/CoreAnimation/CAMediaTimingFunction.j b/AppKit/CoreAnimation/CAMediaTimingFunction.j new file mode 100644 index 000000000..eb97fd140 --- /dev/null +++ b/AppKit/CoreAnimation/CAMediaTimingFunction.j @@ -0,0 +1,102 @@ +/* + * CAMediaTimingFunction.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import +import + + +kCAMediaTimingFunctionLinear = @"kCAMediaTimingFunctionLinear"; +kCAMediaTimingFunctionEaseIn = @"kCAMediaTimingFunctionEaseIn"; +kCAMediaTimingFunctionEaseOut = @"kCAMediaTimingFunctionEaseOut"; +kCAMediaTimingFunctionEaseInEaseOut = @"kCAMediaTimingFunctionEaseInEaseOut"; + +var CAMediaNamedTimingFunctions = nil; + +@implementation CAMediaTimingFunction : CPObject +{ + float _c1x; + float _c1y; + float _c2x; + float _c2y; +} + ++ (id)functionWithName:(CPString)aName +{ + if (!CAMediaNamedTimingFunctions) + { + CAMediaNamedTimingFunctions = [CPDictionary dictionary]; + + [CAMediaNamedTimingFunctions setObject:[CAMediaTimingFunction functionWithControlPoints:0.0 :0.0 :1.0 :1.0] forKey:kCAMediaTimingFunctionLinear]; + [CAMediaNamedTimingFunctions setObject:[CAMediaTimingFunction functionWithControlPoints:0.42 :0.0 :1.0 :1.0] forKey:kCAMediaTimingFunctionEaseIn]; + [CAMediaNamedTimingFunctions setObject:[CAMediaTimingFunction functionWithControlPoints:0.0 :0.0 :0.58 :1.0] forKey:kCAMediaTimingFunctionEaseOut]; + [CAMediaNamedTimingFunctions setObject:[CAMediaTimingFunction functionWithControlPoints:0.42 :0.0 :0.58 :1.0] forKey:kCAMediaTimingFunctionEaseInEaseOut]; + } + + return [CAMediaNamedTimingFunctions objectForKey:aName]; +} + ++ (id)functionWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y +{ + return [[self alloc] initWithControlPoints:c1x :c1y :c2x :c2y]; +} + +- (id)initWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y +{ + self = [super init]; + + if (self) + { + _c1x = c1x; + _c1y = c1y; + _c2x = c2x; + _c2y = c2y; + } + + return self; +} + +- (void)getControlPointAtIndex:(unsigned)anIndex values:(float[2])reference +{ + if (anIndex == 0) + { + reference[0] = 0; + reference[1] = 0; + } + else if (anIndex == 1) + { + reference[0] = _c1x; + reference[1] = _c1y; + } + else if (anIndex == 2) + { + reference[0] = _c2x; + reference[1] = _c2y; + } + else + { + reference[0] = 1.0; + reference[0] = 1.0; + } +} + +@end diff --git a/AppKit/CoreGraphics/CGAffineTransform.h b/AppKit/CoreGraphics/CGAffineTransform.h new file mode 100644 index 000000000..1b3fc9266 --- /dev/null +++ b/AppKit/CoreGraphics/CGAffineTransform.h @@ -0,0 +1,62 @@ +/* + * CGAffineTransform.h + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "CGGeometry.h" + +#define _CGAffineTransformMake(a_, b_, c_, d_, tx_, ty_) { a:a_, b:b_, c:c_, d:d_, tx:tx_, ty:ty_ } +#define _CGAffineTransformMakeIdentity() _CGAffineTransformMake(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) +#define _CGAffineTransformMakeCopy(aTransform) _CGAffineTransformMake(aTransform.a, aTransform.b, aTransform.c, aTransform.d, aTransform.tx, aTransform.ty) + +#define _CGAffineTransformMakeScale(sx, sy) _CGAffineTransformMake(sx, 0.0, 0.0, sy, 0.0, 0.0) +#define _CGAffineTransformMakeTranslation(tx, ty) _CGAffineTransformMake(1.0, 0.0, 0.0, 1.0, tx, ty) + +#define _CGAffineTransformTranslate(aTransform, tx, ty) _CGAffineTransformMake(aTransform.a, aTransform.b, aTransform.c, aTransform.d, aTransform.tx + aTransform.a * tx + aTransform.c * ty, aTransform.ty + aTransform.b * tx + aTransform.d * ty) +#define _CGAffineTransformScale(aTransform, sx, sy) _CGAffineTransformMake(aTransform.a * sx, aTransform.b * sx, aTransform.c * sy, aTransform.d * sy, aTransform.tx, aTransform.ty) + +#define _CGAffineTransformConcat(lhs, rhs) _CGAffineTransformMake(lhs.a * rhs.a + lhs.b * rhs.c, lhs.a * rhs.b + lhs.b * rhs.d, lhs.c * rhs.a + lhs.d * rhs.c, lhs.c * rhs.b + lhs.d * rhs.d, lhs.tx * rhs.a + lhs.ty * rhs.c + rhs.tx, lhs.tx * rhs.b + lhs.ty * rhs.d + rhs.ty) + +#define _CGPointApplyAffineTransform(aPoint, aTransform) _CGPointMake(aPoint.x * aTransform.a + aPoint.y * aTransform.c + aTransform.tx, aPoint.x * aTransform.b + aPoint.y * aTransform.d + aTransform.ty) +#define _CGSizeApplyAffineTransform(aSize, aTransform) _CGSizeMake(aSize.width * aTransform.a + aSize.height * aTransform.c, aSize.width * aTransform.b + aSize.height * aTransform.d) +#define _CGRectApplyAffineTransform(aRect, aTransform) { origin:_CGPointApplyAffineTransform(aRect.origin, aTransform), size:_CGSizeApplyAffineTransform(aRect.size, aTransform) } + +#define _CGAffineTransformIsIdentity(aTransform) (aTransform.a == 1 && aTransform.b == 0 && aTransform.c == 0 && aTransform.d == 1 && aTransform.tx == 0 && aTransform.ty == 0) +#define _CGAffineTransformEqualToTransform(lhs, rhs) (lhs.a == rhs.a && lhs.b == rhs.b && lhs.c == rhs.c && lhs.d == rhs.d && lhs.tx == rhs.tx && lhs.ty == rhs.ty) + +#define _CGStringCreateWithCGAffineTransform(aTransform) (" [[ " + aTransform.a + ", " + aTransform.b + ", 0 ], [ " + aTransform.c + ", " + aTransform.d + ", 0 ], [ " + aTransform.tx + ", " + aTransform.ty + ", 1]]") + +#define _CGAffineTransformConcatTo(lhs, rhs, to) \ +var tx = lhs.tx * rhs.a + lhs.ty * rhs.c + rhs.tx;\ +to.ty = lhs.tx * rhs.b + lhs.ty * rhs.d + rhs.ty;\ +to.tx = tx;\ +var a = lhs.a * rhs.a + lhs.b * rhs.c,\ + b = lhs.a * rhs.b + lhs.b * rhs.d,\ + c = lhs.c * rhs.a + lhs.d * rhs.c;\ +to.d = lhs.c * rhs.b + lhs.d * rhs.d;\ +to.a = a;\ +to.b = b;\ +to.c = c;\ + +/* +a b 0 cos sin 0 +c d 0 -sin cos 0 +tx ty 1 0 0 1 +*/ diff --git a/AppKit/CoreGraphics/CGAffineTransform.j b/AppKit/CoreGraphics/CGAffineTransform.j new file mode 100644 index 000000000..2bd7e39be --- /dev/null +++ b/AppKit/CoreGraphics/CGAffineTransform.j @@ -0,0 +1,112 @@ +/* + * CGAffineTransform.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "CGGeometry.h" +#include "CGAffineTransform.h" + +#define _function(inline) function inline { return _##inline; } + +import "CGGeometry.j" + +_function(CGAffineTransformMake(a, b, c, d, tx, ty)) +_function(CGAffineTransformMakeIdentity()) +_function(CGAffineTransformMakeCopy(anAffineTransform)) + +_function(CGAffineTransformMakeScale(sx, sy)) +_function(CGAffineTransformMakeTranslation(tx, ty)) +_function(CGAffineTransformTranslate(aTransform, tx, ty)) +_function(CGAffineTransformScale(aTransform, sx, sy)) + +_function(CGAffineTransformConcat(lhs, rhs)) +_function(CGPointApplyAffineTransform(aPoint, aTransform)) +_function(CGSizeApplyAffineTransform(aSize, aTransform)) + +_function(CGAffineTransformIsIdentity(aTransform)) +_function(CGAffineTransformEqualToTransform(lhs, rhs)) + +_function(CGStringCreateWithCGAffineTransform(aTransform)) + +// FIXME: !!!! +function CGAffineTransformCreateCopy(aTransform) +{ + return _CGAffineTransformMakeCopy(aTransform); +} + +function CGAffineTransformMakeRotation(anAngle) +{ + var sin = SIN(anAngle), + cos = COS(anAngle); + + return _CGAffineTransformMake(cos, sin, -sin, cos, 0.0, 0.0); +} + +function CGAffineTransformRotate(aTransform, anAngle) +{ + var sin = SIN(anAngle), + cos = COS(anAngle); + + return { + a:aTransform.a * cos + aTransform.c * sin, + b:aTransform.b * cos + aTransform.d * sin, + c:aTransform.c * cos - aTransform.a * sin, + d:aTransform.d * cos - aTransform.b * sin, + tx:aTransform.tx, + ty:aTransform.ty + }; +} + +function CGAffineTransformInvert(aTransform) +{ + var determinant = 1 / (aTransform.a * aTransform.d - aTransform.b * aTransform.c); + + return { + a:determinant * aTransform.d, + b:-determinant * aTransform.b, + c:-determinant * aTransform.c, + d:determinant * aTransform.a, + tx:determinant * (aTransform.c * aTransform.ty - aTransform.d * aTransform.tx), + ty:determinant * (aTransform.b * aTransform.tx - aTransform.a * aTransform.ty) + }; +} + +function CGRectApplyAffineTransform(aRect, anAffineTransform) +{ + var top = _CGRectGetMinY(aRect), + left = _CGRectGetMinX(aRect), + right = _CGRectGetMaxX(aRect), + bottom = _CGRectGetMaxY(aRect), + topLeft = CGPointApplyAffineTransform(_CGPointMake(left, top), anAffineTransform), + topRight = CGPointApplyAffineTransform(_CGPointMake(right, top), anAffineTransform), + bottomLeft = CGPointApplyAffineTransform(_CGPointMake(left, bottom), anAffineTransform), + bottomRight = CGPointApplyAffineTransform(_CGPointMake(right, bottom), anAffineTransform), + minX = MIN(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x), + maxX = MAX(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x), + minY = MIN(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y), + maxY = MAX(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y); + + return _CGRectMake(minX, minY, (maxX - minX), (maxY - minY)); +} + +function CPStringFromCGAffineTransform(anAffineTransform) +{ + return '{' + anAffineTransform.a + ", " + anAffineTransform.b + ", " + anAffineTransform.c + ", " + anAffineTransform.d + ", " + anAffineTransform.tx + ", " + anAffineTransform.ty + '}'; +} diff --git a/AppKit/CoreGraphics/CGColor.j b/AppKit/CoreGraphics/CGColor.j new file mode 100644 index 000000000..a5838e87f --- /dev/null +++ b/AppKit/CoreGraphics/CGColor.j @@ -0,0 +1,188 @@ +/* + * CGColor.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +//import "CGPattern.j" +import "CGColorSpace.j" + +// FIXME: Move this to Objective-J.js!!! +var CFTypeGlobalCount = 0; + +function CFHashCode(aCFObject) +{ + if (!aCFObject.hash) + aCFObject.hash = ++CFTypeGlobalCount; + + return aCFObject; +} + +kCGColorWhite = "kCGColorWhite"; +kCGColorBlack = "kCGColorBlack"; +kCGColorClear = "kCGColorClear"; + +var _CGColorMap = { }; + +function CGColorGetConstantColor(aColorName) +{ + alert("FIX ME"); +} + +function CGColorRetain(aColor) +{ + return aColor; +} + +function CGColorRelease() +{ +} + +function CGColorCreate(aColorSpace, components) +{ + if (!aColorSpace || !components) + return NULL; + + var components = components.slice(); + + CGColorSpaceStandardizeComponents(aColorSpace, components); + + var UID = CFHashCode(aColorSpace) + components.join(""); + + if (_CGColorMap[UID]) + return _CGColorMap[UID]; + + return _CGColorMap[UID] = { colorspace:aColorSpace, pattern:NULL, components:components }; +} + +function CGColorCreateCopy(aColor) +{ + // Colors should be treated as immutable, so don't mutate it! + return aColor; +} + +function CGColorCreateGenericGray(gray, alpha) +{ + return CGColorCreate(0, [gray, alpha]); +} + +function CGColorCreateGenericRGB(red, green, blue, alpha) +{ + return CGColorCreate(0, [red, green, blue, alpha]); +} + +function CGColorCreateGenericCMYK(cyan, magenta, yellow, black, alpha) +{ + return CGColorCreate(0, [cyan, magenta, yellow, black, alpha]); +} + +function CGColorCreateCopyWithAlpha(aColor, anAlpha) +{ + var components = aColor.components; + + if (!aColor || anAlpha == components[components.length - 1]) + return aColor; + + if (aColor.pattern) + var copy = CGColorCreateWithPattern(aColor.colorspace, aColor.pattern, components); + else + var copy = CGColorCreate(aColor.colorspace, components); + + copy.components[components.length - 1] = anAlpha; + + return copy; +} + +function CGColorCreateWithPattern(aColorSpace, aPattern, components) +{ + if (!aColorSpace || !aPattern || !components) + return NULL; + + return { colorspace:aColorSpace, pattern:aPattern, components:components.slice() }; +} + +function CGColorEqualToColor(lhs, rhs) +{ + if (lhs == rhs) + return true; + + if (!lhs || !rhs) + return false; + + var lhsComponents = lhs.components, + rhsComponents = rhs.components, + lhsComponentCount = lhsComponents.length; + + if (lhsComponentCount != rhsComponents.length) + return false; + + while (lhsComponentCount--) + if (lhsComponents[lhsComponentCount] != rhsComponents[lhsComponentCount]) + return false; + + if (lhs.pattern != rhs.pattern) + return false; + + if (CGColorSpaceEqualToColorSpace(lhs.colorspace, rhs.colorspace)) + return false; + + return true; +} + +function CGColorGetAlpha(aColor) +{ + var components = aColor.components; + + return components[components.length - 1]; +} + +function CGColorGetColorSpace(aColor) +{ + return aColor.colorspace; +} + +function CGColorGetComponents(aColor) +{ + return aColor.components; +} + +function CGColorGetNumberOfComponents(aColor) +{ + return aColor.components.length; +} + +function CGColorGetPattern(aColor) +{ + return aColor.pattern; +} + +/* var components = aColor.components; + + case : _CGCSSForColor[CFGetHash(aColor)] = "rgba(" + ROUND(components[0] * 255.0) + ',' + ROUND(components[0] * 255.0) + ',' ROUND(components[0] * 255.0) + ',' + ROUND(components[0] * 255.0); + _cssString = (hasAlpha ? "rgba(" : "rgb(") + + parseInt(_components[0] * 255.0) + ", " + + parseInt(_components[1] * 255.0) + ", " + + parseInt(_components[2] * 255.0) + + (hasAlpha ? (", " + _components[3]) : "") + ")"; + +function CFStringFromColor() +{ + +} +*/ diff --git a/AppKit/CoreGraphics/CGColorSpace.j b/AppKit/CoreGraphics/CGColorSpace.j new file mode 100644 index 000000000..6befbcf82 --- /dev/null +++ b/AppKit/CoreGraphics/CGColorSpace.j @@ -0,0 +1,212 @@ +/* + * CGColorSpace.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +kCGColorSpaceModelUnknown = -1; +kCGColorSpaceModelMonochrome = 0; +kCGColorSpaceModelRGB = 1; +kCGColorSpaceModelCMYK = 2; +kCGColorSpaceModelLab = 3; +kCGColorSpaceModelDeviceN = 4; +kCGColorSpaceModelIndexed = 5; +kCGColorSpaceModelPattern = 6; + +kCGColorSpaceGenericGray = "CGColorSpaceGenericGray"; +kCGColorSpaceGenericRGB = "CGColorSpaceGenericRGB"; +kCGColorSpaceGenericCMYK = "CGColorSpaceGenericCMYK"; +kCGColorSpaceGenericRGBLinear = "CGColorSpaceGenericRGBLinear"; +kCGColorSpaceGenericRGBHDR = "CGColorSpaceGenericRGBHDR"; +kCGColorSpaceAdobeRGB1998 = "CGColorSpaceAdobeRGB1998"; +kCGColorSpaceSRGB = "CGColorSpaceSRGB"; + +var _CGNamedColorSpaces = {}; + +#define _CGColorSpaceCreateWithModel(aModel, aComponentCount, aBaseColorSpace) \ + { model:aModel, count:aComponentCount, base:aBaseColorSpace } + +function CGColorSpaceCreateCalibratedGray(aWhitePoint, aBlackPoint, gamma) +{ + return _CGColorSpaceCreateWithModel(kCGColorSpaceModelMonochrome, 1, NULL); +} + +function CGColorSpaceCreateCalibratedRGB(aWhitePoint, aBlackPoint, gamma) +{ + return _CGColorSpaceCreateWithModel(kCGColorSpaceModelRGB, 1, NULL); +} + +function CGColorSpaceCreateICCBased(aComponentCount, range, profile, alternate) +{ + // FIXME: Do we need to support this? + return NULL; +} + +function CGColorSpaceCreateLab(aWhitePoint, aBlackPoint, aRange) +{ + // FIXME: Do we need to support this? + return NULL; +} + +function CGColorSpaceCreateDeviceCMYK() +{ + return CGColorSpaceCreateWithName(kCGColorSpaceGenericCMYK); +} + +function CGColorSpaceCreateDeviceGray() +{ + return CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); +} + +function CGColorSpaceCreateDeviceRGB() +{ + return CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); +} + +function CGColorSpaceCreateWithPlatformColorSpace() +{ + // FIXME: This for sure we don't need. + return NULL; +} + +function CGColorSpaceCreateIndexed(aBaseColorSpace, lastIndex, colorTable) +{ + // FIXME: Do we need to support this? + return NULL; +} + +function CGColorSpaceCreatePattern(aBaseColorSpace) +{ + if (aBaseColorSpace) + return _CGColorSpaceCreateWithModel(kCGColorSpaceModelPattern, aBaseColorSpace.count, aBaseColorSpace); + + return _CGColorSpaceCreateWithModel(kCGColorSpaceModelPattern, 0, NULL); +} + +function CGColorSpaceCreateWithName(aName) +{ + var colorSpace = _CGNamedColorSpaces[aName]; + + if (colorSpace) + return colorSpace; + + switch (aName) + { + case kCGColorSpaceGenericGray: return _CGNamedColorSpaces[aName] = _CGColorSpaceCreateWithModel(kCGColorSpaceModelMonochrome, 1, NULL); + case kCGColorSpaceGenericRGB: return _CGNamedColorSpaces[aName] = _CGColorSpaceCreateWithModel(kCGColorSpaceModelRGB, 3, NULL); + case kCGColorSpaceGenericCMYK: return _CGNamedColorSpaces[aName] = _CGColorSpaceCreateWithModel(kCGColorSpaceModelCMYK, 4, NULL); + case kCGColorSpaceGenericRGBLinear: return _CGNamedColorSpaces[aName] = _CGColorSpaceCreateWithModel(kCGColorSpaceModelRGB, 3, NULL); + case kCGColorSpaceGenericRGBHDR: return _CGNamedColorSpaces[aName] = _CGColorSpaceCreateWithModel(kCGColorSpaceModelRGB, 3, NULL); + case kCGColorSpaceAdobeRGB1998: return _CGNamedColorSpaces[aName] = _CGColorSpaceCreateWithModel(kCGColorSpaceModelRGB, 3, NULL); + case kCGColorSpaceSRGB: return _CGNamedColorSpaces[aName] = _CGColorSpaceCreateWithModel(kCGColorSpaceModelRGB, 3, NULL); + } + + return NULL; +} + +// Getting Information About Color Spaces + +function CGColorSpaceCopyICCProfile(aColorSpace) +{ + return NULL; +} + +function CGColorSpaceGetNumberOfComponents(aColorSpace) +{ + return aColorSpace.count; +} + +function CGColorSpaceGetTypeID(aColorSpace) +{ +} + +function CGColorSpaceGetModel(aColorSpace) +{ + return aColorSpace.model; +} + +function CGColorSpaceGetBaseColorSpace(aColorSpace) +{ +} + +function CGColorSpaceGetColorTableCount(aColorSpace) +{ +} + +function CGColorSpaceGetColorTable(aColorSpace) +{ +} + +// Retaining and Releasing Color Spaces + +function CGColorSpaceRelease(aColorSpace) +{ +} + +function CGColorSpaceRetain(aColorSpace) +{ + return aColorSpace; +} + +// FIXME: We should refer to some default values. +#define STANDARDIZE(components, index, minimum, maximum, multiplier) \ +{ \ + if (index > components.length) \ + { \ + components[index] = maximum; \ + return; \ + } \ +\ + var component = components[index]; \ + \ + if (component < minimum) \ + components[index] = minimum; \ + else if (component > maximum) \ + components[index] = maximum; \ + else \ + components[index] = ROUND(component * multiplier) / multiplier; \ +} + +function CGColorSpaceStandardizeComponents(aColorSpace, components) +{ + var count = aColorSpace.count; + + // Standardize the alpha value. We allow the alpha value to have a + // higher precision than other components since it is not ultimately + // bound to 256 bits like RGB. + STANDARDIZE(components, count, 0, 1, 1000); + + if (aColorSpace.base) + aColorSpace = aColorSpace.base; + + switch (aColorSpace.model) + { + case kCGColorSpaceModelMonochrome: + case kCGColorSpaceModelRGB: + case kCGColorSpaceModelCMYK: + case kCGColorSpaceModelDeviceN: while (count--) + STANDARDIZE(components, count, 0, 1, 255); + break; + + // We don't currently support these color spaces. + case kCGColorSpaceModelIndexed: + case kCGColorSpaceModelLab: + case kCGColorSpaceModelPattern: break; + } +} diff --git a/AppKit/CoreGraphics/CGContext.j b/AppKit/CoreGraphics/CGContext.j new file mode 100644 index 000000000..ed73a0539 --- /dev/null +++ b/AppKit/CoreGraphics/CGContext.j @@ -0,0 +1,438 @@ +/* + * CGContext.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "CGGeometry.h" +#include "CGAffineTransform.h" + +import "CGGeometry.j" +import "CGAffineTransform.j" +import "CGPath.j" + +kCGLineCapButt = 0; +kCGLineCapRound = 1; +kCGLineCapSquare = 2; + +kCGLineJoinMiter = 0; +kCGLineJoinRound = 1; +kCGLineJoinBevel = 2; + +kCGPathFill = 0; +kCGPathEOFill = 1; +kCGPathStroke = 2; +kCGPathFillStroke = 3; +kCGPathEOFillStroke = 4; + +kCGBlendModeNormal = 0; +kCGBlendModeMultiply = 1; +kCGBlendModeScreen = 2; +kCGBlendModeOverlay = 3; +kCGBlendModeDarken = 4; +kCGBlendModeLighten = 5; +kCGBlendModeColorDodge = 6; +kCGBlendModeColorBurn = 7; +kCGBlendModeSoftLight = 8; +kCGBlendModeHardLight = 9; +kCGBlendModeDifference = 10; +kCGBlendModeExclusion = 11; +kCGBlendModeHue = 12; +kCGBlendModeSaturation = 13; +kCGBlendModeColor = 14; +kCGBlendModeLuminosity = 15; +kCGBlendModeClear = 16; +kCGBlendModeCopy = 17; +kCGBlendModeSourceIn = 18; +kCGBlendModeSourceOut = 19; +kCGBlendModeSourceAtop = 20; +kCGBlendModeDestinationOver = 21; +kCGBlendModeDestinationIn = 22; +kCGBlendModeDestinationOut = 23; +kCGBlendModeDestinationAtop = 24; +kCGBlendModeXOR = 25; +kCGBlendModePlusDarker = 26; +kCGBlendModePlusLighter = 27; + +function CGContextRelease() +{ +} + +function CGContextRetain(aContext) +{ + return aContext; +} + +if (!CPFeatureIsCompatible(CPHTMLCanvasFeature)) +{ + +function CGGStateCreate() +{ + return { strokeStyle:"#000", fillStyle:"#ccc", lineWidth:1.0, lineJoin:kCGLineJoinMiter, lineCap:kCGLineCapButt, miterLimit:10.0, globalAlpha:1.0, + blendMode:kCGBlendModeNormal, + shadowOffset:_CGSizeMakeZero(), shadowBlur:0.0, shadowColor:NULL, CTM:_CGAffineTransformMakeIdentity() }; +} + +function CGGStateCreateCopy(aGState) +{ + return { strokeStyle:aGState.strokeStyle, fillStyle:aGState.fillStyle, lineWidth:aGState.lineWidth, + lineJoin:aGState.lineJoin, lineCap:aGState.lineCap, miterLimit:aGState.miterLimit, globalAlpha:aGState.globalAlpha, + blendMode:aGState.blendMode, + shadowOffset:aGState.shadowOffset, shadowBlur:aGState.shadowBlur, shadowColor:aGState.shadowColor, CTM:_CGAffineTransformMakeCopy(aGState.CTM) }; +} + +function CGBitmapGraphicsContextCreate() +{ + return { DOMElement:document.createElement("div"), path:NULL, gState:CGGStateCreate(), gStateStack:[] }; +} + +function CGContextSaveGState(aContext) +{ + aContext.gStateStack.push(CGGStateCreateCopy(aContext.gState)); +} + +function CGContextRestoreGState(aContext) +{ + aContext.gState = aContext.gStateStack.pop(); +} + +function CGContextSetLineCap(aContext, aLineCap) +{ + aContext.gState.lineCap = aLineCap; +} + +function CGContextSetLineJoin(aContext, aLineJoin) +{ + aContext.gState.lineJoin = aLineJoin; +} + +function CGContextSetLineWidth(aContext, aLineWidth) +{ + aContext.gState.lineWidth = aLineWidth; +} + +function CGContextSetMiterLimit(aContext, aMiterLimit) +{ + aContext.gState.miterLimit = aMiterLimit; +} + +function CGContextSetBlendMode(aContext, aBlendMode) +{ + aContext.gState.blendMode = aBlendMode; +} + +function CGContextAddArc(aContext, x, y, radius, startAngle, endAngle, clockwise) +{ + CGPathAddArc(aContext.path, aContext.gState.CTM, x, y, radius, startAngle, endAngle, clockwise); +} + +function CGContextAddArcToPoint(aContext, x1, y1, x2, y2, radius) +{ + CGPathAddArcToPoint(aContext.path, aContext.gState.CTM, x1, y1, x2, y2, radius); +} + +function CGContextAddCurveToPoint(aContext, cp1x, cp1y, cp2x, cp2y, x, y) +{ + CGPathAddCurveToPoint(aContext.path, aContext.gState.CTM, cp1x, cp1y, cp2x, cp2y, x, y); +} + +function CGContextAddLines(aContext, points, count) +{ + CGPathAddLines(aContext.path, aContext.gState.CTM, points, count); +} + +function CGContextAddLineToPoint(aContext, x, y) +{ + CGPathAddLineToPoint(aContext.path, aContext.gState.CTM, x, y); +} + +function CGContextAddPath(aContext, aPath) +{ + if (!aContext || CGPathIsEmpty(aPath)) + return; + + if (!aContext.path) + aContext.path = CGPathCreateMutable(); + + CGPathAddPath(aContext.path, aContext.gState.CTM, aPath); +} + +function CGContextAddQuadCurveToPoint(aContext, cpx, cpy, x, y) +{ + CGPathAddQuadCurveToPoint(aContext.path, aContext.gState.CTM, cpx, cpy, x, y); +} + +function CGContextAddRect(aContext, aRect) +{ + CGPathAddRect(aContext.path, aContext.gState.CTM, aRect); +} + +function CGContextAddRects(aContext, rects, count) +{ + CGPathAddRects(aContext.path, aContext.gState.CTM, rects, count); +} + +function CGContextBeginPath(aContext) +{ + // This clears any previous path. + aContext.path = CGPathCreateMutable(); +} + +function CGContextClosePath(aContext) +{ + CGPathCloseSubpath(aContext.path); +} + +function CGContextMoveToPoint(aContext, x, y) +{ + if (!aContext.path) + aContext.path = CGPathCreateMutable(); + + CGPathMoveToPoint(aContext.path, aContext.gState.CTM, x, y); +} + +function CGContextFillRect(aContext, aRect) +{ + CGContextFillRects(aContext, [aRect], 1); +} + +function CGContextFillRects(aContext, rects, count) +{ + if (arguments["count"] == NULL) + var count = rects.length; + + CGContextBeginPath(aContext); + CGContextAddRects(aContext, rects, count); + CGContextClosePath(aContext); + + CGContextDrawPath(aContext, kCGPathFill); +} + +function CGContextStrokeRect(aContext, aRect) +{ + CGContextBeginPath(aContext); + CGContextAddRect(aContext, aRect); + CGContextClosePath(aContext); + + CGContextDrawPath(aContext, kCGPathStroke); +} + +function CGContextStrokeRectWithWidth(aContext, aRect, aWidth) +{ + CGContextSaveGState(aContext); + + CGContextSetLineWidth(aContext, aWidth); + CGContextStrokeRect(aContext, aRect); + + CGContextRestoreGState(aContext); +} + +function CGContextConcatCTM(aContext, aTransform) +{ + var CTM = aContext.gState.CTM; + + _CGAffineTransformConcatTo(CTM, aTransform, CTM); +} + +function CGContextGetCTM(aContext) +{ + return aContext.gState.CTM; +} + +function CGContextRotateCTM(aContext, anAngle) +{ + var gState = aContext.gState; + + gState.CTM = CGAffineTransformRotate(gState.CTM, anAngle); +} + +function CGContextScaleCTM(aContext, sx, sy) +{ + var gState = aContext.gState; + + gState.CTM = _CGAffineTransformScale(gState.CTM, sx, sy); +} + +function CGContextTranslateCTM(aContext, tx, ty) +{ + var gState = aContext.gState; + + gState.CTM = _CGAffineTransformTranslate(gState.CTM, tx, ty); +} + +function CGContextSetShadow(aContext, aSize, aBlur) +{ + var gState = aContext.gState; + + gState.shadowOffset = _CGSizeMakeCopy(aSize); + gState.shadowBlur = aBlur; + gState.shadowColor = [CPColor shadowColor]; +} + +function CGContextSetShadowWithColor(aContext, aSize, aBlur, aColor) +{ + var gState = aContext.gState; + + gState.shadowOffset = _CGSizeMakeCopy(aSize); + gState.shadowBlur = aBlur; + gState.shadowColor = aColor; +} + +} + +// GOOD. + +function CGContextEOFillPath(aContext, aMode) +{ + CGContextDrawPath(aContext, kCGPathEOFill); +} + +function CGContextFillPath(aContext) +{ + CGContextDrawPath(aContext, kCGPathFill); +} + +var KAPPA = 4.0 * ((SQRT2 - 1.0) / 3.0); + +function CGContextAddEllipseInRect(aContext, aRect) +{ + CGContextBeginPath(aContext); + + if (_CGRectGetWidth(aRect) == _CGRectGetHeight(aRect)) + CGContextAddArc(aContext, _CGRectGetMidX(aRect), _CGRectGetMidY(aRect), _CGRectGetWidth(aRect) / 2.0, 0.0, 2 * PI, YES); + else + { + var axis = _CGSizeMake(_CGRectGetWidth(aRect) / 2.0, _CGRectGetHeight(aRect) / 2.0), + center = _CGPointMake(_CGRectGetMinX(aRect) + axis.width, _CGRectGetMinY(aRect) + axis.height); + + CGContextMoveToPoint(aContext, center.x, center.y - axis.height); + + CGContextAddCurveToPoint(aContext, center.x + (KAPPA * axis.width), center.y - axis.height, center.x + axis.width, center.y - (KAPPA * axis.height), center.x + axis.width, center.y); + CGContextAddCurveToPoint(aContext, center.x + axis.width, center.y + (KAPPA * axis.height), center.x + (KAPPA * axis.width), center.y + axis.height, center.x, center.y + axis.height); + CGContextAddCurveToPoint(aContext, center.x - (KAPPA * axis.width), center.y + axis.height, center.x - axis.width, center.y + (KAPPA * axis.height), center.x - axis.width, center.y); + CGContextAddCurveToPoint(aContext, center.x - axis.width, center.y - (KAPPA * axis.height), center.x - (KAPPA * axis.width), center.y - axis.height, center.x, center.y - axis.height); + } + + CGContextClosePath(aContext); +} + + +function CGContextFillEllipseInRect(aContext, aRect) +{ + CGContextAddEllipseInRect(aContext, aRect); + CGContextFillPath(aContext); +} + +function CGContextStrokeEllipseInRect(aContext, aRect) +{ + CGContextAddEllipseInRect(aContext, aRect); + CGContextStrokePath(aContext); +} + +function CGContextStrokePath(aContext) +{ + CGContextDrawPath(aContext, kCGPathStroke); +} + +function CGContextStrokeLineSegments(aContext, points, count) +{ + var i = 0; + + if (arguments["count"] == NULL) + var count = points.length; + + CGContextBeginPath(aContext); + + for (; i < count; i += 2) + { + CGContextMoveToPoint(aContext, points[i].x, points[i].y); + CGContextAddLineToPoint(aContext, points[i + 1].x, points[i + 1].y); + } + + CGContextStrokePath(aContext); +} + +// FIXME: THIS IS WRONG!!! + +function CGContextSetFillColor(aContext, aColor) +{ + if (aColor) + aContext.gState.fillStyle = [aColor cssString]; +} + +function CGContextSetStrokeColor(aContext, aColor) +{ + if (aColor) + aContext.gState.strokeStyle = [aColor cssString]; +} + +function CGContextFillRoundedRectangleInRect(aContext, aRect, aRadius, ne, se, sw, nw) +{ + var xMin = _CGRectGetMinX(aRect), + xMax = _CGRectGetMaxX(aRect), + yMin = _CGRectGetMinY(aRect), + yMax = _CGRectGetMaxY(aRect); + + CGContextBeginPath(aContext); + CGContextMoveToPoint(aContext, xMin + aRadius, yMin); + + if (ne) + { + CGContextAddLineToPoint(aContext, xMax - aRadius, yMin); + CGContextAddCurveToPoint(aContext, xMax - aRadius, yMin, xMax, yMin, xMax, yMin + aRadius); + } + else + CGContextAddLineToPoint(aContext, xMax, yMin); + + if (se) + { + CGContextAddLineToPoint(aContext, xMax, yMax - aRadius); + CGContextAddCurveToPoint(aContext, xMax, yMax - aRadius, xMax, yMax, xMax - aRadius, yMax); + } + else + CGContextAddLineToPoint(aContext, xMax, yMax); + + if (sw) + { + CGContextAddLineToPoint(aContext, xMin + aRadius, yMax); + CGContextAddCurveToPoint(aContext, xMin + aRadius, yMax, xMin, yMax, xMin, yMax - aRadius); + } + else + CGContextAddLineToPoint(aContext, xMin, yMax); + + if (nw) + { + CGContextAddLineToPoint(aContext, xMin, yMin + aRadius); + CGContextAddCurveToPoint(aContext, xMin, yMin + aRadius, xMin, yMin, xMin + aRadius, yMin); + } else + CGContextAddLineToPoint(aContext, xMin, yMin); + + CGContextClosePath(aContext); + + CGContextFillPath(aContext); +} + +if (CPFeatureIsCompatible(CPHTMLCanvasFeature)) +{ +#include "CGContextCanvas.j" +} +else if (CPFeatureIsCompatible(CPVMLFeature)) +{ +#include "CGContextVML.j" +} diff --git a/AppKit/CoreGraphics/CGContextCanvas.j b/AppKit/CoreGraphics/CGContextCanvas.j new file mode 100644 index 000000000..20cfc026a --- /dev/null +++ b/AppKit/CoreGraphics/CGContextCanvas.j @@ -0,0 +1,433 @@ +/* + * CGContextCanvas.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +var CANVAS_LINECAP_TABLE = [ "butt", "round", "square" ], + CANVAS_LINEJOIN_TABLE = [ "miter", "round", "bevel" ], + CANVAS_COMPOSITE_TABLE = [ "source-over", "source-over", "source-over", "source-over", "darker", + "lighter", "source-over", "source-over", "source-over", "source-over", + "source-over", "source-over", "source-over", "source-over", "source-over", + "source-over", "source-over", + "copy", "source-in", "source-out", "source-atop", + "destination-over", "destination-in", "destination-out", "destination-atop", + "xor", "source-over", "source-over" ]; + +#define _CGContextAddArcCanvas(aContext, x, y, radius, startAngle, endAngle, anticlockwise) aContext.arc(x, y, radius, startAngle, endAngle, anticlockwise) +#define _CGContextAddArcToPointCanvas(aContext, x1, y1, x2, y2, radius) aContext.arcTo(x1, y1, x2, y2, radius) +#define _CGContextAddCurveToPointCanvas(aContext, cp1x, cp1y, cp2x, cp2y, x, y) aContext.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) +#define _CGContextAddLineToPointCanvas(aContext, x, y) aContext.lineTo(x, y) +#define _CGContextClosePathCanvas(aContext) aContext.closePath() +#define _CGContextMoveToPointCanvas(aContext, x, y) aContext.moveTo(x, y) + +#define _CGContextAddRectCanvas(aContext, aRect) aContext.rect(_CGRectGetMinX(aRect), _CGRectGetMinY(aRect), _CGRectGetWidth(aRect), _CGRectGetHeight(aRect)) +#define _CGContextBeginPathCanvas(aContext) aContext.beginPath() +#define _CGContextFillRectCanvas(aContext, aRect) aContext.fillRect(_CGRectGetMinX(aRect), _CGRectGetMinY(aRect), _CGRectGetWidth(aRect), _CGRectGetHeight(aRect)) +#define _CGContextClipCanvas(aContext) aContext.clip() + +function CGContextSaveGState(aContext) +{ + aContext.save(); +} + +function CGContextRestoreGState(aContext) +{ + aContext.restore(); +} + +function CGContextSetLineCap(aContext, aLineCap) +{ + aContext.lineCap = CANVAS_LINECAP_TABLE[aLineCap]; +} + +function CGContextSetLineJoin(aContext, aLineJoin) +{ + aContext.lineJoin = CANVAS_LINEJOIN_TABLE[aLineJoin]; +} + +function CGContextSetLineWidth(aContext, aLineWidth) +{ + aContext.lineWidth = aLineWidth; +} + +function CGContextSetMiterLimit(aContext, aMiterLimit) +{ + aContext.miterLimit = aMiterLimit; +} + +function CGContextSetBlendMode(aContext, aBlendMode) +{ + aContext.globalCompositeOperation = CANVAS_COMPOSITE_TABLE[aBlendMode]; +} + +function CGContextAddArc(aContext, x, y, radius, startAngle, endAngle, clockwise) +{ + // Despite the documentation saying otherwise, the last parameter is anti-clockwise not clockwise. + // http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes#Arcs + _CGContextAddArcCanvas(aContext, x, y, radius, startAngle, endAngle, !clockwise); +} + +function CGContextAddArcToPoint(aContext, x1, y1, x2, y2, radius) +{ + _CGContextAddArcToPointCanvas(aContext, x1, y1, x2, y2, radius); +} + +function CGContextAddCurveToPoint(aContext, cp1x, cp1y, cp2x, cp2y, x, y) +{ + _CGContextAddCurveToPointCanvas(aContext, cp1x, cp1y, cp2x, cp2y, x, y); +} + +function CGContextAddLineToPoint(aContext, x, y) +{ + _CGContextAddLineToPointCanvas(aContext, x, y); +} + +function CGContextAddPath(aContext, aPath) +{ + if (!aContext || CGPathIsEmpty(aPath)) + return; + + var elements = aPath.elements, + + i = 0, + count = aPath.count; + + for (; i < count; ++i) + { + var element = elements[i], + type = element.type; + + switch (type) + { + case kCGPathElementMoveToPoint: _CGContextMoveToPointCanvas(aContext, element.x, element.y); + break; + case kCGPathElementAddLineToPoint: _CGContextLineToPoint(aContext, element.x, element.y); + break; + case kCGPathElementAddQuadCurveToPoint: _CGContextAddQuadCurveToPoint(aContext, element.cpx, element.cpy, element.x, element.y); + break; + case kCGPathElementAddCurveToPoint: _CGContextAddCurveToPointCanvas(aContext, element.cp1x, element.cp1y, element.cp2x, element.cp2y, element.x, element.y); + break; + case kCGPathElementCloseSubpath: _CGContextClosePathCanvas(aContext); + break; + case kCGPathElementAddArc: _CGContextAddArcCanvas(aContext, element.x, element.y, element.radius, element.startAngle, element.endAngle, element.clockwise); + break; + case kCGPathElementAddArcTo: //_CGContextAddArcToPointCanvas(aContext, element.cp1x, element.cp1.y, element.cp2.x, element.cp2y, element.radius); + break; + } + } +} + +function CGContextAddRect(aContext, aRect) +{ + _CGContextAddRectCanvas(aContext, aRect); +} + +function CGContextAddRects(aContext, rects, count) +{ + var i = 0; + + if (arguments["count"] == NULL) + var count = rects.length; + + for (; i < count; ++i) + { + var rect = rects[i]; + _CGContextAddRectCanvas(aContext, rect); + } +} + +function CGContextBeginPath(aContext) +{ + _CGContextBeginPathCanvas(aContext); +} + +function CGContextClosePath(aContext) +{ + _CGContextClosePathCanvas(aContext); +} + +function CGContextMoveToPoint(aContext, x, y) +{ + _CGContextMoveToPointCanvas(aContext, x, y); +} + +function CGContextClearRect(aContext, aRect) +{ + aContext.clearRect(_CGRectGetMinX(aRect), _CGRectGetMinY(aRect), _CGRectGetWidth(aRect), _CGRectGetHeight(aRect)); +} + +function CGContextDrawPath(aContext, aMode) +{ + if (aMode == kCGPathFill || aMode == kCGPathFillStroke) + aContext.fill(); + else if (aMode == kCGPathEOFill || aMode == kCGPathEOFillStroke) + alert("not implemented!!!"); + + if (aMode == kCGPathStroke || aMode == kCGPathFillStroke || aMode == kCGPathEOFillStroke) + aContext.stroke(); +} + +function CGContextFillRect(aContext, aRect) +{ + _CGContextFillRectCanvas(aContext, aRect); +} + +function CGContextFillRects(aContext, rects, count) +{ + var i = 0; + + if (arguments["count"] == NULL) + var count = rects.length; + + for (; i < count; ++i) + { + var rect = rects[i]; + _CGContextFillRectCanvas(aContext, rect); + } +} + +function CGContextStrokeRect(aContext, aRect) +{ + aContext.strokeRect(_CGRectGetMinX(aRect), _CGRectGetMinY(aRect), _CGRectGetWidth(aRect), _CGRectGetHeight(aRect)); +} + +function CGContextClip(aContext) +{ + _CGContextClipCanvas(aContext); +} + +function CGContextClipToRect(aContext, aRect) +{ + _CGContextBeginPathCanvas(aContext); + _CGContextAddRectCanvas(aContext, aRect); + _CGContextClosePathCanvas(aContext); + + _CGContextClipCanvas(aContext); +} + +function CGContextClipToRects(aContext, rects, count) +{ + if (arguments["count"] == NULL) + var count = rects.length; + + _CGContextBeginPathCanvas(aContext); + CGContextAddRects(aContext, rects, count); + _CGContextClipCanvas(aContext); +} + +function CGContextSetAlpha(aContext, anAlpha) +{ + aContext.globalAlpha = anAlpha; +} + +function CGContextSetFillColor(aContext, aColor) +{ + aContext.fillStyle = [aColor cssString]; +} + +function CGContextSetStrokeColor(aContext, aColor) +{ + aContext.strokeStyle = [aColor cssString]; +} + +function CGContextSetShadow(aContext, aSize, aBlur) +{ + aContext.shadowOffsetX = aSize.width; + aContext.shadowOffsetY = aSize.height; + aContext.shadowBlur = aBlur; +} + +function CGContextSetShadowWithColor(aContext, aSize, aBlur, aColor) +{ + aContext.shadowOffsetX = aSize.width; + aContext.shadowOffsetY = aSize.height; + aContext.shadowBlur = aBlur; + aContext.shadowColor = [aColor cssString]; +} + +function CGContextRotateCTM(aContext, anAngle) +{ + aContext.rotate(anAngle); +} + +function CGContextScaleCTM(aContext, sx, sy) +{ + aContext.scale(sx, sy); +} + +function CGContextTranslateCTM(aContext, tx, ty) +{ + aContext.translate(tx, ty); +} + +#define scale_rotate(a, b, c, d) \ + var sign = (a * d < 0.0 || b * c > 0.0) ? -1.0 : 1.0, \ + a2 = (ATAN2(b, d) + ATAN2(-sign * c, sign * a)) / 2.0, \ + cos = COS(a2),\ + sin = SIN(a2);\ + \ + if (cos == 0)\ + {\ + sx = -c / sin;\ + sy = b / sin;\ + }\ + else if (sin == 0)\ + {\ + sx = a / cos;\ + sy = d / cos;\ + }\ + else\ + {\ + abs_cos = ABS(cos);\ + abs_sin = ABS(sin);\ + \ + sx = (abs_cos * a / cos + abs_sin * -c / sin) / (abs_cos + abs_sin);\ + sy = (abs_cos * d / cos + abs_sin * b / sin) / (abs_cos + abs_sin);\ + }\ + +#define rotate_scale(a, b, c, d) \ + var sign = (a * d < 0.0 || b * c > 0.0) ? -1.0 : 1.0;\ + a1 = (Math.atan2(sign * b, sign * a) + Math.atan2(-c, d)) / 2.0,\ + cos = COS(a1),\ + sin = SIN(a1);\ + \ + if (cos == 0)\ + {\ + sx = b / sin;\ + sy = -c / sin;\ + }\ + else if (sin == 0)\ + {\ + sx = a / cos;\ + sy = d / cos;\ + }\ + else\ + {\ + abs_cos = ABS(cos);\ + abs_sin = ABS(sin);\ + \ + sx = (abs_cos * a / cos + abs_sin * b / sin) / (abs_cos + abs_sin);\ + sy = (abs_cos * d / cos + abs_sin * -c / sin) / (abs_cos + abs_sin);\ + }\ + +function eigen(anAffineTransform) +{ + alert("IMPLEMENT ME!"); +} + +function CGContextConcatCTM(aContext, anAffineTransform) +{ + var a = anAffineTransform.a, + b = anAffineTransform.b, + c = anAffineTransform.c, + d = anAffineTransform.d, + tx = anAffineTransform.tx, + ty = anAffineTransform.ty, + sx = 1.0, + sy = 1.0, + a1 = 0.0, + a2 = 0.0; + + // Detect the simple case of just scaling. + if (b == 0.0 && c == 0.0) + { + sx = a; + sy = d; + } + + // a scale followed by a rotate + else if (a * b == -c * d) + { + scale_rotate(a, b, c, d) + } + + // rotate, then scale. + else if (a * c == -b * d) + { + rotate_scale(a, b, c, d) + } + else + { + var transpose = CGAffineTransformMake(a, c, b, d, 0.0, 0.0), // inline + u = eigen(CGAffineTransformConcat(anAffineTransform, transpose)), + v = eigen(CGAffineTransformConcat(transpose, anAffineTransform)), + U = CGAffineTransformMake(u.vector_1.x, u.vector_2.x, u.vector_1.y, u.vector_2.y, 0.0, 0.0), // inline + VT = CGAffineTransformMake(v.vector_1.x, v.vector_1.y, v.vector_2.x, v.vector_2.y, 0.0, 0.0), + S = CGAffineTransformConcat(CGAffineTransformConcat(CGAffineTransformInvert(U), anAffineTransform), CGAffineTransformInvert(VT)); + + a = VT.a; + b = VT.b; + c = VT.c; + d = VT.d; + scale_rotate(a, b, c, d) + S.a *= sx; + S.d *= sy; + a = U.a; + b = U.b; + c = U.c; + d = U.d; + rotate_scale(a, b, c, d) + sx = S.a * sx; + sy = S.d * sy; + } + + if (tx != 0 || ty != 0) + CGContextTranslateCTM(aContext, tx, ty); + if (a1 != 0.0) + CGContextRotateCTM(aContext, a1); + if (sx != 1.0 || sy != 1.0) + CGContextScaleCTM(aContext, sx, sy); + if (a2 != 0.0) + CGContextRotateCTM(aContext, a2); +} + +function CGContextDrawImage(aContext, aRect, anImage) +{ + aContext.drawImage(anImage._image, _CGRectGetMinX(aRect), _CGRectGetMinY(aRect), _CGRectGetWidth(aRect), _CGRectGetHeight(aRect)); +} + +function to_string(aColor) +{ + return "rgba(" + ROUND(aColor.components[0] * 255) + ", " + ROUND(aColor.components[1] * 255) + ", " + ROUND(255 * aColor.components[2]) + ", " + aColor.components[3] + ")"; +} + +function CGContextDrawLinearGradient(aContext, aGradient, aStartPoint, anEndPoint, options) +{ + var colors = aGradient.colors, + count = colors.length, + + linearGradient = aContext.createLinearGradient(aStartPoint.x, aStartPoint.y, anEndPoint.x, anEndPoint.y); + + while (count--) + linearGradient.addColorStop(aGradient.locations[count], to_string(colors[count])); + + aContext.fillStyle = linearGradient; + aContext.fill(); +} + +function CGBitmapGraphicsContextCreate() +{ + var DOMElement = document.createElement("canvas"), + context = DOMElement.getContext("2d"); + + context.DOMElement = DOMElement; + + return context; +} diff --git a/AppKit/CoreGraphics/CGContextVML.j b/AppKit/CoreGraphics/CGContextVML.j new file mode 100644 index 000000000..264b20587 --- /dev/null +++ b/AppKit/CoreGraphics/CGContextVML.j @@ -0,0 +1,261 @@ +/* + * CGContextVML.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +var VML_TRUTH_TABLE = [ "f", "t"], + VML_LINECAP_TABLE = [ "flat", "round", "square" ], + VML_LINEJOIN_TABLE = [ "miter", "round", "bevel" ], + VML_ELEMENT_TABLE = [ " m ", " l ", "qb", " c ", " x ", [" at ", " wa "]]; + +var _CGBitmapGraphicsContextCreate = CGBitmapGraphicsContextCreate; + +function CGBitmapGraphicsContextCreate() +{ + // The first time around, we have to set up our environment to support vml. + document.namespaces.add("cg_vml_", "urn:schemas-microsoft-com:vml"); + document.createStyleSheet().cssText = "cg_vml_\\:*{behavior:url(#default#VML)}"; + + CGBitmapGraphicsContextCreate = _CGBitmapGraphicsContextCreate; + + return _CGBitmapGraphicsContextCreate(); +} + +// FIXME: aRect is ignored. +function CGContextClearRect(aContext, aRect) +{ + if (aContext.buffer != nil) + aContext.buffer = ""; + else + aContext.DOMElement.innerHTML = ""; + + aContext.path = NULL; +} + +var W = 10.0, + H = 10.0, + Z = 10.0, + Z_2 = Z / 2.0; + +#define COORD(aCoordinate) (ROUND(Z * (aCoordinate) - Z_2)) + +function CGContextDrawImage(aContext, aRect, anImage) +{ + var string = ""; + + if (anImage.buffer != nil) + string = anImage.buffer; + else + { + var ctm = aContext.gState.CTM, + origin = CGPointApplyAffineTransform(aRect.origin, ctm), + similarity = ctm.a == ctm.d && ctm.b == -ctm.c, + vml = [""); + + string = vml.join(""); + } + + if (aContext.buffer != nil) + aContext.buffer += string; + else + aContext.DOMElement.insertAdjacentHTML("BeforeEnd", string); +} + +function CGContextDrawPath(aContext, aMode) +{ + if (!aContext || CGPathIsEmpty(aContext.path)) + return; +var opacity = 1.0; + var elements = aContext.path.elements, + + i = 0, + count = aContext.path.count, + + gState = aContext.gState, + fill = (aMode == kCGPathFill || aMode == kCGPathFillStroke) ? 1 : 0, + stroke = (aMode == kCGPathStroke || aMode == kCGPathFillStroke) ? 1 : 0, + vml = [ "= x) + { + if (start.y < y) + start.x += 0.125; + else + start.y += 0.125; + } + else + { + if (end.y <= y) + end.x += 0.125; + else + end.y += 0.125; + } + + vml.push(VML_ELEMENT_TABLE[type][clockwise], + COORD(x - radius), ',', COORD(y - radius), " ", + COORD(x + radius), ',', COORD(y + radius), " ", + COORD(start.x), ',', COORD(start.y), " ", + COORD(end.x), ',', COORD(end.y)); + break; + case kCGPathElementAddArcTo: break; + } + + // TODO: Following is broken for curves due to + // move to proper paths. + + // Figure out dimensions so we can do gradient fills + // properly + /*if(c) { + if (min.x == null || c.x < min.x) { + min.x = c.x; + } + if (max.x == null || c.x > max.x) { + max.x = c.x; + } + if (min.y == null || c.y < min.y) { + min.y = c.y; + } + if (max.y == null || c.y > max.y) { + max.y = c.y; + } + }*/ + } + + vml.push("\">"); + + if (fill) + vml.push(""); + + if (stroke) + vml.push( ""); + + var shadowColor = gState.shadowColor; + //\"", [shadowColor cssString], "\" + if (shadowColor) + { + var shadowOffset = gState.shadowOffset; + + vml.push(""); + } + + vml.push(""); + + aContext.path = NULL; + + if (aContext.buffer != nil) + aContext.buffer += vml.join(""); + else + aContext.DOMElement.insertAdjacentHTML("BeforeEnd", vml.join("")); +} + diff --git a/AppKit/CoreGraphics/CGGeometry.h b/AppKit/CoreGraphics/CGGeometry.h new file mode 100644 index 000000000..d12c97fc1 --- /dev/null +++ b/AppKit/CoreGraphics/CGGeometry.h @@ -0,0 +1,64 @@ +/* + * CGGeometry.h + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define _CGPointMake(x_, y_) { x:x_, y:y_ } +#define _CGPointMakeCopy(aPoint) _CGPointMake(aPoint.x, aPoint.y) +#define _CGPointMakeZero() _CGPointMake(0.0, 0.0) + +#define _CGPointEqualToPoint(lhsPoint, rhsPoint) (lhsPoint.x == rhsPoint.x && lhsPoint.y == rhsPoint.y) +#define _CGStringFromPoint(aPoint) ("{" + aPoint.x + ", " + aPoint.y + "}") + +#define _CGSizeMake(width_, height_) { width:width_, height:height_ } +#define _CGSizeMakeCopy(aSize) _CGSizeMake(aSize.width, aSize.height) +#define _CGSizeMakeZero() _CGSizeMake(0.0, 0.0) + +#define _CGSizeEqualToSize(lhsSize, rhsSize) (lhsSize.width == rhsSize.width && lhsSize.height == rhsSize.height) +#define _CGStringFromSize(aSize) ("{" + aSize.width + ", " + aSize.height + "}") + +#define _CGRectMake(x, y, width, height) { origin: _CGPointMake(x, y), size: _CGSizeMake(width, height) } +#define _CGRectMakeZero() _CGRectMake(0.0, 0.0, 0.0, 0.0) +#define _CGRectMakeCopy(aRect) _CGRectMake(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height) +#define _CGRectCreateCopy(aRect) _CGRectMake(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height) + +#define _CGRectEqualToRect(lhsRect, rhsRect) (_CGPointEqualToPoint(lhsRect.origin, rhsRect.origin) && _CGSizeEqualToSize(lhsRect.size, rhsRect.size)) +#define _CGStringFromRect(aRect) ("{" + _CGStringFromPoint(aRect.origin) + ", " + _CGStringFromSize(aRect.size) + "}") + +#define _CGRectOffset(aRect, dX, dY) _CGRectMake(aRect.origin.x + dX, aRect.origin.y + dY, aRect.size.width, aRect.size.height) +#define _CGRectInset(aRect, dX, dY) _CGRectMake(aRect.origin.x + dX, aRect.origin.y + dY, aRect.size.width - 2 * dX, aRect.size.height - 2 * dY) + +#define _CGRectGetHeight(aRect) (aRect.size.height) +#define _CGRectGetMaxX(aRect) (aRect.origin.x + aRect.size.width) +#define _CGRectGetMaxY(aRect) (aRect.origin.y + aRect.size.height) +#define _CGRectGetMidX(aRect) (aRect.origin.x + (aRect.size.width) / 2.0) +#define _CGRectGetMidY(aRect) (aRect.origin.y + (aRect.size.height) / 2.0) +#define _CGRectGetMinX(aRect) (aRect.origin.x) +#define _CGRectGetMinY(aRect) (aRect.origin.y) +#define _CGRectGetWidth(aRect) (aRect.size.width) + +#define _CGRectIsEmpty(aRect) (aRect.size.width <= 0.0 || aRect.size.height <= 0.0) +#define _CGRectIsNull(aRect) (aRect.size.width <= 0.0 || aRect.size.height <= 0.0) + +#define _CGRectContainsPoint(aRect, aPoint) (aPoint.x >= _CGRectGetMinX(aRect) && aPoint.y >= _CGRectGetMinY(aRect) && aPoint.x < _CGRectGetMaxX(aRect) && aPoint.y < _CGRectGetMaxY(aRect)) + +// DEPRECATED +#define _CGPointCreateCopy(aPoint) _CGPointMake(aPoint.x, aPoint.y) +#define _CGSizeCreateCopy(aSize) _CGSizeMake(aSize.width, aSize.height) diff --git a/AppKit/CoreGraphics/CGGeometry.j b/AppKit/CoreGraphics/CGGeometry.j new file mode 100644 index 000000000..0e3aced22 --- /dev/null +++ b/AppKit/CoreGraphics/CGGeometry.j @@ -0,0 +1,173 @@ +/* + * CGGeometry.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "CGGeometry.h" + +#define _function(inline) function inline { return _##inline; } + +_function(CGPointMake(x, y)) +_function(CGPointMakeZero()) +_function(CGPointMakeCopy(aPoint)) +_function(CGPointCreateCopy(aPoint)) + +_function(CGPointEqualToPoint(lhsPoint, rhsPoint)) +_function(CGStringFromPoint(aPoint)) + +_function(CGSizeMake(width, height)) +_function(CGSizeMakeZero()) +_function(CGSizeMakeCopy(aSize)) +_function(CGSizeCreateCopy(aSize)) + +_function(CGSizeEqualToSize(lhsSize, rhsSize)) +_function(CGStringFromSize(aSize)) + +_function(CGRectMake(x, y, width, height)) +_function(CGRectMakeZero()) +_function(CGRectMakeCopy(aRect)) +_function(CGRectCreateCopy(aRect)) + +_function(CGRectEqualToRect(lhsRect, rhsRect)) +_function(CGStringFromRect(aRect)) + +_function(CGRectOffset(aRect, dX, dY)) +_function(CGRectInset(aRect, dX, dY)) + +_function(CGRectGetHeight(aRect)) +_function(CGRectGetMaxX(aRect)) +_function(CGRectGetMaxY(aRect)) +_function(CGRectGetMidX(aRect)) +_function(CGRectGetMidY(aRect)) +_function(CGRectGetMinX(aRect)) +_function(CGRectGetMinY(aRect)) +_function(CGRectGetWidth(aRect)) + +_function(CGRectIsEmpty(aRect)) +_function(CGRectIsNull(aRect)) + +_function(CGRectContainsPoint(aRect, aPoint)) + +function CGRectContainsRect(lhsRect, rhsRect) +{ + var union = CGRectUnion(lhsRect, rhsRect); + + return _CGRectEqualToRect(union, lhsRect); +} + +function CGRectIntersectsRect(lhsRect, rhsRect) +{ + var intersection = CGRectIntersection(lhsRect, rhsRect); + + return !_CGRectIsEmpty(intersection); +} + +function CGRectIntegral(aRect) +{ + aRect = CGRectStandardize(aRect); + + // Store these out separately, if not the GetMaxes will return incorrect values. + var x = FLOOR(_CGRectGetMinX(aRect)), + y = FLOOR(_CGRectGetMinY(aRect)); + + aRect.size.width = CEIL(_CGRectGetMaxX(aRect)) - x; + aRect.size.height = CEIL(_CGRectGetMaxY(aRect)) - y; + + aRect.origin.x = x; + aRect.origin.y = y; + + return aRect; +} + +function CGRectIntersection(lhsRect, rhsRect) +{ + var intersection = _CGRectMake( + MAX(_CGRectGetMinX(lhsRect), _CGRectGetMinX(rhsRect)), + MAX(_CGRectGetMinY(lhsRect), _CGRectGetMinY(rhsRect)), + 0, 0); + + intersection.size.width = MIN(_CGRectGetMaxX(lhsRect), _CGRectGetMaxX(rhsRect)) - _CGRectGetMinX(intersection); + intersection.size.height = MIN(_CGRectGetMaxY(lhsRect), _CGRectGetMaxY(rhsRect)) - _CGRectGetMinY(intersection); + + return _CGRectIsEmpty(intersection) ? _CGRectMakeZero() : intersection; +} + +function CGRectStandardize(aRect) +{ + var width = _CGRectGetWidth(aRect), + height = _CGRectGetHeight(aRect), + standardized = aRect; + + if (width < 0.0) + { + if (standardized == aRect) + standardized = _CGRectMakeCopy(aRect); + + standardized.origin.x += width; + standardized.size.width = -width; + } + + if (height < 0.0) + { + if (standardized == aRect) + standardized = _CGRectMakeCopy(aRect); + + standardized.origin.y += height; + standardized.size.height = -height; + } + + return standardized; +} + +function CGRectUnion(lhsRect, rhsRect) +{ + var minX = MIN(_CGRectGetMinX(lhsRect), _CGRectGetMinX(rhsRect)), + minY = MIN(_CGRectGetMinY(lhsRect), _CGRectGetMinY(rhsRect)), + maxX = MAX(_CGRectGetMaxX(lhsRect), _CGRectGetMaxX(rhsRect)), + maxY = MAX(_CGRectGetMaxY(lhsRect), _CGRectGetMaxY(rhsRect)); + + return _CGRectMake(minX, minY, maxX - minX, maxY - minY); +} + +function CGPointFromString(aString) +{ + var comma = aString.indexOf(','); + + return { x:parseInt(aString.substr(1, comma - 1)), y:parseInt(aString.substring(comma + 1, aString.length)) }; +} + +function CGSizeFromString(aString) +{ + var comma = aString.indexOf(','); + + return { width:parseInt(aString.substr(1, comma - 1)), height:parseInt(aString.substring(comma + 1, aString.length)) }; +} + +function CGRectFromString(aString) +{ + var comma = aString.indexOf(',', aString.indexOf(',') + 1); + + return { origin:CGPointFromString(aString.substr(1, comma - 1)), size:CGSizeFromString(aString.substring(comma + 2, aString.length)) }; +} + +function CGPointFromEvent(anEvent) +{ + return _CGPointMake(anEvent.clientX, anEvent.clientY); +} diff --git a/AppKit/CoreGraphics/CGGradient.j b/AppKit/CoreGraphics/CGGradient.j new file mode 100644 index 000000000..b46bc35ab --- /dev/null +++ b/AppKit/CoreGraphics/CGGradient.j @@ -0,0 +1,57 @@ +/* + * CGGradient.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CGColor.j" +import "CGColorSpace.j" + +kCGGradientDrawsBeforeStartLocation = 1 << 0; +kCGGradientDrawsAfterEndLocation = 1 << 1; + +function CGGradientCreateWithColorComponents(aColorSpace, components, locations, count) +{ + if (arguments["count"] == NULL) + var count = locations.length; + + var colors = []; + + while (count--) + { + var offset = count * 4; + colors[count] = CGColorCreate(aColorSpace, components.slice(offset, offset + 4)); + } + + return CGGradientCreateWithColors(aColorSpace, colors, locations); +} + +function CGGradientCreateWithColors(aColorSpace, colors, locations) +{ + return { colorspace:aColorSpace, colors:colors, locations:locations }; +} + +function CGGradientRelease() +{ +} + +function CGGradientRetain(aGradient) +{ + return aGradient; +} \ No newline at end of file diff --git a/AppKit/CoreGraphics/CGPath.j b/AppKit/CoreGraphics/CGPath.j new file mode 100644 index 000000000..f06095629 --- /dev/null +++ b/AppKit/CoreGraphics/CGPath.j @@ -0,0 +1,285 @@ +/* + * CGPath.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "CGGeometry.h" +#include "CGAffineTransform.h" + +import "CGGeometry.j" +import "CGAffineTransform.j" + +kCGPathElementMoveToPoint = 0; +kCGPathElementAddLineToPoint = 1; +kCGPathElementAddQuadCurveToPoint = 2; +kCGPathElementAddCurveToPoint = 3; +kCGPathElementCloseSubpath = 4; + +kCGPathElementAddArc = 5; +kCGPathElementAddArcToPoint = 6; + +function CGPathCreateMutable() +{ + return { count:0, start:NULL, current:NULL, elements:[] }; +} + +function CGPathCreateMutableCopy(aPath) +{ + var path = CGPathCreateMutable(); + + CGPathAddPath(path, aPath); + + return path; +} + +function CGPathCreateCopy(aPath) +{ + return CGPathCreateMutableCopy(aPath); +} + +function CGPathRelease(aPath) +{ +} + +function CGPathRetain(aPath) +{ + return aPath; +} + +function CGPathAddArc(aPath, aTransform, x, y, aRadius, aStartAngle, anEndAngle, isClockwise) +{ + if (aTransform && !_CGAffineTransformIsIdentity(aTransform)) + { + var center = _CGPointMake(x, y), + end = _CGPointMake(COS(anEndAngle), SIN(anEndAngle)), + start = _CGPointMake(COS(aStartAngle), SIN(aStartAngle)); + + end = _CGPointApplyAffineTransform(end, aTransform); + start = _CGPointApplyAffineTransform(start, aTransform); + center = _CGPointApplyAffineTransform(center, aTransform); + + x = center.x; + y = center.y; + + var oldEndAngle = anEndAngle, + oldStartAngle = aStartAngle; + + anEndAngle = ATAN2(end.y - aTransform.ty, end.x - aTransform.tx); + aStartAngle = ATAN2(start.y - aTransform.ty, start.x - aTransform.tx); + + // Angles that equal "modulo" 2 pi return as equal after transforming them, + // so we have to make sure to make them different again if they were different + // to start out with. It's the difference between no circle and a full circle. + if (anEndAngle == aStartAngle && oldEndAngle != oldStartAngle) + if (oldStartAngle > oldEndAngle) + anEndAngle = anEndAngle - PI2; + else + aStartAngle = aStartAngle - PI2; + + aRadius = _CGSizeMake(aRadius, 0); + aRadius = _CGSizeApplyAffineTransform(aRadius, aTransform); + aRadius = SQRT(aRadius.width * aRadius.width + aRadius.height * aRadius.height); + } + + aPath.current = _CGPointMake(x + aRadius * COS(anEndAngle), y + aRadius * SIN(anEndAngle)); + aPath.elements[aPath.count++] = { type:kCGPathElementAddArc, x:x, y:y, radius:aRadius, startAngle:aStartAngle, endAngle:anEndAngle }; +} + +function CGPathAddArcToPoint(aPath, aTransform, x1, y1, x2, y2, aRadius) +{ +} + +function CGPathAddCurveToPoint(aPath, aTransform, cp1x, cp1y, cp2x, cp2y, x, y) +{ + var cp1 = _CGPointMake(cp1x, cp1y), + cp2 = _CGPointMake(cp2x, cp2y), + end = _CGPointMake(x, y); + + if (aTransform) + { + cp1 = _CGPointApplyAffineTransform(cp1, aTransform); + cp2 = _CGPointApplyAffineTransform(cp2, aTransform); + end = _CGPointApplyAffineTransform(end, aTransform); + } + + aPath.current = end; + aPath.elements[aPath.count++] = { type:kCGPathElementAddCurveToPoint, cp1x:cp1.x, cp1y:cp1.y, cp2x:cp2.x, cp2y:cp2.y, x:end.x, y:end.y }; +} + +function CGPathAddLines(aPath, aTransform, points, count) +{ + var i = 1; + + if (arguments["count"] == NULL) + var count = points.length; + + if (!aPath || count < 2) + return; + + CGPathMoveToPoint(aPath, aTransform, points[0].x, points[0].y); + + for (; i < count; ++i) + CGPathAddLineToPoint(aPath, aTransform, points[i].x, points[i].y); +} + +function CGPathAddLineToPoint(aPath, aTransform, x, y) +{ + var point = _CGPointMake(x, y); + + if (aTransform != NULL) + point = _CGPointApplyAffineTransform(point, aTransform); + + aPath.elements[aPath.count++] = { type: kCGPathElementAddLineToPoint, x:point.x, y:point.y }; + aPath.current = point; +} + +function CGPathAddPath(aPath, aTransform, anotherPath) +{ + var i = 0, + count = anotherPath.count; + + for (; i < count; ++i) + { + var element = anotherPath[i]; + + aPath.elements[aPath.count++] = { type:element.type, points:element.point.slice() }; + + if (element.type == kCGPathElementAddArc || element.type == kCGPathElementAddArcToPoint) + aPath.elements[aPath.count - 1].radius = element.radius; + } + + aPath.current = anotherPath.current; +} + +function CGPathAddQuadCurveToPoint(aPath, aTransform, cpx, cpy, x, y) +{ + var cp = _CGPointMake(cpx, cpy), + end = _CGPointMake(x, y); + + if (aTransform) + { + cp = _CGPointApplyAffineTransform(control, aTransform); + end = _CGPointApplyAffineTransform(end, aTransform); + } + + aPath.elements[aPath.count++] = { type:kCGPathElementAddQuadCurveToPoint, cpx:cp.x, cpy:cp.y, x:end.x, y:end.y } + aPath.current = end; +} + +function CGPathAddRect(aPath, aTransform, aRect) +{ + CGPathAddRects(aPath, aTransform, [aRect], 1); +} + +function CGPathAddRects(aPath, aTransform, rects, count) +{ + var i = 0; + + if (arguments["count"] == NULL) + var count = rects.length; + + for (; i < count; ++i) + { + var rect = rects[i]; + + CGPathMoveToPoint(aPath, aTransform, _CGRectGetMinX(rect), _CGRectGetMinY(rect)); + CGPathAddLineToPoint(aPath, aTransform, _CGRectGetMaxX(rect), _CGRectGetMinY(rect)); + CGPathAddLineToPoint(aPath, aTransform, _CGRectGetMaxX(rect), _CGRectGetMaxY(rect)); + CGPathAddLineToPoint(aPath, aTransform, _CGRectGetMinX(rect), _CGRectGetMaxY(rect)); + + CGPathCloseSubpath(aPath); + } +} + +function CGPathMoveToPoint(aPath, aTransform, x, y) +{ + var point = _CGPointMake(x, y), + count = aPath.count; + + if (aTransform != NULL) + point = _CGPointApplyAffineTransform(point, aTransform); + + aPath.start = point; + aPath.current = point; + + var previous = aPath.elements[count - 1]; + + if (count != 0 && previous.type == kCGPathElementMoveToPoint) + { + previous.x = point.x; + previous.y = point.y; + } + else + aPath.elements[aPath.count++] = { type:kCGPathElementMoveToPoint, x:point.x, y:point.y }; +} + +function CGPathCloseSubpath(aPath) +{ + var count = aPath.count; + + // Don't bother closing this subpath if there aren't any current elements, or the last element already closed the subpath. + if (count == 0 || aPath.elements[count - 1].type == kCGPathElementCloseSubpath) + return; + + aPath.elements[aPath.count++] = { type:kCGPathElementCloseSubpath, points:[aPath.start] }; +} + +function CGPathEqualToPath(aPath, anotherPath) +{ + if (aPath == anotherPath) + return YES; + + if (aPath.count != anotherPath.count || !_CGPointEqualToPoint(aPath.start, anotherPath.start) || !_CGPointEqualToPoint(aPath.current, anotherPath.current)) + return NO; + + var i = 0, + count = aPath.count; + + for (; i < count; ++i) + { + var element = aPath[i], + anotherElement = anotherPath[i]; + + if (element.type != anotherElement.type) + return NO; + + if ((element.type == kCGPathElementAddArc || element.type == kCGPathElementAddArcToPoint) && + element.radius != anotherElement.radius) + return NO; + + var j = element.points.length; + + while (j--) + if (!_CGPointEqualToPoint(element.points[j], anotherElement.points[j])) + return NO; + } + + return YES; +} + +function CGPathGetCurrentPoint(aPath) +{ + return _CGPointCreateCopy(aPath.current); +} + +function CGPathIsEmpty(aPath) +{ + return !aPath || aPath.count == 0; +} diff --git a/AppKit/Info.plist b/AppKit/Info.plist new file mode 100644 index 000000000..ed261efba --- /dev/null +++ b/AppKit/Info.plist @@ -0,0 +1,14 @@ + + + + + CPBundleIdentifier + com.280n.AppKit + CPBundleInfoDictionaryVersion + 6.0 + CPBundleName + AppKit + CPBundlePackageType + FMWK + + diff --git a/AppKit/Platform/DOM/CPDOMDisplayServer.h b/AppKit/Platform/DOM/CPDOMDisplayServer.h new file mode 100644 index 000000000..7afa07107 --- /dev/null +++ b/AppKit/Platform/DOM/CPDOMDisplayServer.h @@ -0,0 +1,88 @@ +/* + * CPDOMDisplayServer.h + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define SetStyleOrigin 0 +#define SetStyleLeftTop 0 +#define SetStyleRightTop 1 +#define SetStyleLeftBottom 2 +#define SetStyleRightBottom 3 +#define SetStyleSize 4 +#define AppendChild 5 +#define InsertBefore 6 +#define RemoveChild 7 + +#define CPDOMDisplayServerSetStyleOrigin(anInstruction, aDOMElement, aTransform, x, y)\ + if (!aDOMElement.CPDOMDisplayContext)\ + aDOMElement.CPDOMDisplayContext = [];\ + var __index = aDOMElement.CPDOMDisplayContext[SetStyleOrigin];\ + if (!(__index >= 0))\ + {\ + __index = aDOMElement.CPDOMDisplayContext[SetStyleOrigin] = CPDOMDisplayServerInstructionCount;\ + CPDOMDisplayServerInstructionCount += 5;\ + }\ + CPDOMDisplayServerInstructions[__index] = anInstruction;\ + CPDOMDisplayServerInstructions[__index + 1] = aDOMElement;\ + CPDOMDisplayServerInstructions[__index + 2] = aTransform;\ + CPDOMDisplayServerInstructions[__index + 3] = x;\ + CPDOMDisplayServerInstructions[__index + 4] = y; + +#define CPDOMDisplayServerSetStyleLeftTop(aDOMElement, aTransform, aLeft, aTop) CPDOMDisplayServerSetStyleOrigin(SetStyleLeftTop, aDOMElement, aTransform, aLeft, aTop) + +#define CPDOMDisplayServerSetStyleRightTop(aDOMElement, aTransform, aRight, aTop) CPDOMDisplayServerSetStyleOrigin(SetStyleRightTop, aDOMElement, aTransform, aRight, aTop) + +#define CPDOMDisplayServerSetStyleLeftBottom(aDOMElement, aTransform, aLeft, aBottom) CPDOMDisplayServerSetStyleOrigin(SetStyleLeftBottom, aDOMElement, aTransform, aLeft, aBottom) + +#define CPDOMDisplayServerSetStyleRightBottom(aDOMElement, aTransform, aRight, aBottom) CPDOMDisplayServerSetStyleOrigin(SetStyleRightBottom, aDOMElement, aTransform, aRight, aBottom) + +#define CPDOMDisplayServerSetStyleSize(aDOMElement, aWidth, aHeight)\ + if (!aDOMElement.CPDOMDisplayContext)\ + aDOMElement.CPDOMDisplayContext = [];\ + var __index = aDOMElement.CPDOMDisplayContext[SetStyleSize];\ + if (!(__index >= 0))\ + {\ + __index = aDOMElement.CPDOMDisplayContext[SetStyleSize] = CPDOMDisplayServerInstructionCount;\ + CPDOMDisplayServerInstructionCount += 4;\ + }\ + CPDOMDisplayServerInstructions[__index] = SetStyleSize;\ + CPDOMDisplayServerInstructions[__index + 1] = aDOMElement;\ + CPDOMDisplayServerInstructions[__index + 2] = aWidth;\ + CPDOMDisplayServerInstructions[__index + 3] = aHeight; + +#define CPDOMDisplayServerAppendChild(aParentElement, aChildElement)\ + if (aChildElement.CPDOMDisplayContext) aChildElement.CPDOMDisplayContext[SetStyleOrigin] = -1;\ + CPDOMDisplayServerInstructions[CPDOMDisplayServerInstructionCount++] = AppendChild;\ + CPDOMDisplayServerInstructions[CPDOMDisplayServerInstructionCount++] = aParentElement;\ + CPDOMDisplayServerInstructions[CPDOMDisplayServerInstructionCount++] = aChildElement; + +#define CPDOMDisplayServerInsertBefore(aParentElement, aChildElement, aBeforeElement)\ + if (aChildElement.CPDOMDisplayContext) aChildElement.CPDOMDisplayContext[SetStyleOrigin] = -1;\ + CPDOMDisplayServerInstructions[CPDOMDisplayServerInstructionCount++] = InsertBefore;\ + CPDOMDisplayServerInstructions[CPDOMDisplayServerInstructionCount++] = aParentElement;\ + CPDOMDisplayServerInstructions[CPDOMDisplayServerInstructionCount++] = aChildElement;\ + CPDOMDisplayServerInstructions[CPDOMDisplayServerInstructionCount++] = aBeforeElement; + +#define CPDOMDisplayServerRemoveChild(aParentElement, aChildElement)\ + CPDOMDisplayServerInstructions[CPDOMDisplayServerInstructionCount++] = RemoveChild;\ + CPDOMDisplayServerInstructions[CPDOMDisplayServerInstructionCount++] = aParentElement;\ + CPDOMDisplayServerInstructions[CPDOMDisplayServerInstructionCount++] = aChildElement; + +//#dfeine CPDOMDisplayServerCustomAction() diff --git a/AppKit/Platform/DOM/CPDOMDisplayServer.j b/AppKit/Platform/DOM/CPDOMDisplayServer.j new file mode 100644 index 000000000..c08945866 --- /dev/null +++ b/AppKit/Platform/DOM/CPDOMDisplayServer.j @@ -0,0 +1,129 @@ +/* + * CPDOMDisplayServer.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + +#include "../../CoreGraphics/CGAffineTransform.h" +#include "CPDOMDisplayServer.h" + + +var CPDOMDisplayRunLoop = nil; + +CPDOMDisplayServerInstructions = []; +CPDOMDisplayServerInstructionCount = 0; + +@implementation CPDOMDisplayServer : CPObject +{ +} + ++ (void)start +{ + CPDOMDisplayRunLoop = [CPRunLoop currentRunLoop]; + + [CPDOMDisplayRunLoop performSelector:@selector(run) target:CPDOMDisplayServer argument:nil order:0 modes:[CPDefaultRunLoopMode]]; +} + ++ (void)run +{ + var index = 0; + + while (index < CPDOMDisplayServerInstructionCount) + { + var instruction = CPDOMDisplayServerInstructions[index++]; +try{ + switch (instruction) + { + case SetStyleLeftTop: + case SetStyleRightTop: + case SetStyleLeftBottom: + case SetStyleRightBottom: var element = CPDOMDisplayServerInstructions[index], + style = element.style, + x = (instruction == SetStyleLeftTop || instruction == SetStyleLeftBottom) ? "left" : "right", + y = (instruction == SetStyleLeftTop || instruction == SetStyleRightTop) ? "top" : "bottom"; + + CPDOMDisplayServerInstructions[index++] = nil; + + var transform = CPDOMDisplayServerInstructions[index++]; + + if (transform) + { + var point = _CGPointMake(CPDOMDisplayServerInstructions[index++], CPDOMDisplayServerInstructions[index++]), + transformed = _CGPointApplyAffineTransform(point, transform); + + style[x] = ROUND(transformed.x) + "px"; + style[y] = ROUND(transformed.y) + "px"; + + } + else + { + style[x] = ROUND(CPDOMDisplayServerInstructions[index++]) + "px"; + style[y] = ROUND(CPDOMDisplayServerInstructions[index++]) + "px"; + } + + element.CPDOMDisplayContext[SetStyleOrigin] = -1; + + break; + + case SetStyleSize: var element = CPDOMDisplayServerInstructions[index], + style = element.style; + + CPDOMDisplayServerInstructions[index++] = nil; + + element.CPDOMDisplayContext[SetStyleSize] = -1; + + style.width = MAX(0.0, ROUND(CPDOMDisplayServerInstructions[index++])) + "px"; + style.height = MAX(0.0, ROUND(CPDOMDisplayServerInstructions[index++])) + "px"; + + break; + + case AppendChild: CPDOMDisplayServerInstructions[index].appendChild(CPDOMDisplayServerInstructions[index + 1]); + + CPDOMDisplayServerInstructions[index++] = nil; + CPDOMDisplayServerInstructions[index++] = nil; + + break; + + case InsertBefore: CPDOMDisplayServerInstructions[index].insertBefore(CPDOMDisplayServerInstructions[index + 1], CPDOMDisplayServerInstructions[index + 2]); + + CPDOMDisplayServerInstructions[index++] = nil; + CPDOMDisplayServerInstructions[index++] = nil; + CPDOMDisplayServerInstructions[index++] = nil; + + break; + + case RemoveChild: CPDOMDisplayServerInstructions[index].removeChild(CPDOMDisplayServerInstructions[index + 1]); + + CPDOMDisplayServerInstructions[index++] = nil; + CPDOMDisplayServerInstructions[index++] = nil; + + break; + }}catch(e) { alert("here?" + instruction) } + } + + CPDOMDisplayServerInstructionCount = 0; + + [CPDOMDisplayRunLoop performSelector:@selector(run) target:CPDOMDisplayServer argument:nil order:0 modes:[CPDefaultRunLoopMode]]; +} + +@end + +[CPDOMDisplayServer start]; diff --git a/AppKit/Platform/DOM/CPDOMWindowBridge.j b/AppKit/Platform/DOM/CPDOMWindowBridge.j new file mode 100644 index 000000000..23450d20a --- /dev/null +++ b/AppKit/Platform/DOM/CPDOMWindowBridge.j @@ -0,0 +1,836 @@ +/* + * CPDOMWindowBridge.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import + +import "CPEvent.j" +import "CPCompatibility.j" + +import "CPDOMWindowLayer.j" + +#import "../../CoreGraphics/CGGeometry.h" + + +CPSharedDOMWindowBridge = nil; + +var ExcludedDOMElements = []; + +@implementation CPDOMWindowBridge : CPObject +{ + CPArray _orderedWindows; + CPWindow _mouseDownWindow; + + DOMWindow _DOMWindow; + DOMElement _DOMBodyElement; + DOMElement _DOMFocusElement; + + CPArray _windowLevels; + CPDictionary _windowLayers; + + CPRect _frame; + CPRect _contentBounds; + + BOOL _mouseIsDown; + CPTimeInterval _lastMouseUp; + CPTimeInterval _lastMouseDown; + + CPPoint _currentMousePosition; + + JSObject _charCodes; + unsigned _keyCode; + + BOOL _DOMEventMode; + + // Native Pasteboard Support + DOMElement _DOMPasteboardElement; + CPEvent _pasteboardKeyDownEvent; + + CPString _overriddenEventType; +} + ++ (id)sharedDOMWindowBridge +{ + if (!CPSharedDOMWindowBridge) + CPSharedDOMWindowBridge = [[CPDOMWindowBridge alloc] _initWithDOMWindow:window]; + + return CPSharedDOMWindowBridge; +} + +- (id)initWithFrame:(CPRect)aFrame +{ + alert("unimplemented"); +} + +- (id)_initWithDOMWindow:(DOMWindow)aDOMWindow +{ + self = [super init]; + + if (self) + { + _DOMWindow = aDOMWindow; + + _windowLevels = []; + _windowLayers = [CPDictionary dictionary]; + + // Do this before getting the frame of the window, because if not it will be wrong in IE. + _DOMBodyElement = document.getElementsByTagName("body")[0]; + _DOMBodyElement.innerHTML = ""; // Get rid of anything that might be lingering in the body element. + _DOMBodyElement.style.overflow = "hidden"; + + if (document.documentElement) + document.documentElement.style.overflow = "hidden"; + + _frame = CPDOMWindowGetFrame(_DOMWindow); + _contentBounds = CGRectMake(0.0, 0.0, CPRectGetWidth(_frame), CPRectGetHeight(_frame)); + + _DOMFocusElement = document.createElement("input"); + _DOMFocusElement.style.position = "absolute"; + _DOMFocusElement.style.zIndex = "-1000"; + _DOMFocusElement.style.opacity = "0"; + _DOMFocusElement.style.filter = "alpha(opacity=0)"; + _DOMBodyElement.appendChild(_DOMFocusElement); + + // Create Native Pasteboard handler. + _DOMPasteboardElement = document.createElement("input"); + _DOMPasteboardElement.style.position = "absolute"; + _DOMPasteboardElement.style.top = "-10000px"; + _DOMPasteboardElement.style.zIndex = "99"; + + _DOMBodyElement.appendChild(_DOMPasteboardElement); + + // Make sure the pastboard element is blurred. + _DOMPasteboardElement.blur(); + + _charCodes = {}; + + // + var theClass = [self class], + + keyEventSelector = @selector(_bridgeKeyEvent:), + keyEventImplementation = class_getMethodImplementation(theClass, keyEventSelector), + keyEventCallback = function (anEvent) { keyEventImplementation(self, nil, anEvent); }, + + mouseEventSelector = @selector(_bridgeMouseEvent:), + mouseEventImplementation = class_getMethodImplementation(theClass, mouseEventSelector), + mouseEventCallback = function (anEvent) { mouseEventImplementation(self, nil, anEvent); }, + + scrollEventSelector = @selector(_bridgeScrollEvent:), + scrollEventImplementation = class_getMethodImplementation(theClass, scrollEventSelector), + scrollEventCallback = function (anEvent) { scrollEventImplementation(self, nil, anEvent); }, + + resizeEventSelector = @selector(_bridgeResizeEvent:), + resizeEventImplementation = class_getMethodImplementation(theClass, resizeEventSelector), + resizeEventCallback = function (anEvent) { resizeEventImplementation(self, nil, anEvent); }, + + theDocument = _DOMWindow.document; + + if (document.addEventListener) + { + _DOMWindow.addEventListener("resize", resizeEventCallback, NO); + + theDocument.addEventListener(CPDOMEventMouseUp, mouseEventCallback, NO); + theDocument.addEventListener(CPDOMEventMouseDown, mouseEventCallback, NO); + theDocument.addEventListener(CPDOMEventMouseMoved, mouseEventCallback, NO); + + theDocument.addEventListener(CPDOMEventKeyUp, keyEventCallback, NO); + theDocument.addEventListener(CPDOMEventKeyDown, keyEventCallback, NO); + theDocument.addEventListener(CPDOMEventKeyPress, keyEventCallback, NO); + + //FIXME: does firefox really need a different value? + _DOMWindow.addEventListener("DOMMouseScroll", scrollEventCallback, NO); + _DOMWindow.addEventListener(CPDOMEventScrollWheel, scrollEventCallback, NO); + } + else if(document.attachEvent) + { + _DOMWindow.attachEvent("onresize", resizeEventCallback); + + theDocument.attachEvent("on" + CPDOMEventMouseUp, mouseEventCallback); + theDocument.attachEvent("on" + CPDOMEventMouseDown, mouseEventCallback); + theDocument.attachEvent("on" + CPDOMEventMouseMoved, mouseEventCallback); + theDocument.attachEvent("on" + CPDOMEventDoubleClick, mouseEventCallback); + + theDocument.attachEvent("on" + CPDOMEventKeyUp, keyEventCallback); + theDocument.attachEvent("on" + CPDOMEventKeyDown, keyEventCallback); + theDocument.attachEvent("on" + CPDOMEventKeyPress, keyEventCallback); + + _DOMWindow.onmousewheel = scrollEventCallback; + theDocument.onmousewheel = scrollEventCallback; + + theDocument.body.ondrag = function () { return NO; }; + theDocument.body.onselectstart = function () { return window.event.srcElement == _DOMPasteboardElement; }; + } + + ExcludedDOMElements["INPUT"] = YES; + ExcludedDOMElements["SELECT"] = YES; + ExcludedDOMElements["TEXTAREA"] = YES; + ExcludedDOMElements["OPTION"] = YES; + } + + return self; +} + +- (CPRect)frame +{ + return CGRectMakeCopy(_frame); +} + +- (CGRect)visibleFrame +{ + var frame = [self frame]; + + frame.origin = CGPointMakeZero(); + + if ([CPMenu menuBarVisible]) + { + var menuBarHeight = [[CPApp mainMenu] menuBarHeight]; + + frame.origin.y += menuBarHeight; + frame.size.height -= menuBarHeight; + } + + return frame; +} + +- (CPRect)contentBounds +{ + return CPRectCreateCopy(_contentBounds); +} + +- (CPDOMWindowLayer)layerAtLevel:(int)aLevel create:(BOOL)aFlag +{ + var layer = [_windowLayers objectForKey:aLevel]; + + // If the layer doesn't currently exist, and the create flag is true, + // create the layer. + if (!layer && aFlag) + { + layer = [[CPDOMWindowLayer alloc] initWithLevel:aLevel]; + + [_windowLayers setObject:layer forKey:aLevel]; + + // Find the nearest layer. This is similar to a binary search, + // only we know we won't find the value. + var low = 0, + high = _windowLevels.length - 1, + middle; + + while (low <= high) + { + middle = FLOOR((low + high) / 2); + + if (_windowLevels[middle] > aLevel) + high = middle - 1; + else + low = middle + 1; + } + + [_windowLevels insertObject:aLevel atIndex:_windowLevels[middle] > aLevel ? middle : middle + 1]; + layer._DOMElement.style.zIndex = aLevel; + _DOMBodyElement.appendChild(layer._DOMElement); + } + + return layer; +} + +- (void)order:(CPWindowOrderingMode)aPlace window:(CPWindow)aWindow relativeTo:(CPWindow)otherWindow +{ + // Grab the appropriate level for the layer, and create it if + // necessary (if we are not simply removing the window). + var layer = [self layerAtLevel:[aWindow level] create:aPlace != CPWindowOut]; + + // Ignore otherWindow, simply remove this window from it's level. + // If layer is nil, this will be a no-op. + if (aPlace == CPWindowOut) + return [layer removeWindow:aWindow]; + + // Place the window at the appropriate index. + [layer insertWindow:aWindow atIndex:(otherWindow ? (aPlace == CPWindowAbove ? otherWindow._index + 1 : otherWindow._index) : CPNotFound)]; +} + +- (CPView)_dragHitTest:(CPPoint)aPoint pasteboard:(CPPasteboard)aPasteboard +{ + var view = nil, + levels = _windowLevels, + layers = _windowLayers, + levelCount = levels.length; + + while (levelCount-- && !view) + { + // Skip any windows above or at the dragging level. + if (levels[levelCount] >= CPDraggingWindowLevel) + continue; + + var windows = [layers objectForKey:levels[levelCount]]._windows, + windowCount = windows.length; + + while (windowCount--) + { + var theWindow = windows[windowCount], + frame = theWindow._frame; + + if (CPRectContainsPoint(frame, aPoint)) + if (view = [theWindow._windowView _dragHitTest:CGPointMake(aPoint.x - frame.origin.x, aPoint.y - frame.origin.y) pasteboard:aPasteboard]) + return view; + else + return nil; + } + } + + return view; +} + +- (void)_propagateCurrentDOMEvent:(BOOL)aFlag +{ + StopDOMEventPropagation = !aFlag; +} + +- (CPWindow)hitTest:(CPPoint)location +{ + var levels = _windowLevels, + layers = _windowLayers, + levelCount = levels.length, + theWindow = nil; + + while (levelCount-- && !theWindow) + { + var windows = [layers objectForKey:levels[levelCount]]._windows, + windowCount = windows.length; + + while (windowCount-- && !theWindow) + if (CPRectContainsPoint(windows[windowCount]._frame, location)) + theWindow = windows[windowCount]; + } + + return theWindow; +} + +@end + +var CPDOMWindowGetFrame = function(_DOMWindow) +{ + var frame = nil;//CGRectMakeZero(); + + // We will rarely be able to get all this information, but we do the best we can: + if (_DOMWindow.outerWidth) + frame = CGRectMake(0, 0, _DOMWindow.outerWidth, _DOMWindow.outerHeight); + + else /*if(self.outerWidth)*/ + frame = CGRectMake(0, 0, -1, -1); + + if (window.screenTop) + frame.origin = CGPointMake(_DOMWindow.screenLeft, _DOMWindow.screenTop, 0); + + else if (window.screenX) + frame.origin = CGPointMake(_DOMWindow.screenX, _DOMWindow.screenY, 0); + + // Safari, Mozilla, Firefox, and Opera + if (_DOMWindow.innerWidth) + frame.size = CGSizeMake(_DOMWindow.innerWidth, _DOMWindow.innerHeight); + + // Internet Explorer 6 in Strict Mode + else if (document.documentElement && document.documentElement.clientWidth) + frame.size = CGSizeMake(_DOMWindow.document.documentElement.clientWidth, _DOMWindow.document.documentElement.clientHeight); + + // Internet Explorer X + else + frame.size = CGSizeMake(_DOMWindow.document.body.clientWidth, _DOMWindow.document.body.clientHeight); + + return frame; +} + +//right now we hard code q, w, r and t as keys to propogate +//these aren't normal keycodes, they are with modifier key codes +//might be mac only, we should investigate futher later. +var KeyCodesToPropagate = { '113':1, '119':1, '114':1, '116':1, '108':1, '102':1 }; +var KeyCodesWithoutKeyPressEvents = { '8':1, '9':1, '37':1, '38':1, '39':1, '40':1, '46':1 }; + +var CTRL_KEY_CODE = 17; + +@implementation CPDOMWindowBridge (Events) + +- (void)_bridgeMouseEvent:(DOMEvent)aDOMEvent +{ + var theType = _overriddenEventType || aDOMEvent.type; + + // IE's event order is down, up, up, dblclick, so we have create these events artificially. + if (theType == CPDOMEventDoubleClick) + { + _overriddenEventType = CPDOMEventMouseDown; + [self _bridgeMouseEvent:aDOMEvent]; + + _overriddenEventType = CPDOMEventMouseUp; + [self _bridgeMouseEvent:aDOMEvent]; + + _overriddenEventType = nil; + + return; + } + + try + { + var event, + location = _CGPointMake(aDOMEvent.clientX, aDOMEvent.clientY), + timestamp = aDOMEvent.timeStamp ? aDOMEvent.timeStamp : new Date(), + sourceElement = (aDOMEvent.target || aDOMEvent.srcElement), + windowNumber = 0, + modifierFlags = (aDOMEvent.shiftKey ? CPShiftKeyMask : 0) | + (aDOMEvent.ctrlKey ? CPControlKeyMask : 0) | + (aDOMEvent.altKey ? CPAlternateKeyMask : 0) | + (aDOMEvent.metaKey ? CPCommandKeyMask : 0); + + StopDOMEventPropagation = YES; + + if (_mouseDownWindow) + windowNumber = [_mouseDownWindow windowNumber]; + else + { + var theWindow = [self hitTest:location]; + + if (aDOMEvent.type == CPDOMEventMouseDown && theWindow) + _mouseDownWindow = theWindow; + + windowNumber = [theWindow windowNumber]; + } + + if (windowNumber) + { + var windowFrame = CPApp._windows[windowNumber]._frame; + + location.x -= _CGRectGetMinX(windowFrame); + location.y -= _CGRectGetMinY(windowFrame); + } + + switch (theType) + { + case CPDOMEventMouseUp: if(_mouseIsDown) + { + event = [CPEvent mouseEventWithType:CPLeftMouseUp location:location modifierFlags:modifierFlags + timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:-1 + clickCount:CPDOMEventGetClickCount(_lastMouseUp, timestamp, location) pressure:0]; + + _mouseIsDown = NO; + _lastMouseUp = event; + _mouseDownWindow = nil; + } + + if(_DOMEventMode) + { + _DOMEventMode = NO; + return; + } + + break; + + case CPDOMEventMouseDown: if (ExcludedDOMElements[sourceElement.tagName] && sourceElement != _DOMFocusElement) + { + _DOMEventMode = YES; + _mouseIsDown = YES; + + //fake a down and up event so that event tracking mode will work correctly + [CPApp sendEvent:[CPEvent mouseEventWithType:CPLeftMouseDown location:location modifierFlags:modifierFlags + timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:-1 + clickCount:CPDOMEventGetClickCount(_lastMouseDown, timestamp, location) pressure:0]]; + + [CPApp sendEvent:[CPEvent mouseEventWithType:CPLeftMouseUp location:location modifierFlags:modifierFlags + timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:-1 + clickCount:CPDOMEventGetClickCount(_lastMouseDown, timestamp, location) pressure:0]]; + + return; + } + + event = [CPEvent mouseEventWithType:CPLeftMouseDown location:location modifierFlags:modifierFlags + timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:-1 + clickCount:CPDOMEventGetClickCount(_lastMouseDown, timestamp, location) pressure:0]; + + _mouseIsDown = YES; + _lastMouseDown = event; + + break; + + case CPDOMEventMouseMoved: if (_DOMEventMode) + return; + + event = [CPEvent mouseEventWithType:_mouseIsDown ? CPLeftMouseDragged : CPMouseMoved + location:location modifierFlags:modifierFlags timestamp:timestamp + windowNumber:windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0]; + + _currentMousePosition = _CGPointMake(aDOMEvent.clientX, aDOMEvent.clientY); + + break; + } + + if (event) + { + event._DOMEvent = aDOMEvent; + + [CPApp sendEvent:event]; + } + + if (StopDOMEventPropagation) + CPDOMEventStop(aDOMEvent); + + [[CPRunLoop currentRunLoop] performSelectors]; + } + catch (anException) + { + objj_exception_report(anException, {path:@"CPDOMWindowBridge.j"}); + } +} + +- (void)_bridgeKeyEvent:(DOMEvent)aDOMEvent +{ + try + { + var event, + timestamp = aDOMEvent.timeStamp ? aDOMEvent.timeStamp : new Date(), + sourceElement = (aDOMEvent.target || aDOMEvent.srcElement), + windowNumber = [[CPApp keyWindow] windowNumber], + modifierFlags = (aDOMEvent.shiftKey ? CPShiftKeyMask : 0) | + (aDOMEvent.ctrlKey ? CPControlKeyMask : 0) | + (aDOMEvent.altKey ? CPAlternateKeyMask : 0) | + (aDOMEvent.metaKey ? CPCommandKeyMask : 0); + + if (ExcludedDOMElements[sourceElement.tagName] && sourceElement != _DOMFocusElement && sourceElement != _DOMPasteboardElement) + return; + + StopDOMEventPropagation = YES; + + if(KeyCodesToPropagate[aDOMEvent.keyCode]) + StopDOMEventPropagation = !(modifierFlags & (CPControlKeyMask | CPCommandKeyMask)); + + /*if (aDOMEvent.keyCode == 17) + StopDOMEventPropagation = NO; + if (aDOMEvent.keyCode != 17) + alert("WILL SEND " + modifierFlags + " " + aDOMEvent.type);*/ + + var isNativePasteEvent = NO, + isNativeCopyOrCutEvent = NO; + + switch (aDOMEvent.type) + { + case CPDOMEventKeyDown: // Grab and store the keycode now since it is correct and consistent at this point. + _keyCode = aDOMEvent.keyCode; + + var characters = String.fromCharCode(_keyCode).toLowerCase(); + + // If this could be a native PASTE event, then we need to further examine it before + // sending a CPEvent. Select our element to see if anything gets pasted in it. + if (characters == "v" && (modifierFlags & CPPlatformActionKeyMask)) + { + _DOMPasteboardElement.select(); + _DOMPasteboardElement.value = ""; + + isNativePasteEvent = YES; + } + + // Normally we return now because we let keypress send the actual CPEvent keyDown event, since we don't have + // a complete set of information yet. + + // However, of this could be a native COPY event, we need to let the normal event-process take place so it + // can capture our internal Cappuccino pasteboard. + else if ((characters == "c" || characters == "x") && (modifierFlags & CPPlatformActionKeyMask)) + isNativeCopyOrCutEvent = YES; + + // Also, certain browsers (IE and Safari), have broken keyboard supportwhere they don't send keypresses for certain events. + // So, allow the keypress event to handle the event if we are not a browser with broken (remedial) key support... + else if (!CPFeatureIsCompatible(CPJavascriptRemedialKeySupport)) + return; + + // Or, if this is not one of those special keycodes, and also not a ctrl+event + else if (!KeyCodesWithoutKeyPressEvents[_keyCode] && (_keyCode == CTRL_KEY_CODE || !(modifierFlags & CPControlKeyMask))) + return; + + // If this is in fact our broke state, continue to keypress and send the keydown. + case CPDOMEventKeyPress: + // If the source of this event is our pasteboard element, then simply let it continue + // as normal, so that the paste event can successfully complete. + if ((aDOMEvent.target || aDOMEvent.srcElement) == _DOMPasteboardElement) + return; + + var keyCode = _keyCode, + charCode = aDOMEvent.keyCode || aDOMEvent.charCode, + isARepeat = (_charCodes[keyCode] != nil); + + _charCodes[keyCode] = charCode; + + var characters = String.fromCharCode(charCode), + charactersIgnoringModifiers = characters.toLowerCase(); + + event = [CPEvent keyEventWithType:CPKeyDown location:location modifierFlags:modifierFlags + timestamp:timestamp windowNumber:windowNumber context:nil + characters:characters charactersIgnoringModifiers:charactersIgnoringModifiers isARepeat:isARepeat keyCode:keyCode]; + + if (isNativePasteEvent) + { + _pasteboardKeyDownEvent = event; + + window.setTimeout(function () { [self _checkPasteboardElement] }, 0); + + return; + } + + break; + + case CPDOMEventKeyUp: var keyCode = aDOMEvent.keyCode, + charCode = _charCodes[keyCode]; + + _charCodes[keyCode] = nil; + + var characters = String.fromCharCode(charCode), + charactersIgnoringModifiers = characters.toLowerCase(); + + if (!(modifierFlags & CPShiftKeyMask)) + characters = charactersIgnoringModifiers; + + event = [CPEvent keyEventWithType:CPKeyUp location:location modifierFlags:modifierFlags + timestamp: timestamp windowNumber:windowNumber context:nil + characters:characters charactersIgnoringModifiers:charactersIgnoringModifiers isARepeat:NO keyCode:keyCode]; + break; + } + + if (event) + { + event._DOMEvent = aDOMEvent; + + [CPApp sendEvent:event]; + + if (isNativeCopyOrCutEvent) + { + var pasteboard = [CPPasteboard generalPasteboard], + types = [pasteboard types]; + + // If this is a native copy event, then check if the pasteboard has anything in it. + if (types.length) + { + if ([types indexOfObjectIdenticalTo:CPStringPboardType] != CPNotFound) + _DOMPasteboardElement.value = [pasteboard stringForType:CPStringPboardType]; + else + _DOMPasteboardElement.value = [pasteboard _generateStateUID]; + + _DOMPasteboardElement.select(); + + window.setTimeout(function() { [self _clearPasteboardElement]; }, 0); + } + + return; + } + } + + if (StopDOMEventPropagation) + CPDOMEventStop(aDOMEvent); + + [[CPRunLoop currentRunLoop] performSelectors]; + } + catch (anException) + { + objj_exception_report(anException, {path:@"CPDOMWindowBridge.j"}); + } +} + +- (void)_bridgeScrollEvent:(DOMEvent)aDOMEvent +{ + if(!aDOMEvent) + aDOMEvent = window.event; + + try + { + var deltaX = 0.0, + deltaY = 0.0, + windowNumber = 0, + location = CGPointMake(_currentMousePosition.x, _currentMousePosition.y), + timestamp = aDOMEvent.timeStamp ? aDOMEvent.timeStamp : new Date(), + modifierFlags = (aDOMEvent.shiftKey ? CPShiftKeyMask : 0) | + (aDOMEvent.ctrlKey ? CPControlKeyMask : 0) | + (aDOMEvent.altKey ? CPAlternateKeyMask : 0) | + (aDOMEvent.metaKey ? CPCommandKeyMask : 0); + + StopDOMEventPropagation = YES; + + windowNumber = [[self hitTest:location] windowNumber]; + + if (!windowNumber) + return; + + var windowFrame = CPApp._windows[windowNumber]._frame; + + location.x -= CGRectGetMinX(windowFrame); + location.y -= CGRectGetMinY(windowFrame); + + if(typeof aDOMEvent.wheelDeltaX != "undefined") + { + deltaX = aDOMEvent.wheelDeltaX / 120.0; + deltaY = aDOMEvent.wheelDeltaY / 120.0; + } + + else if (aDOMEvent.wheelDelta) + deltaY = aDOMEvent.wheelDelta / 120.0; + + else if (aDOMEvent.detail) + deltaY = -aDOMEvent.detail / 3.0; + + else + return; + + if(!CPFeatureIsCompatible(CPJavaScriptNegativeMouseWheelValues)) + { + deltaX = -deltaX; + deltaY = -deltaY; + } + + var event = [CPEvent mouseEventWithType:CPScrollWheel location:location modifierFlags:modifierFlags + timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0 ]; + + event._DOMEvent = aDOMEvent; + event._deltaX = ROUND(deltaX * 1.5); + event._deltaY = ROUND(deltaY * 1.5); + + [CPApp sendEvent:event]; + + if (StopDOMEventPropagation) + CPDOMEventStop(aDOMEvent); + + [[CPRunLoop currentRunLoop] performSelectors]; + } + catch (anException) + { + objj_exception_report(anException, {path:@"CPDOMWindowBridge.j"}); + } + +} + +- (void)_bridgeResizeEvent:(DOMEvent)aDOMEvent +{ + try + { + // FIXME: This is not the right way to do this. + // We should pay attention to mouse down and mouse up in conjunction with this. + //window.liveResize = YES; + + var oldSize = _frame.size; + + // window.liveResize = YES? + _frame = CPDOMWindowGetFrame(_DOMWindow); + _contentBounds.size = CGSizeCreateCopy(_frame.size); + + var levels = _windowLevels, + layers = _windowLayers, + levelCount = levels.length; + + while (levelCount--) + { + var windows = [layers objectForKey:levels[levelCount]]._windows, + windowCount = windows.length; + + while (windowCount--) + [windows[windowCount] resizeWithOldBridgeSize:oldSize]; + } + + //window.liveResize = NO; + + [[CPRunLoop currentRunLoop] performSelectors]; + + } + catch (anException) + { + objj_exception_report(anException, {path:@"CPDOMWindowBridge.j"}); + } +} + +- (void)_checkPasteboardElement +{ + try + { + var value = _DOMPasteboardElement.value; + + if ([value length]) + { + var pasteboard = [CPPasteboard generalPasteboard]; + + if ([pasteboard _stateUID] != value) + { + [pasteboard declareTypes:[CPStringPboardType] owner:self]; + + [pasteboard setString:value forType:CPStringPboardType]; + } + } + + [self _clearPasteboardElement]; + + [CPApp sendEvent:_pasteboardKeyDownEvent]; + + _pasteboardKeyDownEvent = nil; + + [[CPRunLoop currentRunLoop] performSelectors]; + } + catch (anException) + { + objj_exception_report(anException, {path:@"CPDOMWindowBridge.j"}); + } +} + +- (void)_clearPasteboardElement +{ + _DOMPasteboardElement.value = ""; + _DOMPasteboardElement.blur(); +} + +@end + +var CLICK_SPACE_DELTA = 5.0, + CLICK_TIME_DELTA = document.addEventListener ? 350.0 : 1000.0; + +var CPDOMEventGetClickCount = function(aComparisonEvent, aTimestamp, aLocation) +{ + if (!aComparisonEvent) + return 1; + + var comparisonLocation = [aComparisonEvent locationInWindow]; + + return (aTimestamp - [aComparisonEvent timestamp] < CLICK_TIME_DELTA && + ABS(comparisonLocation.x - aLocation.x) < CLICK_SPACE_DELTA && + ABS(comparisonLocation.y - aLocation.y) < CLICK_SPACE_DELTA) ? [aComparisonEvent clickCount] + 1 : 1; +} + +var CPDOMEventStop = function(aDOMEvent) +{ + // IE Model + aDOMEvent.cancelBubble = true; + aDOMEvent.returnValue = false; + + // W3C Model + if (aDOMEvent.preventDefault) + aDOMEvent.preventDefault(); + + if (aDOMEvent.stopPropagation) + aDOMEvent.stopPropagation(); + + if (aDOMEvent.type == CPDOMEventMouseDown) + { + CPSharedDOMWindowBridge._DOMFocusElement.focus(); + CPSharedDOMWindowBridge._DOMFocusElement.blur(); + } +} + +/* + +*/ \ No newline at end of file diff --git a/AppKit/Platform/DOM/CPDOMWindowLayer.j b/AppKit/Platform/DOM/CPDOMWindowLayer.j new file mode 100644 index 000000000..85393aa2a --- /dev/null +++ b/AppKit/Platform/DOM/CPDOMWindowLayer.j @@ -0,0 +1,119 @@ +/* + * CPDOMWindowLayer.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import + +#include "CPDOMDisplayServer.h" + + +@implementation CPDOMWindowLayer : CPObject +{ + int _level; + CPArray _windows; + DOMElement _DOMElement; +} + +- (id)initWithLevel:(int)aLevel +{ + self = [super init]; + + if (self) + { + _level = aLevel; + + _windows = []; + + _DOMElement = document.createElement("div"); + _DOMElement.style.position = "absolute"; + _DOMElement.style.top = "0px"; + _DOMElement.style.left = "0px"; + _DOMElement.style.width = "1px"; + _DOMElement.style.height = "1px"; + } + + return self; +} + +- (int)level +{ + return _level; +} + +- (void)removeWindow:(CPWindow)aWindow +{ + var index = aWindow._index, + count = _windows.length - 1; + + CPDOMDisplayServerRemoveChild(_DOMElement, aWindow._DOMElement); + + [_windows removeObjectAtIndex:aWindow._index]; + + for (; index < count; ++index) + { + _windows[index]._index = index; + _windows[index]._DOMElement.style.zIndex = index; + } + + aWindow._isVisible = NO; +} + +- (void)insertWindow:(CPWindow)aWindow atIndex:(unsigned)anIndex +{ + // We will have to adjust the z-index of all windows starting at this index. + var count = [_windows count], + zIndex = (anIndex == CPNotFound ? count : anIndex), + isVisible = aWindow._isVisible; + + // If the window is already a resident of this layer, remove it. + if (isVisible) + { + zIndex = MIN(zIndex, aWindow._index); + [_windows removeObjectAtIndex:aWindow._index]; + } + else + ++count; + + if (anIndex == CPNotFound || anIndex >= count) + [_windows addObject:aWindow]; + else + [_windows insertObject:aWindow atIndex:anIndex]; + + // Adjust all the affected z-indexes. + for (; zIndex < count; ++zIndex) + { + _windows[zIndex]._index = zIndex; + _windows[zIndex]._DOMElement.style.zIndex = zIndex; + } + // If the window is not already a resident of this layer, add it. + if (!isVisible) + { + CPDOMDisplayServerAppendChild(_DOMElement, aWindow._DOMElement); + + aWindow._isVisible = YES; + + if ([aWindow styleMask] & CPBorderlessBridgeWindowMask) + [aWindow setFrame:[aWindow._bridge contentBounds]]; + } +} + +@end diff --git a/AppKit/Platform/Platform.h b/AppKit/Platform/Platform.h new file mode 100644 index 000000000..7e763be27 --- /dev/null +++ b/AppKit/Platform/Platform.h @@ -0,0 +1,25 @@ +/* + * Platform.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define PLATFORM(FEATURE) (defined( PLATFORM_##FEATURE ) && PLATFORM_##FEATURE) + +#define PLATFORM_DOM 1 diff --git a/AppKit/Resources/CPApplication/New.png b/AppKit/Resources/CPApplication/New.png new file mode 100644 index 0000000000000000000000000000000000000000..16c1817bb5486478a12442188186b24ac1be8dae GIT binary patch literal 3240 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPApplication/SaveHighlighted.png b/AppKit/Resources/CPApplication/SaveHighlighted.png new file mode 100644 index 0000000000000000000000000000000000000000..e84e392b0c9e0995f0c13d609baf8ea6586c3637 GIT binary patch literal 471 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPButton/CPButtonHUDRegular1.png b/AppKit/Resources/CPButton/CPButtonHUDRegular1.png new file mode 100644 index 0000000000000000000000000000000000000000..31fb7a109242dbcf9d29529efea91daafff795c2 GIT binary patch literal 2844 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPButton/CPButtonHUDRegularHighlighted0.png b/AppKit/Resources/CPButton/CPButtonHUDRegularHighlighted0.png new file mode 100644 index 0000000000000000000000000000000000000000..78d5e3ac30c943f1aac5f087a3d7a62b4986ca0e GIT binary patch literal 3300 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPButton/CPButtonRoundRectRegular1.png b/AppKit/Resources/CPButton/CPButtonRoundRectRegular1.png new file mode 100644 index 0000000000000000000000000000000000000000..e874e8d12065d50c802c2c8c09dc94e6dd79e30b GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{J!3HE}g>Tsdq$EpRBT9nv(@M${i&7aJQ}UBi z6+Ckj(^G>|6H_V+Po~-c73q7rIEGZ*N{ZW>bv3;0{{H&^>A(K}w`Xqo@%_C#8{@Pe nzrX7ni7($JtnOFC%wfQA{hm2{%j^YuK&=d(u6{1-oD!M$0bZY=A7JHosMXp?0iB67+ade`3Bhc!jfK0AjS%F`c!y-oY5-4ia_4b!&fLkR zEX&F<#uQ)&^`&jwTf;Cu&>v7u(_pel(-f`O>u$AL)v$e36y@rdvaV}<$g(W4>$;h3 z+e=75d!nkU@ECpH&p~YNg>>KdXpFKf3p~$Xnx=V9k|%|Pk|dpQ9CtS~lVur3GjJTI zfS)*vALRP^So6x0aDs0>TDo2gbm}0H>#=v)d-is zmVa!e{RKbjy1ocXaU8!iO~V@!>DOEu(|(p^DO6XTgKgVBR8<9hK{gdB{Wpd8q9}&G z?-v#Ee9id0>8b9cC_z>%07*qoM6N<$f}n$<1^@s6 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPButton/CPButtonRoundRectRegularHighlighted1.png b/AppKit/Resources/CPButton/CPButtonRoundRectRegularHighlighted1.png new file mode 100644 index 0000000000000000000000000000000000000000..cea07927a2fd4c505a28ef291826acc310e4a359 GIT binary patch literal 133 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{J!2~2lO_g5*DajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_d9Me3d|jv*DdlA<;yu}+>fOG=o-z{tqxAcL{7F;}lQ&x-b& eH*QEM9AMbBkGbN3Z}2wV`-6K!rdE1;6Wz$unqx=a+oh&CWO9%4S-ETS) zRaK?S-fub*WLajoTyx6$2fDLD90Zj_9BS!3HE91=ODbDajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_d9MID|ljv*DdlIGY}Z?k1)cE0}q|NpZR7Z|vWjXzt(#>OfZ z78bJcoZMgkpR2R8(~zMw$*YND0*jfa+6)ylhHF3H-?zUrX-ALhn#nbur{1Kbq#T*j zBH4L0Vglc$nA0t%JvOMAo0}g#-Y|6H_V+Po~-c6&ZTEIEGZ*N}6MuE%tb^d;g4o|No!=^8UWP8XFs%0q-FL p!xXz+5+SymXU>#l4&YNb!0<`g@Z-D48wEhk44$rjF6*2UngEJ!FD3v0 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPButton/CPButtonTexturedRoundedRegular2.png b/AppKit/Resources/CPButton/CPButtonTexturedRoundedRegular2.png new file mode 100644 index 0000000000000000000000000000000000000000..49b44ab98522ce692296e59f1108106699d9803a GIT binary patch literal 232 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPButton/CPButtonTexturedRoundedRegularHighlighted1.png b/AppKit/Resources/CPButton/CPButtonTexturedRoundedRegularHighlighted1.png new file mode 100644 index 0000000000000000000000000000000000000000..0b44ef2a3b22e84de19f32000aef5513bf554e46 GIT binary patch literal 2841 zcmV+!3+D8RP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0000)NklKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0002~Nkl#%=6rVhyV}~C!D4UcSl4J5i*mA;PH4+#&JYdds27D%n%VuDFqQB zA{d4NRqbMJ0j{^Il9?#b{jRC3c^DL?*2GEu+B6^@E)V92eBI1N*hP%Ij4qJ6* zMy(Yy>lURguBTP`0KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0001ZNklKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0001bNklUWF##Ai{P&j8D!I3BlY<%j?P002ovPDHLkV1g5gV9o#l literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPImageView/CPImageViewBottomShadow.png b/AppKit/Resources/CPImageView/CPImageViewBottomShadow.png new file mode 100644 index 0000000000000000000000000000000000000000..5fc3ef0216ef920d875275dcfe8aab9a13d11b98 GIT binary patch literal 2758 zcmV;%3OV(OP)4Tx0C=38Q)g6D=@vcr-t0tDdAZ9o73 zZrB8d;W+$%P#4PN3IHSw0H%w?*+KxM5CAfA6*2_?G713fq;#1A03`qbTOJ!14}fX` z06S%pPXhpU(j@l+0JbPoDgr>G06-?n6o~-P4ggq}qZEq(uwVcv%8`h30kE3@V3MKC zlmKAw0Dzq-7Gwhu7yw|R5DQZQ2=)NLkVi%E00=VyD2$Y^c+yu~A!A zINCaVwW$9Z{ELWe@Q#JLh_3eL-tiX;k2mK2vr z|C5P-v+NI;ylVhp)qV!{LR(O~$_DJ0E+DYzfFK@c*+ zL|BM6Vt|+;)`%m*MP?y>NH7wC#36}D3L-_6$WmlAQi7BtRmfhX9{C7|KA|s2*yD+M!(38x2CE(D`Tzx(Llj3(*Z|C0c_XLYvXE=oR!9+KWC% z$1uR?7zZ=NY%ngy!$PrmEE$ty%dujt0;|Cqu{Nv|yMgs$BiMTaiNGS@1RH`oA&@Ya zAS5gzEGLu_st5-N&4doZ4MHDbl<=9zBT%>LK-$#>ix{Hrbl&K@KGg$O>{1c{}+K`84@D zd4T+mLZ=u|94Y>kc#4!#K&hY{q@1E$rwmfYscKYHsv9+wDxxl?mQib|ZPcsO0qQtS zon}t+pheNrXsc+Iv_{%_+C$naI-PDrccq8ZCG?f_O8Q~?MS36oJwtCX;E#^kT*{70eCHdgeLiW9B;*mWr(kUqz&{LZw=zS>?LQ3stJBsj9c? z0@Zxg3e}^kS5-&UsA^_vJT-yZah$}`!vpJ^s_LQF^k6%vR1QdS?5^;Y!cg?&1a{vOW5DByV;|f8k#dSqc!t1t2Iw* z_HrV>*%V3s)#9)iTX@h6DChm=A;FWj>K5D3I7-*<8+-ulv zIBsNaG}oxWsLAM&G0m83oNT02{%vlz3r zW-Vqz=33@_^L+CL^M@8p3r~wh7Bv<(ElHMK%XG_~me;IMD<`W|t7@yO)~L0!wZwX- zb`d(9?KatU+I_Znvd^%uwSVBC z;V|2wz@g3IH%BW+p<}h<&FReP{?k`XZ=L>fhV=~bj9oMCI5S6S0C3Et|wgIyE(fl+>W^Y>Tctn?tajHXr}p0@yyzp z{T@ah0*}2Oy|eIHiL>_1>h(1A6nNHnKJha45_#2m4SHL8r+FXpe&J*9BlkJx^Oonv zTgE%%i}?ol7W;PlY52|ctMYs7Z{(li-{3zQ;1sYV;7lMfFeq?S;2pjmU&ycLkIr_P zy=-?QME!`u_BZjF^n3OiE^A=5eWpG+o+}rJt3T)g!Z(70G%Rxh>kdXjC2~uggZV z=V!Mn*b14VOKG88qwLF>l~bMbE;l;&Xr6kWG_Py1)#CMw2lM^&zg?sbH9l6Bqdr?20>{&TUY_;QJTNkz%WQeo-kZydg<{AOZ9@`mm*=dxWJ zNgJgbZ*TJ4bf8?lJiokubI9iAE%=t=Ew8sO++@f7m10b9ZmR-sT#!nu>j-eL4G{)<)NM ze#`x~zD}pEr0&yx>HgjW5eGWzUFz!(>K-g>KpT_|!-o^R0cR@{sWv6JT3QtX(&ObeNMs{Z8Y|7dG_J!>a&c&X)*%98+eLm>?#S8uy&UJcs zp1$aD@x&#!OUEyBFSlHAzS7*~)OGA9r=N~>J9jrbX7l_T4)PcY5!N?hf6{xcBmY&i(NRD<2Xc7C%yZRPk8%am~+`KR5L{ z_nz$Y?dy6H`Q$;ru>bi#vj6dMpzta4X~m$yVEvHe(1~IH;cL(4JsWr~dp44_~BQtU%N(QM+aWYUrzj1`bzuN{?{{Jw~vL5J${qVa;gX-B8kEePT@9oBaMOe0H9z6r@6|=WB>pF M07*qoM6N<$g8oxa>i_@% literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPImageView/CPImageViewLeftShadow.png b/AppKit/Resources/CPImageView/CPImageViewLeftShadow.png new file mode 100644 index 0000000000000000000000000000000000000000..a67f66f47c7183a8ea40245ec0bc7ad146d9d2bb GIT binary patch literal 2800 zcmV*(P)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0000RNkl*SU|=u+00030{{sL4dH`Y|D@bPm0000r literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPImageView/CPImageViewRightShadow.png b/AppKit/Resources/CPImageView/CPImageViewRightShadow.png new file mode 100644 index 0000000000000000000000000000000000000000..1b3cf77573e814fdc1b066c9ea51988d6767f9cd GIT binary patch literal 2746 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPImageView/CPImageViewTopRightShadow.png b/AppKit/Resources/CPImageView/CPImageViewTopRightShadow.png new file mode 100644 index 0000000000000000000000000000000000000000..818d7f73d60f91876ca784993851541142cad0af GIT binary patch literal 2878 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 b^K#b!rZJnyU|5b@00000NkvXXu0mjfE5KFJ literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPMenuItem/CPMenuItemOnStateHighlighted.png b/AppKit/Resources/CPMenuItem/CPMenuItemOnStateHighlighted.png new file mode 100644 index 0000000000000000000000000000000000000000..116fe0550b1d1fb9580aad0b28042ded05a03731 GIT binary patch literal 2875 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 Z2LN8C$tSP?s9OL4002ovPDHLkV1lzwQ$+v( literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPProgressIndicator/CPProgressIndicatorBarBarRegular.png b/AppKit/Resources/CPProgressIndicator/CPProgressIndicatorBarBarRegular.png new file mode 100644 index 0000000000000000000000000000000000000000..df417762c477d5f8c40c1ce883b48f9f90be2534 GIT binary patch literal 2818 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPProgressIndicator/CPProgressIndicatorBezelBorderHUDBarSmall0.png b/AppKit/Resources/CPProgressIndicator/CPProgressIndicatorBezelBorderHUDBarSmall0.png new file mode 100644 index 0000000000000000000000000000000000000000..113dbb5cfe9cb6b83706f2863a6d4f0b5a0dceea GIT binary patch literal 2838 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif b/AppKit/Resources/CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif new file mode 100644 index 0000000000000000000000000000000000000000..0d2567cd01553badc23cce79cdaa7bbd95178927 GIT binary patch literal 4481 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPScroller/CPScrollerDecrementArrowHorizontalRegular.png b/AppKit/Resources/CPScroller/CPScrollerDecrementArrowHorizontalRegular.png new file mode 100644 index 0000000000000000000000000000000000000000..9ab26e2fc26bc828a61e9259a47efaa61cbdb2a4 GIT binary patch literal 3200 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 Sc%|h40000 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPScroller/CPScrollerDecrementArrowVerticalRegular.png b/AppKit/Resources/CPScroller/CPScrollerDecrementArrowVerticalRegular.png new file mode 100644 index 0000000000000000000000000000000000000000..6421e7426332a6dd65837bb35ba4a432dad5d299 GIT binary patch literal 472 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 A0RR91 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPScroller/CPScrollerIncrementArrowVerticalRegularHighlighted.png b/AppKit/Resources/CPScroller/CPScrollerIncrementArrowVerticalRegularHighlighted.png new file mode 100644 index 0000000000000000000000000000000000000000..13006d9a3f8871c6b7d5360c5213beb13d6bba71 GIT binary patch literal 472 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 LNkvXXu0mjfyntG( literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPScroller/CPScrollerKnobHorizontalRegular2.png b/AppKit/Resources/CPScroller/CPScrollerKnobHorizontalRegular2.png new file mode 100644 index 0000000000000000000000000000000000000000..913b0d9ea4eaf672f5e79759981d77dc767eb98b GIT binary patch literal 3031 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 Z{{R;}v1>($VZi_Z002ovPDHLkV1gaD$)f-O literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPScroller/CPScrollerKnobSlotHorizontalRegular.png b/AppKit/Resources/CPScroller/CPScrollerKnobSlotHorizontalRegular.png new file mode 100644 index 0000000000000000000000000000000000000000..60c5300b9d00d2d858076029b0be8d600846464b GIT binary patch literal 2808 zcmV4Tx0C=38Q)g6D=@vcr-t0tDdAZ9o73 zZrB8d;W+$%P#4PN3IHSw0H%w?*+KxM5CAfA6*2_?G713fq;#1A03`qbTOJ!14}fX` z06S%pPXhpU(j@l+0JbPoDgr>G06-?n6o~-P4ggq}qZEq(uwVcv%8`h30kE3@V3MKC zlmKAw0Dzq-7Gwhu7yw|R5DQZQ2=)NLkVi%E00=VyD2$Y^c+yu~A!A zINCaVwW$9Z{ELWe@Q#JLh_3eL-tiX;k2mK2vr z|C5P-v+NI;ylVhp)qV!{LR(O~$_DJ0E+DYzfFK@c*+ zL|BM6Vt|+;)`%m*MP?y>NH7wC#36}D3L-_6$WmlAQi7BtRmfhX9{C7|KA|s2*yD+M!(38x2CE(D`Tzx(Llj3(*Z|C0c_XLYvXE=oR!9+KWC% z$1uR?7zZ=NY%ngy!$PrmEE$ty%dujt0;|Cqu{Nv|yMgs$BiMTaiNGS@1RH`oA&@Ya zAS5gzEGLu_st5-N&4doZ4MHDbl<=9zBT%>LK-$#>ix{Hrbl&K@KGg$O>{1c{}+K`84@D zd4T+mLZ=u|94Y>kc#4!#K&hY{q@1E$rwmfYscKYHsv9+wDxxl?mQib|ZPcsO0qQtS zon}t+pheNrXsc+Iv_{%_+C$naI-PDrccq8ZCG?f_O8Q~?MS36oJwtCX;E#^kT*{70eCHdgeLiW9B;*mWr(kUqz&{LZw=zS>?LQ3stJBsj9c? z0@Zxg3e}^kS5-&UsA^_vJT-yZah$}`!vpJ^s_LQF^k6%vR1QdS?5^;Y!cg?&1a{vOW5DByV;|f8k#dSqc!t1t2Iw* z_HrV>*%V3s)#9)iTX@h6DChm=A;FWj>K5D3I7-*<8+-ulv zIBsNaG}oxWsLAM&G0m83oNT02{%vlz3r zW-Vqz=33@_^L+CL^M@8p3r~wh7Bv<(ElHMK%XG_~me;IMD<`W|t7@yO)~L0!wZwX- zb`d(9?KatU+I_Znvd^%uwSVBC z;V|2wz@g3IH%BW+p<}h<&FReP{?k`XZ=L>fhV=~bj9oMCI5S6S0C3Et|wgIyE(fl+>W^Y>Tctn?tajHXr}p0@yyzp z{T@ah0*}2Oy|eIHiL>_1>h(1A6nNHnKJha45_#2m4SHL8r+FXpe&J*9BlkJx^Oonv zTgE%%i}?ol7W;PlY52|ctMYs7Z{(li-{3zQ;1sYV;7lMfFeq?S;2pjmU&ycLkIr_P zy=-?QME!`u_BZjF^n3OiE^A=5eWpG+o+}rJt3T)g!Z(70G%Rxh>kdXjC2~uggZV z=V!Mn*b14VOKG88qwLF>l~bMbE;l;&Xr6kWG_Py1)#CMw2lM^&zg?sbH9l6Bqdr?20>{&TUY_;QJTNkz%WQeo-kZydg<{AOZ9@`mm*=dxWJ zNgJgbZ*TJ4bf8?lJiokubI9iAE%=t=Ew8sO++@f7m10b9ZmR-sT#!nu>j-eL4G{)<)NM ze#`x~zD}pEr0&yx>HgjW5eGWzUFz!(>K-g>KpT_|!-o^R0cR@{sWv6JT3QtX(&ObeNMs{Z8Y|7dG_J!>a&c&X)*%98+eLm>?#S8uy&UJcs zp1$aD@x&#!OUEyBFSlHAzS7*~)OGA9r=N~>J9jrbX7l_T4)PcY5!N?hf6{xcBmY&i(NRD<2Xc7C%yZRPk8%am~+`KR5L{ z_nz$Y?dy6H`Q$;ru>bi#vj6dMpzta4X~m$yVEvHe(1~IH;cL(4JsWr~dp44_~BQtU%N(QM+aWYUrzj1`bzuN{?{{Jw~vL5J${q(_=B>(^b0001b zB>(^b0001bB>(^b0001bC2}$zU;qFB32;bRa{vGf6951U69E94oEQKA04+&GK~xBt zV<;*r`p=}Ttz|7Cj-v9vW@CO>5kS$IC0000< KMNUMnLSTX|5nsjt literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPScroller/CPScrollerKnobSlotVerticalRegular.png b/AppKit/Resources/CPScroller/CPScrollerKnobSlotVerticalRegular.png new file mode 100644 index 0000000000000000000000000000000000000000..8dff1370b4c4940aab5a0965ab01e1cc9aada67d GIT binary patch literal 2822 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 Y0KxAFS5D?ig#Z8m07*qoM6N<$f-JW|0ssI2 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPScroller/CPScrollerKnobSlotVerticalSmall.png b/AppKit/Resources/CPScroller/CPScrollerKnobSlotVerticalSmall.png new file mode 100644 index 0000000000000000000000000000000000000000..181b1debb678d34955eb7afb7bb277961a6c6b6c GIT binary patch literal 2821 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 Xk+uWoaK_@=00000NkvXXu0mjfj+;Bj literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPScroller/CPScrollerKnobVerticalRegular0.png b/AppKit/Resources/CPScroller/CPScrollerKnobVerticalRegular0.png new file mode 100644 index 0000000000000000000000000000000000000000..3ddbaca6f4c40f45d2332e79445b586171df939e GIT binary patch literal 3020 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPScroller/CPScrollerKnobVerticalRegular2.png b/AppKit/Resources/CPScroller/CPScrollerKnobVerticalRegular2.png new file mode 100644 index 0000000000000000000000000000000000000000..2100b9992dff99c0d9358ec80b30b2b3b3210996 GIT binary patch literal 3004 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPScroller/CPScrollerKnobVerticalSmall1.png b/AppKit/Resources/CPScroller/CPScrollerKnobVerticalSmall1.png new file mode 100644 index 0000000000000000000000000000000000000000..534c519835abc4799914a82a297b59eea1a4ccc0 GIT binary patch literal 2822 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 Y0Dy5FSFh>hl>h($07*qoM6N<$f^En;MgRZ+ literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPScroller/CPScrollerKnobVerticalSmall2.png b/AppKit/Resources/CPScroller/CPScrollerKnobVerticalSmall2.png new file mode 100644 index 0000000000000000000000000000000000000000..a6aa8d5803b35bb3154894e0bee9b02f3100511a GIT binary patch literal 2926 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPShadowView/CPShadowViewHeavyBottomRight.png b/AppKit/Resources/CPShadowView/CPShadowViewHeavyBottomRight.png new file mode 100644 index 0000000000000000000000000000000000000000..77718b1c74731117c53842125217d5a500e1fd4d GIT binary patch literal 2973 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 TVs=9T00000NkvXXu0mjfj9Gg> literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPShadowView/CPShadowViewHeavyLeft.png b/AppKit/Resources/CPShadowView/CPShadowViewHeavyLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..8a3e888000bb522f21c581ac431306b54a0fc4f3 GIT binary patch literal 2819 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 BecAv3 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPShadowView/CPShadowViewLightBottom.png b/AppKit/Resources/CPShadowView/CPShadowViewLightBottom.png new file mode 100644 index 0000000000000000000000000000000000000000..5fc3ef0216ef920d875275dcfe8aab9a13d11b98 GIT binary patch literal 2758 zcmV;%3OV(OP)4Tx0C=38Q)g6D=@vcr-t0tDdAZ9o73 zZrB8d;W+$%P#4PN3IHSw0H%w?*+KxM5CAfA6*2_?G713fq;#1A03`qbTOJ!14}fX` z06S%pPXhpU(j@l+0JbPoDgr>G06-?n6o~-P4ggq}qZEq(uwVcv%8`h30kE3@V3MKC zlmKAw0Dzq-7Gwhu7yw|R5DQZQ2=)NLkVi%E00=VyD2$Y^c+yu~A!A zINCaVwW$9Z{ELWe@Q#JLh_3eL-tiX;k2mK2vr z|C5P-v+NI;ylVhp)qV!{LR(O~$_DJ0E+DYzfFK@c*+ zL|BM6Vt|+;)`%m*MP?y>NH7wC#36}D3L-_6$WmlAQi7BtRmfhX9{C7|KA|s2*yD+M!(38x2CE(D`Tzx(Llj3(*Z|C0c_XLYvXE=oR!9+KWC% z$1uR?7zZ=NY%ngy!$PrmEE$ty%dujt0;|Cqu{Nv|yMgs$BiMTaiNGS@1RH`oA&@Ya zAS5gzEGLu_st5-N&4doZ4MHDbl<=9zBT%>LK-$#>ix{Hrbl&K@KGg$O>{1c{}+K`84@D zd4T+mLZ=u|94Y>kc#4!#K&hY{q@1E$rwmfYscKYHsv9+wDxxl?mQib|ZPcsO0qQtS zon}t+pheNrXsc+Iv_{%_+C$naI-PDrccq8ZCG?f_O8Q~?MS36oJwtCX;E#^kT*{70eCHdgeLiW9B;*mWr(kUqz&{LZw=zS>?LQ3stJBsj9c? z0@Zxg3e}^kS5-&UsA^_vJT-yZah$}`!vpJ^s_LQF^k6%vR1QdS?5^;Y!cg?&1a{vOW5DByV;|f8k#dSqc!t1t2Iw* z_HrV>*%V3s)#9)iTX@h6DChm=A;FWj>K5D3I7-*<8+-ulv zIBsNaG}oxWsLAM&G0m83oNT02{%vlz3r zW-Vqz=33@_^L+CL^M@8p3r~wh7Bv<(ElHMK%XG_~me;IMD<`W|t7@yO)~L0!wZwX- zb`d(9?KatU+I_Znvd^%uwSVBC z;V|2wz@g3IH%BW+p<}h<&FReP{?k`XZ=L>fhV=~bj9oMCI5S6S0C3Et|wgIyE(fl+>W^Y>Tctn?tajHXr}p0@yyzp z{T@ah0*}2Oy|eIHiL>_1>h(1A6nNHnKJha45_#2m4SHL8r+FXpe&J*9BlkJx^Oonv zTgE%%i}?ol7W;PlY52|ctMYs7Z{(li-{3zQ;1sYV;7lMfFeq?S;2pjmU&ycLkIr_P zy=-?QME!`u_BZjF^n3OiE^A=5eWpG+o+}rJt3T)g!Z(70G%Rxh>kdXjC2~uggZV z=V!Mn*b14VOKG88qwLF>l~bMbE;l;&Xr6kWG_Py1)#CMw2lM^&zg?sbH9l6Bqdr?20>{&TUY_;QJTNkz%WQeo-kZydg<{AOZ9@`mm*=dxWJ zNgJgbZ*TJ4bf8?lJiokubI9iAE%=t=Ew8sO++@f7m10b9ZmR-sT#!nu>j-eL4G{)<)NM ze#`x~zD}pEr0&yx>HgjW5eGWzUFz!(>K-g>KpT_|!-o^R0cR@{sWv6JT3QtX(&ObeNMs{Z8Y|7dG_J!>a&c&X)*%98+eLm>?#S8uy&UJcs zp1$aD@x&#!OUEyBFSlHAzS7*~)OGA9r=N~>J9jrbX7l_T4)PcY5!N?hf6{xcBmY&i(NRD<2Xc7C%yZRPk8%am~+`KR5L{ z_nz$Y?dy6H`Q$;ru>bi#vj6dMpzta4X~m$yVEvHe(1~IH;cL(4JsWr~dp44_~BQtU%N(QM+aWYUrzj1`bzuN{?{{Jw~vL5J${qVa;gX-B8kEePT@9oBaMOe0H9z6r@6|=WB>pF M07*qoM6N<$g8oxa>i_@% literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPShadowView/CPShadowViewLightBottomLeft.png b/AppKit/Resources/CPShadowView/CPShadowViewLightBottomLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..654ef3cc6cc540e2f9e64664ffa788b03d77fcb9 GIT binary patch literal 2893 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPShadowView/CPShadowViewLightLeft.png b/AppKit/Resources/CPShadowView/CPShadowViewLightLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..d0f29b7846b6aca4a35822c1e53b31ed3d5e9a23 GIT binary patch literal 2807 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 JPDHLkV1ksDGm-!R literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPShadowView/CPShadowViewLightRight.png b/AppKit/Resources/CPShadowView/CPShadowViewLightRight.png new file mode 100644 index 0000000000000000000000000000000000000000..1b3cf77573e814fdc1b066c9ea51988d6767f9cd GIT binary patch literal 2746 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPShadowView/CPShadowViewLightTopRight.png b/AppKit/Resources/CPShadowView/CPShadowViewLightTopRight.png new file mode 100644 index 0000000000000000000000000000000000000000..818d7f73d60f91876ca784993851541142cad0af GIT binary patch literal 2878 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 Z0|3kwHiB!Vn1KKQ002ovPDHLkV1iIMJ|qAD literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPTabView/_CPTabLabelBackgroundLeft.png b/AppKit/Resources/CPTabView/_CPTabLabelBackgroundLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..5a0edfc9ecb1b750820f11d685ab5d2d8b091a96 GIT binary patch literal 2931 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 X*HDxTyH}hp00000NkvXXu0mjf;j?QQ literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPTabView/_CPTabLabelSelectedCenter.png b/AppKit/Resources/CPTabView/_CPTabLabelSelectedCenter.png new file mode 100644 index 0000000000000000000000000000000000000000..9fe80236b6eb46c5fd3a38e0ec9dfba0efe4f2b8 GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{J!2~2lO_g5*DajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_d9MfRR9jv*DdY>qOrF&OeN9K8MPU~RITpi@gg;9pnS=hHTx zpCcS9d!Ryi;(z%wJmu<2Cwx|QZ56wF_TKE`bD{|h^H)h1PkZ~L8fX-Qr>mdKI;Vst E08LsnRR910 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPTabView/_CPTabLabelSelectedLeft.png b/AppKit/Resources/CPTabView/_CPTabLabelSelectedLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..3c0d4a17b111ff2e70859bc4e6b81c82fe6a44ba GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^%s?!}!3HGfElOzwQj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>JilRJS978H@E$KVR$zaIA@_ms&kc-!b4wKodj)bo|aa@6& z-KlQ7{&B{;$L|_GF9~J+dargZt03cS$zu{Lwl;mgm$6py&{7eBi`<4s9_7^?F1MQb hMP0#k$05N4hQ|>i%WUU;WCGg4;OXk;vd$@?2>@&MK`a0O literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPTabView/_CPTabLabelSelectedRight.png b/AppKit/Resources/CPTabView/_CPTabLabelSelectedRight.png new file mode 100644 index 0000000000000000000000000000000000000000..3388ca886b98c51591cccdc8e7501cb767fe59fd GIT binary patch literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^%s?!}!3HGfElOzwQj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>Jiefxn978H@C1vE~{Mldf^3s2Y0|$20{r&Yne0^N%gb5Q8 z5`@IW(hSVa(|44=mtz(dFeoT0GWzrDYjl6qtbI3L^u)E*?#pHEzkb gn1kEqGYcdz?0YTxz?>mC7ibTIr>mdKI;Vst0C?6vw*UYD literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPTabView/_CPTabLabelsViewCenter.png b/AppKit/Resources/CPTabView/_CPTabLabelsViewCenter.png new file mode 100644 index 0000000000000000000000000000000000000000..19d8e7463238f0a2485a9ba91721a0212a45dce8 GIT binary patch literal 2832 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 Q+yDRo07*qoM6N<$f((J4Jpcdz literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPTabView/_CPTabLabelsViewRight.png b/AppKit/Resources/CPTabView/_CPTabLabelsViewRight.png new file mode 100644 index 0000000000000000000000000000000000000000..b9973d4b091b6576581c4a718f0b769b7789296f GIT binary patch literal 3035 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPTextField/CPTextFieldBezelSquare0.png b/AppKit/Resources/CPTextField/CPTextFieldBezelSquare0.png new file mode 100644 index 0000000000000000000000000000000000000000..1819bb3a8ca5cf6d645c53909a60ddb4041a1e76 GIT binary patch literal 124 zcmeAS@N?(olHy`uVBq!ia0vp^OhC-c0V2&hJg)&M$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1Ga-J@ZAr-fhW*VpSsjI7Z_w@8^*kB+m;O*tb#3I3tDnm{r-UW|9fKft literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPTextField/CPTextFieldBezelSquare1.png b/AppKit/Resources/CPTextField/CPTextFieldBezelSquare1.png new file mode 100644 index 0000000000000000000000000000000000000000..2c77bb764b5fcec9d4a081d58cf3e9a5525280fa GIT binary patch literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^j6lrH!2~4l?*DWZNJ*BsMwA5SrGAr-fhB6pR%{QmxabP0l+XkKX!I#E literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPTextField/CPTextFieldBezelSquare3.png b/AppKit/Resources/CPTextField/CPTextFieldBezelSquare3.png new file mode 100644 index 0000000000000000000000000000000000000000..81cd274512cf61edd45262459f6fbfe946bc3fe9 GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^OhC-Y0V1m%Ufcyzk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5XggjjwLn>}1?J9bD>Uh6ABNGpUkUDEn`Td}1{rdmk-l2h!fsKusLA$eLEl`TV)78&qol`;+ E0DoN_YybcN literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPTextField/CPTextFieldBezelSquare5.png b/AppKit/Resources/CPTextField/CPTextFieldBezelSquare5.png new file mode 100644 index 0000000000000000000000000000000000000000..21f81000edf05b5246b09fb3139cea6868f01ad1 GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^OhC-Y0V1m%Ufcyzk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5XggjjwLn>}1{rU0n@#EwDj7&TX!u70m%T6`717#UJUHx3v IIVCg!05qi`djJ3c literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPTextField/CPTextFieldBezelSquare6.png b/AppKit/Resources/CPTextField/CPTextFieldBezelSquare6.png new file mode 100644 index 0000000000000000000000000000000000000000..acc67dfa27a9cb969d98d06c4c56ec24d42e80ab GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^Od!kwBL7~QRScvgOI#yLg7ec#$`gxH85~pclTsBt za}(23gHjVyDhp4h+5iDSr z1<%~X^wgl##FWaylc_d9MZ%sgjv*DdlK%YvZ~ypszdR!o4}=$H)6;+SUL2^Y?do0|PUI9~-ybVP4Kj PKvfK$u6{1-oD!M<#hfON literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPWindow/CPWindowShadow0.png b/AppKit/Resources/CPWindow/CPWindowShadow0.png new file mode 100644 index 0000000000000000000000000000000000000000..d47d315954dc158588f30cf370517e61cc70373a GIT binary patch literal 250 zcmeAS@N?(olHy`uVBq!ia0vp^B0wz6!3HEJ^yqE{Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>JispE_IEGZ*S~K}J*8v3{=iYDIYd;;9<&Zx2by8<@kZZAz zwd;G^xqm){UxJRR+gG^W$7$vWGMbtrM+M9+ZplY8|WHeiMcC*VTJ~#p0$>8bg=d#Wzp$P!qjA7~k literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPWindow/CPWindowShadow1.png b/AppKit/Resources/CPWindow/CPWindowShadow1.png new file mode 100644 index 0000000000000000000000000000000000000000..fc74aea29cfb403028deda76574d6405d18f1fab GIT binary patch literal 154 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{R!3HD)xziF!Hb*vcH7JNMI4BD?9XRM%kdeW`wD8~m=W%x~ z@lID#+W2SfDXm*uR> BG&cYM literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPWindow/CPWindowShadow2.png b/AppKit/Resources/CPWindow/CPWindowShadow2.png new file mode 100644 index 0000000000000000000000000000000000000000..9764d1bdddd6e4dfdced8f9028cb975462b52e4a GIT binary patch literal 319 zcmV-F0l@x=P)vJw!%;~VG`mZ%TLBg!PdOCWy#TUc=<)~lP>T^@ z5x^c$U{7$C3OmSiS{B$#Ekp-qIUMWc5)$lPfOQ7ca+hU2>ZwPLImbtU0RZl~yS=%< Re0~4`002ovPDHLkV1k)bf4=|# literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPWindow/CPWindowShadow3.png b/AppKit/Resources/CPWindow/CPWindowShadow3.png new file mode 100644 index 0000000000000000000000000000000000000000..4565f2bcb16855cf2078f2ccdc68423e539f31c5 GIT binary patch literal 126 zcmeAS@N?(olHy`uVBq!ia0vp^B0$W@!3HGnP3ltxQj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>JiWEFu978H@C8Z=JB&0MjxM`$09X^vWgO%4DSr z1<%~X^wgl##FWaylc_d9MT(v-jv*Ddl2Q^9F0enU5BMYA^?$*`{T@H$rT+0BW?*Dv YsQDb%7 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/CPWindow/CPWindowShadow6.png b/AppKit/Resources/CPWindow/CPWindowShadow6.png new file mode 100644 index 0000000000000000000000000000000000000000..5208801f11f180f2ec162e939140d5882b8191d8 GIT binary patch literal 263 zcmeAS@N?(olHy`uVBq!ia0vp^B0wy}!3HFwFZ>e#Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>JidK5MIEGZ*niCYwcUXaEv-G;N;@{JRV@($7>5HB8>TY^$ zA;9pFQ)?Z&OY!CR+Z@f-NSWRE81!JG@dC>foe937rd#Xg#wPWgd2nX+&#sRgo7vX+ zJ}OzY>fc6Z877whCq%+Trk=2I(pI`(c1W|Y-iPDvbCuTCCCO1-g$euIZOU6Yjx8}< zW%_Hb@p=gp1M!oO+_ZcDRjIw4+x1hO+e$mm@Ys&x_jmXF7E54oJ7-(CinFW|=x7E{ LS3j3^P6Tsdq$EpRBT9nv(@M${i&7aJQ}UBi z6+Ckj(^G>|6H_V+Po~-c6&ZNCIEGZ*N=isbFi2n$`tNuoKI9R<7NcM?n^2BIlc-CB m0kd>RLSjRqFbqYD;R}55!Ndn1 zOiWDt$^Eu#oy0De+LqDehEdqz0NX@FuNGCT?+Bc*z{yz uOx8+ak~}T6KuBhmmIp!Dp$S=i1Q-AV{ofzFQ9RH90000EaloF>&g}g}bm;s4Dh|d+_itQ! z;9*v@yUe-Z!Gr6U{Lij>x4}K`O5B~8Y~L&IS2sV%zj|Bg`JHRiCvmstp41Cmy^Cj( z($6V-PVfJIVK=w*y|qu=1g}q;s%Di?SYUm!`AOWTM~vo^vQN%^;Kcl*`8nAbaHBsM%<(3_HNEXkO*H{5iy;He))&^nG)f-Z!e( z+xsiooMPlqXb@>&VB%0qzrOQgdDXMxEvue0yjIEF)W;E~ zUZLDy$C&T&_+tKBiOQy@4}$zl7o6qJwcKHA^eN7Ag=^u@wmD@Bc%yS8U;dmVaUesu z<~!eKj)Du^Wn9nN*SpPMnAQ7r;mz}mvp&tvj?VQhg8sqovH9j%-#?&*nWh$opzWz%nfq|=QQr_m1vo-_M e0fVQjpUXO@geDt(U|c)e+2}iY`Z)$g+5rFso&KKy literal 0 HcmV?d00001 diff --git a/AppKit/Resources/HUDTheme/CPSliderHorizontalBarCenter.png b/AppKit/Resources/HUDTheme/CPSliderHorizontalBarCenter.png new file mode 100644 index 0000000000000000000000000000000000000000..8d2e5aac8cd4f17770fefcb501b327437047a55b GIT binary patch literal 107 zcmeAS@N?(olHy`uVBq!ia0vp^j6lr7!3HG#Z-iO_Db50q$YKTtZeb8+WSBKa0w^f! z>Eal|F*Etcm%snnm;L`Qv1q0Q2-wyB|If&f{gjJ0T5j46ph5;uS3j3^P6#crMw5Ggp(GSXFdpP}8s_fGns|rnZw`m=l@Z#L@R1p`W a<+hL7MY*2ZuR09W&*16m=d#Wzp$Pyn&?PSb literal 0 HcmV?d00001 diff --git a/AppKit/Resources/HUDTheme/CPSliderHorizontalBarRight.png b/AppKit/Resources/HUDTheme/CPSliderHorizontalBarRight.png new file mode 100644 index 0000000000000000000000000000000000000000..ff4f979686c859479deab1321e92aad2dd4f4895 GIT binary patch literal 129 zcmeAS@N?(olHy`uVBq!ia0vp^%s|Y-!3HF~bz9ki6lZ})WHAE+w=f7ZGR&GI0TeX$ zba4#fnCW|PqacHTh|9t9{oH$BI5bO5(B?IEd$y!(Yajdcyg<|K-7d$LJP_uRQj5I8 Y{zsjknfdg;aG-VuPgg&ebxsLQ0H>HCf&c&j literal 0 HcmV?d00001 diff --git a/AppKit/Resources/HUDTheme/CPSliderHorizontalKnob.png b/AppKit/Resources/HUDTheme/CPSliderHorizontalKnob.png new file mode 100644 index 0000000000000000000000000000000000000000..6752bc2084fd4c741cc5014a60cc488a116fd402 GIT binary patch literal 509 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 u0000JNklj2*mZyUb=0000?b literal 0 HcmV?d00001 diff --git a/AppKit/Resources/HUDTheme/WindowCenterLeft.png b/AppKit/Resources/HUDTheme/WindowCenterLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6b63fff48b7b84626261f2adf3a6dde37b9efb GIT binary patch literal 2822 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 Y0K+;3-q;Uh7ytkO07*qoM6N<$f-!0}iU0rr literal 0 HcmV?d00001 diff --git a/AppKit/Resources/HUDTheme/WindowCenterRight.png b/AppKit/Resources/HUDTheme/WindowCenterRight.png new file mode 100644 index 0000000000000000000000000000000000000000..750eb713189be7c80b018a604af92d1a46a4313a GIT binary patch literal 2823 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/HUDTheme/WindowCloseActive.png b/AppKit/Resources/HUDTheme/WindowCloseActive.png new file mode 100644 index 0000000000000000000000000000000000000000..94771fcbfb2918241b0ce768d78115a18f620852 GIT binary patch literal 3513 zcmV;q4My^bP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0008yNklz)S;h2;4K@`5qqnIK_QG4*pWBeU*FdkcSdn5BG$kTb)yhw#}0J zy>Gyp%`Y}<>9+SxV#%hRTAfo+q^|dXFzI2)6OyD|6~&pvoMFNJ-WPy$+dBkS-R~Xd z`xl7?U=HaFyql|>P8JC{r7f4$1yEvU!s6{ZS>07Y0_{rrl`?Um1YfB^_pb61&CQ-Y6sI6hx8dR{kUUfD$VuMb{Hqu)EoG)X{W z__PjOW>LKK5HQlY>d~g4mKZX)KJ-K~%}fW^hrrOLR;)LHbB~LBDLGet;uN=mC*Yp; z%70#4>tFRC#SfLbfTXDZIX-f7$|tS-2n!`jXJCECAt!SOLW8H>U+Tr zFwjGP2fLuCj+@deCnBfS?)vWLNHKoo;TFv=p4$A#F;k_$i&Bh^^yY0>nwkdcJsU(2 z4K3q+OjJ>vxvVazX0I4Ntt-}>j&U1YBy<$oOJ8BEWyo6YJ&%DKbP0YKtPw|hf?eBN zk~V-#q;ufJMS0Adc2^ot+mHlqn#0r&Gk=vSHSxzOa}ZYc!^VaTSY{wgkPUP4K-5pZ nt>!qH#=dfGx$*q}vHl$Z@;H!yU@wjm00000NkvXXu0mjfpKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0001-NklN=i81E=1^~k_Wct3(VrI~FT}D-R1Xaz15b6rt)^jwa b=h=4v^EsLqpFKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z00089Nkl_yU~%4POQu3Z?0n-Q79 zqL-%ULj@Zk0|=5OlYIO=&IIJw%>3>$?+_|N599aQ_#8(iqU=U^ri9{n{|ew2fDM2z z)>tSAJ^}a~IJ0KNfueR+9#oX_WUJRa$EIuSG9 z_!yN{vA6*6bGzL>^?jfA`~3g_AzbW;f)E0tg8KmA8Ndes-#42L9}b7BH6nWRb%fn1 z-+KUa0G|PTS}vD3pU*7TLI~GO6h`H9KSEvr2wm54N{RKKkx721U_S!*sI8R*#pl_G zAdax-B0LNOYAY%PQW(8_B%*7SOR#N)1r05?Y`{9DAdFTyrNlW!BHW>|Y3oCo2ja;u2tI}GRO%t5pj(SVoSUA)fMer z7r8AH(OpYUfqg0L3MyBsO0b)?T}xY&3`(e)1ehyHd9M0QM1NnNo)tYsV#&|tbBVWI z<*9cAlX+VLW*ehP1~MtdlBOYdW0dk-rQY0lvCt>aD%WtYO-C1p$*i)FoBa#`DWzg- zy1Obz2+azs4Z2pI*|wx@4EKng8tuD1wws1>*7Ux+YIzt2q?EEb_RcEK?M+-9)*7>u z*wd1Nn?1G9&49HC&}}(aD4yLA>$8U5IyPZTp5JvhG?|8S-(1nQCs-Hk(x_=#mgcDO z_@sbY_^nx0Y)2w$kJwV=tL2&7YfoxPdmMZhGVr8|ONTMn86#I&`nd_)lAnuub9?Pc o0c)*)BkVaE{fDq?G$iZK0JD>O4ku0-h5!Hn07*qoM6N<$f;X~s8UO$Q literal 0 HcmV?d00001 diff --git a/AppKit/Resources/HUDTheme/WindowTopRight.png b/AppKit/Resources/HUDTheme/WindowTopRight.png new file mode 100644 index 0000000000000000000000000000000000000000..dbb8e39b9cd72f9f9788faef5cf11a938fd98040 GIT binary patch literal 3454 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/_CPMenuItemView/_CPMenuItemViewMenuBarArrow.png b/AppKit/Resources/_CPMenuItemView/_CPMenuItemViewMenuBarArrow.png new file mode 100644 index 0000000000000000000000000000000000000000..27ac7e02e89f979b057111ba2df128e44c1226d4 GIT binary patch literal 2872 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 T@-ryK00000NkvXXu0mjf{nAl= literal 0 HcmV?d00001 diff --git a/AppKit/Resources/_CPMenuWindow/_CPMenuWindow1.png b/AppKit/Resources/_CPMenuWindow/_CPMenuWindow1.png new file mode 100644 index 0000000000000000000000000000000000000000..438f284c6fadf30ec0d1a58ab47390ea64163f6a GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^j6lr7!3HG#Z-iO_DajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_d9MN*zFjv*Ddl6w04|DXTy;9#@A503+b8Uqs#L%>zmt@)x` RmjG2Uc)I$ztaD0e0s#0gB8vb3 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/_CPMenuWindow/_CPMenuWindow3.png b/AppKit/Resources/_CPMenuWindow/_CPMenuWindow3.png new file mode 100644 index 0000000000000000000000000000000000000000..52efc8ff17fe51c7b19fd6f85c2385ca0dfe22a4 GIT binary patch literal 115 zcmeAS@N?(olHy`uVBq!ia0vp^EI`c2!3HFM+VGzRQj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>JibOqK978H@C3W=o|NsBsV6(pgk3a%LGAqyJDN{Fu0u?ZL My85}Sb4q9e0BwIEt^fc4 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/_CPMenuWindow/_CPMenuWindow4.png b/AppKit/Resources/_CPMenuWindow/_CPMenuWindow4.png new file mode 100644 index 0000000000000000000000000000000000000000..0b952a9942a4c43aaac980555ab4af6ce65deed3 GIT binary patch literal 110 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k8}bl$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1G0-i38Ar-fhYCb$TsNTT9%)oJnd5V~op*v8H!PC{xWt~$( F698h^9M}K= literal 0 HcmV?d00001 diff --git a/AppKit/Resources/_CPMenuWindow/_CPMenuWindow5.png b/AppKit/Resources/_CPMenuWindow/_CPMenuWindow5.png new file mode 100644 index 0000000000000000000000000000000000000000..a9a7257fffdb44d5166a4c1d11cec3d2f5691a1f GIT binary patch literal 116 zcmeAS@N?(olHy`uVBq!ia0vp^EI`c2!3HFM+VGzRQj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>Jio`r!978H@B~^ZSa8R91W5xRQ&sjMP7%ZAu6{l*ydk9p) N;OXk;vd$@?2>^Q=A#eZy literal 0 HcmV?d00001 diff --git a/AppKit/Resources/_CPMenuWindow/_CPMenuWindow7.png b/AppKit/Resources/_CPMenuWindow/_CPMenuWindow7.png new file mode 100644 index 0000000000000000000000000000000000000000..c577e8bbf46fa9ed2c4d2b619b7bb294e032261b GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^j6lr7!3HG#Z-iO_DajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_d9MN*zFjv*DdlIlJ@IH<11robS4=KcNs`OF*!4DR>XKA2u< RE&!@x@O1TaS?83{1OVzJBF_K- literal 0 HcmV?d00001 diff --git a/AppKit/Resources/_CPMenuWindow/_CPMenuWindowMoreAbove.png b/AppKit/Resources/_CPMenuWindow/_CPMenuWindowMoreAbove.png new file mode 100644 index 0000000000000000000000000000000000000000..1058cb9cfdfdd7a7d92c992acf8a99cb82762c84 GIT binary patch literal 243 zcmeAS@N?(olHy`uVBq!ia0vp^YCtT+!3HGFudNXUQj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>Jil%zHIEGZ*O8WEvzy09^79XBwkshm@8x}pSA-tTNoI94Z zEc_B((#gs#cHv%P#Q_%$Sz`soHs&YHg(g#KxjNK&+f1G@9NFvfCvL@!1}h)Aj_FK> z#!)&tt*3Z94&P|3U={FAoH)7Z)JFc6!w#Kynfh%!*7e`x(`I;7qI4zI@#-bj@Fp8$ o#;!~@3HNC6#e9nm88{3WraTY}{i^p!9q2#?Pgg&ebxsLQ01y~d9RL6T literal 0 HcmV?d00001 diff --git a/AppKit/Resources/_CPMenuWindow/_CPMenuWindowMoreBelow.png b/AppKit/Resources/_CPMenuWindow/_CPMenuWindowMoreBelow.png new file mode 100644 index 0000000000000000000000000000000000000000..bbaca547603856fec35cb61c127f89a31b8f30d2 GIT binary patch literal 239 zcmeAS@N?(olHy`uVBq!ia0vp^YCtT+!3HGFudNXUQj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>JiY9uxIEGZ*O8WEvzy09^79XBwkshm@D~X2>C313ds@y*8 zw9J*&Vby$(r>zb)jd6->n=+&XU!_fYtl_nI6Gw;tgNf`XpYpp%{pLI(=Xn ll}?b!{l+8S&d4Icu=2HxQPI?2oIuAhc)I$ztaD0e0ssV|RU-fZ literal 0 HcmV?d00001 diff --git a/AppKit/Resources/_CPMenuWindow/_CPMenuWindowRounded0.png b/AppKit/Resources/_CPMenuWindow/_CPMenuWindowRounded0.png new file mode 100644 index 0000000000000000000000000000000000000000..0892087aac7c2cb21c8ba9cde8e051292cda1931 GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0vp^EFjFm1|(O0oL2{=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrH1%IeEG`hE&{2`uYFAy|a^3lL<4kvzmaqfqlgXhrXFJe{O7U zZmujSFwo}qU_0?MGd=w~_ldLwrbj8s$&c^z1TY9BFsu_4sIFv+-~*b*;OXk;vd$@? F2>^MaGYS9z literal 0 HcmV?d00001 diff --git a/AppKit/Resources/_CPMenuWindow/_CPMenuWindowRounded2.png b/AppKit/Resources/_CPMenuWindow/_CPMenuWindowRounded2.png new file mode 100644 index 0000000000000000000000000000000000000000..dd79b1e22b1298743bb74828f7c6f51ea3f4550b GIT binary patch literal 165 zcmeAS@N?(olHy`uVBq!ia0vp^EFjFm1|(O0oL2{=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrH1%xqG@ehE&{2>g(^XPfAEoU^!xLo_FWR%#W9rde1*U*ZO$X ziwlb1_SgSEW&H8u$G_zT1wUAi*h@-C7|oPeaNx#`ALbLh*fmdKI;Vst04S(EX8-^I literal 0 HcmV?d00001 diff --git a/AppKit/Resources/_CPMenuWindow/_CPMenuWindowRounded6.png b/AppKit/Resources/_CPMenuWindow/_CPMenuWindowRounded6.png new file mode 100644 index 0000000000000000000000000000000000000000..e0846a642263a9036c5e017ffb9420557666e7f7 GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^EFjFm1|(O0oL2{=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrH1%xp}%chE&{2>geyUFa7%J>Un-Sn;$HPe0X?xiqFrpJ$;IS z^$Z&u+je=|s*poKprE1gqyOXo|NnV7IXSf)PWmYHF>x3$xI{@6AKUw_6lfxYr>mdK II;Vst0K6qP4FCWD literal 0 HcmV?d00001 diff --git a/AppKit/Resources/_CPMenuWindow/_CPMenuWindowRounded8.png b/AppKit/Resources/_CPMenuWindow/_CPMenuWindowRounded8.png new file mode 100644 index 0000000000000000000000000000000000000000..3cff81e1259025a8932ff0c40188910e6c77e086 GIT binary patch literal 162 zcmeAS@N?(olHy`uVBq!ia0vp^EFjFm1|(O0oL2{=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrH1%xp=xbhE&{2s`>EXpgNnvk6&N4lf%QWm#eX9Sd_n$(Vh@> z;M32~>BqdM>ur2@fB$@04THIcc6R?PCv4<7l9`jUhgl$jVPUi6``OL`hk)iWc)I$z JtaD0e0s!R7IfMWJ literal 0 HcmV?d00001 diff --git a/AppKit/Resources/_CPToolbarView/_CPToolbarViewBackground.png b/AppKit/Resources/_CPToolbarView/_CPToolbarViewBackground.png new file mode 100644 index 0000000000000000000000000000000000000000..ce3d59280abf03c41251424b2afbce8c36aeaf04 GIT binary patch literal 2870 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 U{kjw*zW@LL07*qoM6N<$f+Am5$N&HU literal 0 HcmV?d00001 diff --git a/AppKit/Resources/_CPToolbarView/_CPToolbarViewExtraItemsAlternateImage.png b/AppKit/Resources/_CPToolbarView/_CPToolbarViewExtraItemsAlternateImage.png new file mode 100644 index 0000000000000000000000000000000000000000..a73d1375492639d1227f88c7876719db1560ca16 GIT binary patch literal 3171 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 e@XN8M_&osT_`F7EaloF>&g}g-L1;Fyx1 zl&avFo0y&&l$w}QS$Hzl2B@gl)5S5Q;?|ohhFlE>JPsEX?)^Vy)e*h0(?sLby-Q|{ z?CtyAj|fix-E%T$%lS7}=U(NRz1|gGCi}kc=IqbQcVE5#`_}$Q%hxsO<*VOcjZC{< zm{xxHuNcFhwiV1BRt$^y8dfkXyn@qUAs`=%)RVbPJPc{O{^=xZtzHat7=x#)pUXO@ GgeCw-+FT+4 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/color_well.png b/AppKit/Resources/color_well.png new file mode 100644 index 0000000000000000000000000000000000000000..54444a6d6d2cfe403d69252395d0677b238319d2 GIT binary patch literal 225 zcmeAS@N?(olHy`uVBq!ia0vp^%0SG|!2~29UVZ2cq$EpRBT9nv(@M${i&7aJQ}UBi z6+Ckj(^G>|6H_V+Po~-c6*YUhIEGZ*dUM5^>!^Z&!$p@P{@P)?bhE!No7*kSBK==2 z@^EsHjnUaD?c9gwT)QRln9;_GV@?p4qJYzb8C$0rvYodSbV}yApmxr3UwHQ0hWYNR zwmKPCzn{M3`fM-F|ChhS9$D|(vvH2`Qjxxwd+jF$ow8)VyJV}~-tR$P8881mp3cC` ZptsEP%yp^y1fX*mJYD@<);T3K0RX|uS2q9v literal 0 HcmV?d00001 diff --git a/AppKit/Resources/kuler_button.png b/AppKit/Resources/kuler_button.png new file mode 100644 index 0000000000000000000000000000000000000000..bd766c45f348a9eeb8ffb6f94a0fbed2677967b0 GIT binary patch literal 4411 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 Bb{_x$ literal 0 HcmV?d00001 diff --git a/AppKit/Resources/kuler_button_h.png b/AppKit/Resources/kuler_button_h.png new file mode 100644 index 0000000000000000000000000000000000000000..84b2866ed5fcd4da128edb4fe5af5c1882b470e7 GIT binary patch literal 1777 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 Lu6{1-oD!M<8B%;) literal 0 HcmV?d00001 diff --git a/AppKit/Resources/slider_button_h.png b/AppKit/Resources/slider_button_h.png new file mode 100644 index 0000000000000000000000000000000000000000..3309cecda34bad6cbf0a3ceafb97bda21f644c39 GIT binary patch literal 319 zcmV-F0l@x=P)%X^xC596tOd=Vachf(>E^yHsRqSM`#7`C>pEA#s|RvRfb_sVE}6imZkJvO`W)z; zz@1w98KrA+?0B2kMrygJ=|3`W*QCzvG7h0|0+tVZNnV R9cusp002ovPDHLkV1g@VgeU+2 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/wheel.png b/AppKit/Resources/wheel.png new file mode 100644 index 0000000000000000000000000000000000000000..939a9ebad907d698f3b66bdd60af32776285c573 GIT binary patch literal 84870 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/wheel_black.png b/AppKit/Resources/wheel_black.png new file mode 100644 index 0000000000000000000000000000000000000000..822ec955c58d40184fa3b1150897fcf8c686ff6d GIT binary patch literal 10393 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 literal 0 HcmV?d00001 diff --git a/AppKit/Resources/wheel_button_h.png b/AppKit/Resources/wheel_button_h.png new file mode 100644 index 0000000000000000000000000000000000000000..a6fc1558441e744ecbafb1d825c660dd1f7e8829 GIT binary patch literal 1952 zcmV;R2VeM!P)L}wv0@4>sff3>S~E6jkd!uqN^P;Fl}3=hDC&cKP$Z!EP(e`?C5TTJ1v{mQO-WLl zQ0xVaq-kz6jUmY-nM>xJvoC9}z5M>Q);@D4ViV#+XXcxKU;pp>zxA)R_jZ(0?EU<4 zuIHl3bhC5ez`NtaD*jX^F5Tm)^cGL$D;t$cV&rH#tUct0=M$%Ke8?SrDG9TeqcT3W zZQ>v0d*!9#uPI=|o(&s4Q9PWAnQabl-_*jf0pD!gUL{Z_ne)kBEQ${9Ji@yXO?V#au=LOyw?1fR+XWF$th35haKz z3f549xkZPuu3%h@P5FHNlV5!Fr8CzQ@bwpdu>4i=#;z0U3XTR))5 zjRQ?hu59(vIv`k37Mh%OI~q!T;D8(4_VCtkK70Cq3V8a^Z-eJ9?*IKi+3~LoXmW=| zNE{$(h-k>o_$PW89P5DUv%f_31#?m&&lpQ{#4cllg6m z@#uKdL0mLE>-?>X?u)HB|(>e54(xC3%(HwH3-(nCN3LMwnO_V7Qz z|3EuZJ5ZYHOQaOsR4%A;EOdE=h$TTn{_LeO8JvG?>gg}Pg0rRft^I$D=ezASCl(ea zgLnW*xK0{qQl*8Eh=$%a!(p!R^iUYFrcYc6#vGOBSCdO4AO}Q)W$&EYnk3`5(x~%i z?)qwXT9u!kk6Wu-y2V;Z)L&DB3vuP?-LT~A*s9G)qUWr(sVukwB?yFRZ}EV z5VF)Y+bP%Q}E9JaLQ2v0z!muny-fN7mwB3!rX5Jq)r15B_MHSRgtZWu?J;P=`49qKr?eL%$01FbQa0_NhR(najsNGcy3R6o@r3GL?;x1 zaiSzQN+YJSg0v`Q_DKMGhBtz_o`6B&9G~v8+bUa~j&?TDzOcx#gPaUA1lKu$n; zKmzKir$tEXN@+!qn9@{}qkUH_JJ}O(ljH6^-j>_x*&!`iY02q1;wejR$AjDqJTvXd zM~~bnUB>IFM^TiEAUDd$h$u-+#M}?A-PaSaD&#LG?ap*pMPm^+mDj{{0TDZPJg6AX zZ69&F;*tQU4@qeTfqB%6*T)FITJpo0hI`*MfsssE080Y=d*t1I7Uo;WC$ILx!E~Dj_vGc$|N1^&Tbs!%H5=+jhS2$%9AJXWOZ} zY81>7k~Wk9Z3jSz`&&3Sh};RtTim{qRR&Gi5sC^8iAQgSNuQ+#DYjF*l*}$L8H%~+ zjuj7X-u>gf^f>0VfWLhA-a{M5{9l&~OtsOUIbI<%AjOMJcOH?Bwc#T22t?5#=L~3@ zj?uR4(BeZYVbHh!W4o)Pa&KL`i^yxqaJCy!k7wfyd{ zJ-_zkQTfY@XVqrE9(N*#0|_wT+VQsnVhCu~0(v4az8y@`qRaS**cYzjJ2oAB?5*qm zF!}g>2L?LRo$p;Zoj)qB@Uda6wxgKJ0}#-3jSJ0w2S^0S8z7G}1HVzu`eX7B&6xe@ z?l-qj-_WPo`1p&T4P^dAdbzvBOT&@GU38+J1zJF9W&t@6MB>WmNVt2*34S$kYGUvI z^=+s>({A4rRUPM+(YX3TcDeYRm#Po@q8e!`6~#tCo`ig6Fybc%N4&o$-C*~cp}`|} my>>_Enjfd{_viV41Q-CIPr;P&sOLBU0000 + +import "CPColor.j" +import "CPFont.j" +import "CPImage.j" +import "CPTextField.j" +import "CPView.j" + +#include "Platform/Platform.h" +#include "Platform/DOM/CPDOMDisplayServer.h" + + +@implementation _CPImageAndTitleView : CPView +{ + CPTextAlignment _alignment; + CPColor _textColor; + CPFont _font; + + CPCellImagePosition _imagePosition; + CPImageScaling _imageScalng; + + CPImage _image; + CPString _title; + + CGRect _titleSize; + +#if PLATFORM(DOM) + DOMElement _DOMImageElement; +#endif + CPTextField _titleField; +} + +- (id)initWithFrame:(CGRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _alignment = CPCenterTextAlignment; + _textColor = nil; + _font = [CPFont systemFontOfSize:12.0]; + + _imagePosition = CPNoImage; + _imageScaling = CPScaleNone; + + _titleSize = CGSizeMakeZero(); + } + + return self; +} + +- (void)setAlignment:(CPTextAlignment)anAlignment +{ + _alignment = anAlignment; + + [_titleField setAlignment:anAlignment]; +} + +- (CPTextAlignment)alignment +{ + return _alignment; +} + +- (void)setImagePosition:(CPCellImagePosition)anImagePosition +{ + if (_imagePosition == anImagePosition) + return; + + _imagePosition = anImagePosition; + + if (_imagePosition == CPImageOnly) + [_titleField setHidden:YES]; + else + [_titleField setHidden:NO]; + + [self tile]; +} + +- (CPCellImagePosition)imagePosition +{ + return _imagePosition; +} + +- (void)setImageScaling:(CPImageScaling)anImageScaling +{ + if (_imageScaling == anImageScaling) + return; + + _imageScaling = anImageScaling; + + [self tile]; +} + +- (void)imageScaling +{ + return _imageScaling; +} + +- (void)setTextAlignment:(CPTextAlignment)aTextAlignment +{ + if (_alignment == aTextAlignment) + return; + + _alignment = aTextAlignment; + [_titleField setTextAlignment:aTextAlignment]; +} + +- (CPTextAlignment)textAlignment +{ + return _alignment; +} + +- (void)setTextColor:(CPColor)aTextColor +{ + if (_textColor == aTextColor) + return; + + _textColor = aTextColor; + [_titleField setTextColor:aTextColor]; +} + +- (CPColor)textColor +{ + return _textColor; +} + +- (void)setFont:(CPFont)aFont +{ + if (_font == aFont) + return; + + _font = aFont; + [_titleField setFont:aFont]; + + [self updateTitleSize]; + + [self tile]; +} + +- (CPFont)font +{ + return _font; +} + +- (void)setImage:(CPImage)anImage +{ + if (_image == anImage) + return; + + var oldSize = [_image size], + newSize = [anImage size]; + + _image = anImage; + + if (anImage) + { +#if PLATFORM(DOM) + if (!_DOMImageElement) + { + _DOMImageElement = document.createElement("img"); + + _DOMImageElement.style.top = "0px"; + _DOMImageElement.style.left = "0px"; + _DOMImageElement.style.position = "absolute"; + _DOMImageElement.style.zIndex = 100; + + _DOMElement.appendChild(_DOMImageElement); + } + + _DOMImageElement.src = [_image filename]; +#endif + + if (oldSize && CGSizeEqualToSize(newSize, oldSize)) + return; + +#if PLATFORM(DOM) + _DOMImageElement.width = newSize.width; + _DOMImageElement.height = newSize.height; + _DOMImageElement.style.width = newSize.width + "px"; + _DOMImageElement.style.height = newSize.height + "px"; +#endif + } + else + { +#if PLATFORM(DOM) + _DOMElement.removeChild(_DOMImageElement); + + _DOMImageElement = NULL; +#endif + } + + [self tile]; +} + +- (CPImage)image +{ + return _image; +} + +- (void)setTitle:(CPString)aTitle +{ + if (_title == aTitle) + return; + + _title = aTitle; + + if ([_title length]) + { + if (!_titleField) + { + _titleField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()]; + + [_titleField setEditable:NO]; + + [_titleField setFont:_font]; + [_titleField setAlignment:_alignment]; + [_titleField setTextColor:_textColor]; + [_titleField setHidden:_imagePosition == CPImageOnly]; + + [self addSubview:_titleField]; + } + + [_titleField setStringValue:_title]; + + [self updateTitleSize]; + } + else + { + [_titleField removeFromSuperview]; + + _titleField = nil; + } + + [self tile]; +} + +- (CPString)title +{ + return _title; +} + +- (void)updateTitleSize +{ + if (!_titleField) + return; + + var size = _titleSize; + + [_titleField sizeToFit]; + + _titleSize = CGSizeMakeCopy([_titleField frame].size); + + [_titleField setFrameSize:size]; +} + +- (void)tile +{ + var size = [self bounds].size, + centerX = size.width / 2.0, + centerY = size.height / 2.0, + titleHeight = _titleField ? _titleSize.height : 0.0, + titleRect = CGRectMake(0.0, centerY - titleHeight / 2.0, size.width, titleHeight); + + if (_imagePosition != CPNoImage && _image) + { + var imageSize = [_image size], + imageWidth = imageSize.width, + imageHeight = imageSize.height; + + if (_imageScaling == CPScaleToFit) + { + imageWidth = size.width; + imageHeight = size.height; + } + else if (_imageScaling == CPScaleProportionally) + { + var scale = MIN(MIN(size.width, imageWidth) / imageWidth, MIN(size.height, imageHeight) / imageHeight); + + imageWidth *= scale; + imageHeight *= scale; + } + +#if PLATFORM(DOM) + _DOMImageElement.width = imageWidth; + _DOMImageElement.height = imageHeight; + _DOMImageElement.style.width = imageWidth + "px"; + _DOMImageElement.style.height = imageHeight + "px"; +#endif + + if (_imagePosition == CPImageBelow) + { +#if PLATFORM(DOM) + _DOMImageElement.style.left = FLOOR(centerX - imageWidth / 2.0) + "px"; + _DOMImageElement.style.top = FLOOR(size.height - imageHeight) + "px"; +#endif + + titleRect.origin.y = (size.height - imageHeight - titleHeight) / 2.0; + } + else if (_imagePosition == CPImageAbove) + { +#if PLATFORM(DOM) + CPDOMDisplayServerSetStyleLeftTop(_DOMImageElement, NULL, FLOOR(centerX - imageWidth / 2.0), 0); +#endif + + titleRect.origin.y = imageHeight + (size.height - imageHeight - titleHeight) / 2.0; + } + else if (_imagePosition == CPImageLeft) + { +#if PLATFORM(DOM) + _DOMImageElement.style.top = FLOOR(centerY - imageHeight / 2.0) + "px"; + _DOMImageElement.style.left = "0px"; +#endif + + titleRect.origin.x += imageWidth; + titleRect.size.width -= imageWidth; + } + else if (_imagePosition == CPImageRight) + { +#if PLATFORM(DOM) + _DOMImageElement.style.top = FLOOR(centerY - imageHeight / 2.0) + "px"; + _DOMImageElement.style.left = FLOOR(size.width - imageWidth) + "px"; +#endif + + titleRect.size.width -= imageWidth; + } + else if(_imagePosition == CPImageOnly) + { +#if PLATFORM(DOM) + _DOMImageElement.style.top = FLOOR(centerY - imageHeight / 2.0) + "px"; + _DOMImageElement.style.left = FLOOR(centerX - imageWidth / 2.0) + "px"; +#endif + } + } + + [_titleField setFrame:titleRect]; +} + +- (void)sizeToFit +{ + var size = CGSizeMakeZero(); + + if (_imagePosition != CPNoImage && _image) + { + var imageSize = [_image size]; + + size.width += imageSize.width; + size.height += imageSize.height; + } + + if (_imagePosition != CPImageOnly && [_title length]) + { + if (_imagePosition == CPImageLeft || _imagePosition == CPImageRight) + { + size.width += _titleSize.width; + size.height = MAX(size.height, _titleSize.height); + } + else if (_imagePosition == CPImageAbove || _imagePosition == CPImageBelow) + { + size.width = MAX(size.width, _titleSize.width); + size.height += _titleSize.height; + } + else // if (_imagePosition == CPImageOverlaps) + { + size.width = MAX(size.width, _titleSize.width); + size.height = MAX(size.height, _titleSize.height); + } + } + + [self setFrameSize:size]; +} + +- (void)resizeSubviewsWithOldSize:(CGSize)aSize +{ + [self tile]; +} + +@end diff --git a/AppKit/_CPWindowView.j b/AppKit/_CPWindowView.j new file mode 100644 index 000000000..b0f8c4883 --- /dev/null +++ b/AppKit/_CPWindowView.j @@ -0,0 +1,270 @@ +/* + * _CPWindowView.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPView.j" +import "CPImageView.j" + + +var _CPWindowViewResizeIndicatorImage = nil; + +@implementation _CPWindowView : CPView +{ + unsigned _styleMask; + + CPImageView _resizeIndicator; + + CPString _title; +} + ++ (void)initialize +{ + if (self != [_CPWindowView class]) + return; + + _CPWindowViewResizeIndicatorImage = [[CPImage alloc] initWithContentsOfFile:[[CPBundle bundleForClass:self] pathForResource:@"_CPWindowView/_CPWindowViewResizeIndicator.png"] size:CGSizeMake(12.0, 12.0)]; +} + +- (id)initWithFrame:(CPRect)aFrame forStyleMask:(unsigned)aStyleMask +{ + if (aStyleMask & CPHUDBackgroundWindowMask) + self = [_CPHUDWindowView alloc]; + + self._styleMask = aStyleMask; + + return [self initWithFrame:aFrame]; +} + +- (id)initWithFrame:(CGRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + _resizeIndicator = [[CPImageView alloc] initWithFrame:CGRectMakeZero()]; + + [_resizeIndicator setImage:_CPWindowViewResizeIndicatorImage]; + [_resizeIndicator setFrameSize:CGSizeMakeCopy([_CPWindowViewResizeIndicatorImage size])]; + + [self addSubview:_resizeIndicator]; + + [self setShowsResizeIndicator:_styleMask & CPResizableWindowMask]; + } + + return self; +} + +- (void)setTitle:(CPString)aTitle +{ +} + +- (CPString)title +{ + return nil; +} + +- (BOOL)acceptsFirstMouse:(CPEvent)anEvent +{ + return YES; +} + +- (void)mouseDown:(CPEvent)anEvent +{ + var theWindow = [self window]; + + if (![_resizeIndicator isHidden]) + { + // FIXME: This should be better + var frame = CGRectMakeCopy([self frame]); + + frame.origin.x = CGRectGetWidth(frame) - 20.0; + frame.origin.y = CGRectGetHeight(frame) - 24.0; + frame.size.width = 20.0 - 5.0, + frame.size.height = 24.0 - 8.0; + + if (CGRectContainsPoint(frame, [self convertPoint:[anEvent locationInWindow] fromView:nil])) + return [theWindow trackResizeWithEvent:anEvent]; + } + + if ([theWindow isMovableByWindowBackground]) + [theWindow trackMoveWithEvent:anEvent]; + + else + [super mouseDown:anEvent]; +} + +- (void)setShowsResizeIndicator:(BOOL)shouldShowResizeIndicator +{ + [_resizeIndicator setHidden:!shouldShowResizeIndicator]; +} + +- (CPImage)showsResizeIndicator +{ + return ![_resizeIndicator isHidden]; +} + +- (void)setTitle:(CPString)title +{ + _title = title; +} + +- (CPString)title +{ + return _title; +} + +- (void)windowDidChangeDocumentEdited +{ +} + +- (void)windowDidChangeDocumentSaving +{ +} + +@end + +var _CPHUDWindowViewTopImage = nil, + _CPHUDWindowViewTopLeftImage = nil, + _CPHUDWindowViewTopRightImage = nil, + + _CPHUDWindowViewLeftImage = nil, + _CPHUDWindowViewRightImage = nil, + _CPHUDWindowViewCenterImage = nil, + + _CPHUDWindowViewBottomImage = nil, + _CPHUDWindowViewBottomLeftImage = nil, + _CPHUDWindowViewBottomRightImage = nil, + + _CPHUDWindowViewBackgroundColor = nil, + + CPHUDCloseButtonImage = nil; + +@implementation _CPHUDWindowView : _CPWindowView +{ + CPTextField _titleField; + CPButton _closeButton; +} + ++ (void)initialize +{ + if (self != [_CPHUDWindowView class]) + return; + + var bundle = [CPBundle bundleForClass:self]; + + _CPHUDWindowViewBackgroundColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices: + [ + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowTopLeft.png"] size:CPSizeMake(15.0, 86.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowTopCenter.png"] size:CPSizeMake(1.0, 86.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowTopRight.png"] size:CPSizeMake(15.0, 86.0)], + + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowCenterLeft.png"] size:CPSizeMake(15.0, 1.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowCenter.png"] size:CPSizeMake(1.0, 1.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowCenterRight.png"] size:CPSizeMake(15.0, 1.0)], + + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowBottomLeft.png"] size:CPSizeMake(15.0, 39.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowBottomCenter.png"] size:CPSizeMake(1.0, 39.0)], + [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowBottomRight.png"] size:CPSizeMake(15.0, 39.0)] + ]]]; + + _CPHUDWindowViewCloseImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowClose.png"] size:CPSizeMake(20.0, 20.0)]; + _CPHUDWindowViewCloseActiveImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"HUDTheme/WindowCloseActive.png"] size:CPSizeMake(20.0, 20.0)]; +} + +- (CPView)hitTest:(CPPoint)aPoint +{ + var view = [super hitTest:aPoint]; + + if (view == _titleField) + return self; + + return view; +} + +- (id)initWithFrame:(CPRect)aFrame +{ + self = [super initWithFrame:aFrame]; + + if (self) + { + var bounds = [self bounds]; + + [self setBackgroundColor:_CPHUDWindowViewBackgroundColor]; + + _titleField = [[CPTextField alloc] initWithFrame:CPRectMakeZero()]; + + [_titleField setFont:[CPFont systemFontOfSize:11.0]]; + [_titleField setTextColor:[CPColor whiteColor]]; + [_titleField setTextShadow:[CPShadow shadowWithOffset:CPSizeMake(0.0, 1.0) blurRadius:2.0 color:[CPColor blackColor]]]; + [_titleField setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin]; + + [self addSubview:_titleField]; + + if (_styleMask & CPClosableWindowMask) + { + var closeSize = [_CPHUDWindowViewCloseImage size]; + + _closeButton = [[CPButton alloc] initWithFrame:CPRectMake(10.0, 7.0, closeSize.width, closeSize.height)]; + + [_closeButton setBordered:NO]; + + [_closeButton setImage:_CPHUDWindowViewCloseImage]; + [_closeButton setAlternateImage:_CPHUDWindowViewCloseActiveImage]; + + [_closeButton setTarget:self]; + [_closeButton setAction:@selector(close:)]; + + [self addSubview:_closeButton]; + } + + [_resizeIndicator setFrameOrigin:CGPointMake(CGRectGetWidth(bounds) - 20.0, CGRectGetHeight(bounds) - 24.0)]; + [_resizeIndicator setAutoresizingMask:CPViewMinXMargin | CPViewMinYMargin]; + } + + return self; +} + +- (void)close:(id)aSender +{ + [[self window] performClose:self]; +} + +- (void)setTitle:(CPString)aTitle +{ + [_titleField setStringValue:aTitle]; + [_titleField sizeToFit]; + + var size = [_titleField frame].size; + + [_titleField setFrameOrigin:CPPointMake((CPRectGetWidth([self frame]) - size.width) / 2.0, (26.0 - size.height) / 2.0)]; +} + +- (CPString)title +{ + return [_titleField stringValue]; +} + +- (void)setFrameSize:(CPSize)aSize +{ + [super setFrameSize:aSize]; +} + +@end diff --git a/AppKit/build.xml b/AppKit/build.xml new file mode 100644 index 000000000..86262c550 --- /dev/null +++ b/AppKit/build.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Foundation/CPArray.j b/Foundation/CPArray.j new file mode 100755 index 000000000..e787d52ce --- /dev/null +++ b/Foundation/CPArray.j @@ -0,0 +1,762 @@ +/* + * CPArray.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPObject.j" +import "CPRange.j" +import "CPEnumerator.j" +import "CPSortDescriptor.j" + +@implementation _CPArrayEnumerator : CPEnumerator +{ + CPArray _array; + int _index; +} + +- (id)initWithArray:(CPArray)anArray +{ + self = [super init]; + + if (self) + { + _array = anArray; + _index = -1; + } + + return self; +} + +- (id)nextObject +{ + if (++_index >= [_array count]) + return nil; + + return _array[_index]; +} + +@end + +@implementation _CPReverseArrayEnumerator : CPEnumerator +{ + CPArray _array; + int _index; +} + +- (id)initWithArray:(CPArray)anArray +{ + self = [super init]; + + if (self) + { + _array = anArray; + _index = [_array count]; + } + + return self; +} + +- (id)nextObject +{ + if (--_index < 0) + return nil; + + return _array[_index]; +} + +@end + +@implementation CPArray : CPObject + ++ (id)alloc +{ + return []; +} + ++ (id)array +{ + return [[self alloc] init]; +} + ++ (id)arrayWithArray:(CPArray)anArray +{ + return [[self alloc] initWithArray:anArray]; +} + ++ (id)arrayWithObject:(id)anObject +{ + return [[self alloc] initWithObjects:anObject]; +} + ++ (id)arrayWithObjects:(id)anObject, ... +{ + var i = 2, + array = [[self alloc] init], + argument; + + for(; i < arguments.length && (argument = arguments[i]) != nil; ++i) + array.push(argument); + + return array; +} + ++ (id)arrayWithObjects:(id)objects count:(unsigned)aCount +{ + return [[self alloc] initWithObjects:objects count:aCount]; +} + +- (id)init +{ + return self; +} + +// Creating an Array + +- (id)initWithArray:(CPArray)anArray +{ + self = [super init]; + + if (self) + [self setArray:anArray]; + + return self; +} + +- (id)initWithArray:(CPArray)anArray copyItems:(BOOL)copyItems +{ + if (!copyItems) + return [self initWithArray:anArray]; + + self = [super init]; + + if (self) + { + var index = 0, + count = [anArray count]; + + for(; index < count; ++i) + { + if (anArray[i].isa) + self[i] = [anArray copy]; + // Do a deep/shallow copy? + else + self[i] = anArray; + } + } + + return self; +} + +- (id)initWithObjects:(Array)anObject, ... +{ + // The arguments array contains self and _cmd, so the first object is at position 2. + var i = 2, + argument; + + for(; i < arguments.length && (argument = arguments[i]) != nil; ++i) + push(argument); + + return self; +} + +- (id)initWithObjects:(id)objects count:(unsigned)aCount +{ + self = [super init]; + + if (self) + { + var index = 0; + + for(; index < aCount; ++index) + push(objects[index]); + } + + return self; +} + +- (unsigned)hash +{ + if (self.__address == nil) + self.__address = _objj_generateObjectHash(); + + return self.__address; +} + +// Querying an array + +- (BOOL)containsObject:(id)anObject +{ + return [self indexOfObject:anObject] != CPNotFound; +} + +- (int)count +{ + return length; +} + +- (int)indexOfObject:(id)anObject +{ + if (anObject === nil) + return CPNotFound; + + var i = 0, + count = length; + + // Only use isEqual: if our object is a CPObject. + if (anObject.isa) + { + for(; i < count; ++i) + if([self[i] isEqual:anObject]) + return i; + } + // If indexOf exists, use it since it's probably + // faster than anything we can implement. + else if (self.indexOf) + return indexOf(anObject); + // Last resort, do a straight forward linear O(N) search. + else + for(; i < count; ++i) + if(self[i] == anObject) + return i; + + return CPNotFound; +} + +- (int)indexOfObject:(id)anObject inRange:(CPRange)aRange +{ + if (anObject === nil) + return CPNotFound; + + var i = aRange.location, + count = MIN(CPMaxRange(aRange), length); + + // Only use isEqual: if our object is a CPObject. + if (anObject.isa) + { + for(; i < count; ++i) + if([self[i] isEqual:anObject]) + return i; + } + // Last resort, do a straight forward linear O(N) search. + else + for(; i < count; ++i) + if(self[i] == anObject) + return i; + + return CPNotFound; +} + +- (int)indexOfObjectIdenticalTo:(id)anObject +{ + if (anObject === nil) + return CPNotFound; + + // If indexOf exists, use it since it's probably + // faster than anything we can implement. + if (self.indexOf) + return indexOf(anObject); + + // Last resort, do a straight forward linear O(N) search. + else + { + var index = 0, + count = length; + + for(; index < count; ++index) + if(self[index] == anObject) + return index; + } + + return CPNotFound; +} + +- (int)indexOfObjectIdenticalTo:(id)anObject inRange:(CPRange)aRange +{ + if (anObject === nil) + return CPNotFound; + + // If indexOf exists, use it since it's probably + // faster than anything we can implement. + if (self.indexOf) + { + var index = indexOf(anObject, aRange.location); + + if (CPLocationInRange(index, aRange)) + return index; + } + + // Last resort, do a straight forward linear O(N) search. + else + { + var index = aRange.location, + count = MIN(CPMaxRange(aRange), length); + + for(; index < count; ++index) + if(self[index] == anObject) + return index; + } + + return CPNotFound; +} + +- (id)lastObject +{ + var count = [self count]; + + if (!count) return nil; + + return self[count - 1]; +} + +- (id)objectAtIndex:(int)anIndex +{ + return self[anIndex]; +} + +- (CPArray)objectsAtIndexes:(CPIndexSet)indexes +{ + var index = [indexes firstIndex], + objects = []; + + while(index != CPNotFound) + { + [objects addObject:self[index]]; + index = [indexes indexGreaterThanIndex:index]; + } + + return objects; +} + +- (CPEnumerator)objectEnumerator +{ + return [[_CPArrayEnumerator alloc] initWithArray:self]; +} + +- (CPEnumerator)reverseObjectEnumerator +{ + return [[_CPReverseArrayEnumerator alloc] initWithArray:self]; +} + +// Sending messages to elements + +- (void)makeObjectsPerformSelector:(SEL)aSelector +{ + var index = 0, + count = length; + + for(; index < count; ++index) + objj_msgSend(self[index], aSelector); +} + +- (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(id)anObject +{ + var index = 0, + count = length; + + for(; index < count; ++index) + objj_msgSend(self[index], aSelector, anObject); +} + +// Comparing arrays + +- (id)firstObjectCommonWithArray:(CPArray)anArray +{ + if (![anArray count] || ![self count]) + return nil; + + var i = 0, + count = [self count]; + + for(; i < count; ++i) + if([anArray containsObject:self[i]]) + return self[i]; + + return nil; +} + +- (BOOL)isEqualToArray:(id)anArray +{ + if(length != anArray.length) + return NO; + + var index = 0, + count = [self count]; + + for(; index < count; ++index) + if(self[index] != anObject && (!self[index].isa || !anObject.isa || ![self[index] isEqual:anObject])) + return NO; + + return YES; +} + +// Deriving new arrays + +- (CPArray)arrayByAddingObject:(id)anObject +{ + var array = [self copy]; + + array.push(anObject); + + return array; +} + +- (CPArray)arrayByAddingObjectsFromArray:(CPArray)anArray +{ + return slice(0).concat(anArray); +} + +/* +- (CPArray)filteredArrayUsingPredicate:(CPPredicate)aPredicate +{ + var i= 0, + count = [self count], + array = [CPArray array]; + + for(; i= upper) + { + _cachedRangeIndex = i; + return YES; + } + + // The value isn't here, but values greater than anIndex should + // start from here regardless. + _cachedRangeIndex = i; + + return NO; +} + +- (BOOL)containsIndexes:(CPIndexSet)anIndexSet +{ + // Return YES if anIndexSet has no indexes + if(![anIndexSet count]) + return YES; + + // Return NO if we have no indexes. + if(!_count) + return NO; + + var i = 0, + count = _ranges.length; + + // This is fast thanks to the _cachedIndexRange. + for(; i < count; ++i) + if (![anIndexSet containsIndexesInRange:_ranges[i]]) + return NO; + + return YES; +} + +- (BOOL)intersectsIndexesInRange:(CPRange)aRange +{ + // This is fast thanks to the _cachedIndexRange. + if(!_count) + return NO; + + var i = SOERangeIndex(self, aRange.location), + count = _ranges.length, + upper = CPMaxRange(aRange); + + // Stop if the location is ever bigger than or equal to our + // non-inclusive upper bound + for (; i < count && _ranges[i].location < upper; ++i) + if(CPIntersectionRange(aRange, _ranges[i]).length) + return YES; + + return NO; +} + +- (int)count +{ + return _count; +} + +// Accessing Indexes + +- (int)firstIndex +{ + return _count ? _ranges[0].location : CPNotFound; +} + +- (int)lastIndex +{ + return _count ? CPMaxRange(_ranges[_ranges.length - 1]) - 1 : CPNotFound; +} + +- (unsigned)indexGreaterThanIndex:(unsigned)anIndex +{ + if(!_count) + return CPNotFound; + + var i = SOERangeIndex(self, anIndex++), + count = _ranges.length; + + for(; i < count && anIndex >= CPMaxRange(_ranges[i]); ++i) ; + + if (i == count) + return CPNotFound; + + _cachedRangeIndex = i; + + if (anIndex < _ranges[i].location) + return _ranges[i].location; + + return anIndex; +} + +- (unsigned)indexLessThanIndex:(unsigned)anIndex +{ + if (!_count) + return CPNotFound; + + var i = GOERangeIndex(self, anIndex--); + + for (; i >= 0 && anIndex < _ranges[i].location; --i) ; + + if(i < 0) + return CPNotFound; + + _cachedRangeIndex = i; + + if (CPLocationInRange(anIndex, _ranges[i])) + return anIndex; + + if (CPMaxRange(_ranges[i]) - 1 < anIndex) + return CPMaxRange(_ranges[i]) - 1; + + return CPNotFound; +} + +- (unsigned int)indexGreaterThanOrEqualToIndex:(unsigned)anIndex +{ + return [self indexGreaterThanIndex:anIndex - 1]; +} + +- (unsigned int)indexLessThanOrEqualToIndex:(unsigned)anIndex +{ + return [self indexLessThanIndex:anIndex + 1]; +} + +- (unsigned)getIndexes:(CPArray)anArray maxCount:(unsigned)aMaxCount inIndexRange:(CPRangePointer)aRangePointer +{ + if (!_count || aMacCount <= 0 || aRangePointer && !aRangePointer.length) + return 0; + + var i = SOERangeIndex(self, aRangePointer.location), + total = 0, + count = _ranges.length; + + for (; i < count; ++i) + { + // If aRangePointer is nil, all indexes are acceptable. + var intersection = aRangePointer ? CPIntersectionRange(_ranges[i], aRangePointer) : _ranges[i], + index = intersection.location, + maximum = CPMaxRange(intersection); + + for (; index < maximum; ++index) + { + anArray[total++] = index; + + if (total == aMaxCount) + { + // Update aRangePointer if it exists... + if (aRangePointer) + { + var upper = CPMaxRange(aRangePointer); + + // Don't use CPMakeRange since the values need to persist. + aRangePointer.location = index + 1; + aRangePointer.length = upper - index - 1; + } + + return aMaxCount; + } + } + } + + // Update aRangePointer if it exists... + if (aRangePointer) + { + aRangePointer.location = CPNotFound; + aRangePointer.length = 0; + } + + return total; +} + +- (CPString)description +{ + var desc = [super description] + " "; + + if (_count) + { + desc += "[number of indexes: " + _count + " (in " + _ranges.length + " ranges), indexes: ("; + for (i = 0; i < _ranges.length; i++) + { + desc += _ranges[i].location; + if (_ranges[i].length > 1) desc += "-" + (CPMaxRange(_ranges[i])-1) + ":"+_ranges[i].length+":"; + if (i+1 < _ranges.length) desc += " "; + } + desc += ")]"; + } + else + desc += "(no indexes)"; + return desc; +} + +@end + +@implementation CPIndexSet(CPMutableIndexSet) + +// Adding indexes. + +- (void)addIndex:(unsigned)anIndex +{ + [self addIndexesInRange:CPMakeRange(anIndex, 1)]; +} + +- (void)addIndexes:(CPIndexSet)anIndexSet +{ + var i = 0, + ranges = anIndexSet._ranges, + count = ranges.length; + + // Simply add each range within anIndexSet. + for(; i < count; ++i) + [self addIndexesInRange:ranges[i]]; +} + +- (void)addIndexesInRange:(CPRange)aRange +{ + if (_ranges.length == 0) + { + _count = aRange.length; + + return [_ranges addObject:CPCopyRange(aRange)]; + } + + // FIXME: Should we really use SOERangeIndex here? There is no real + // reason the cached index would be a better guess than 0, and it + // would avoid a function call. + var i = SOERangeIndex(self, aRange.location), + count = _ranges.length, + padded = CPMakeRange(aRange.location - 1, aRange.length + 2), + maximum = CPMaxRange(aRange); + + // If our range won't intersect with the last range, just append it to the end. + if (count && CPMaxRange(_ranges[count - 1]) < aRange.location) + [_ranges addObject:CPCopyRange(aRange)]; + else + for (; i < count; ++i) + { + // This range is completely independent of existing ranges, + // simply add it to the array. + if (maximum < _ranges[i].location) + { + _count += aRange.length; + + // Keep _cachedRangeIndex relevant. + if (i < _cachedRangeIndex) ++_cachedRangeIndex; + + return [_ranges insertObject:CPCopyRange(aRange) atIndex:i]; + } + + if (CPIntersectionRange(_ranges[i], padded).length) + { + var union = CPUnionRange(_ranges[i], aRange); + + // We already contain all the indexes in this range. + if (union.length == _ranges[i].length) + return; + + // Pad the length to collapse with later ranges. + ++union.length; + + // We only need to check if we now intersect with any following + // ranges since if we now intersected with the previous range, + // it would have already been handled. We start at i and not i + 1 + // to make sure we subtract i's length. + var j = i; + + for(; j < count; ++j) + // Bail as soon as we don't find an intersection. + if(CPIntersectionRange(union, _ranges[j]).length) + _count -= _ranges[j].length; + else + break; + + // Remove the padding now that we are done. + // NOTE: We could have set _ranges[i] = CPCopyRange(union), + // and then not had to bother decerementing here, but this avoids + // a lookup above during unioning, and a function call (CPCopyRange). + --union.length; + _ranges[i] = union; + + // Now remove indexes [i + 1, j - 1] + if (j - i - 1 > 0) + { + var remove = CPMakeRange(i + 1, j - i - 1); + + _ranges[i] = CPUnionRange(_ranges[i], _ranges[j - 1]); + [_ranges removeObjectsInRange:remove]; + + // Keep _cachedRangeIndex relevant. + if (_cachedRangeIndex >= CPMaxRange(remove)) _cachedRangedIndex -= remove.length; + else if (CPLocationInRange(_cachedRangeIndex, remove)) _cachedRangeIndex = i; + } + + // Update count. + _count += _ranges[i].length; + + return; + } + } + + _count += aRange.length; +} + +// Removing Indexes + +- (void)removeIndex:(unsigned int)anIndex +{ + [self removeIndexesInRange:CPMakeRange(anIndex, 1)]; +} + +- (void)removeIndexes:(CPIndexSet)anIndexSet +{ + var i = 0, + ranges = anIndexSet._ranges, + count = ranges.length; + + // Simply remove each index from anIndexSet + for(; i < count; ++i) + [self removeIndexesInRange:ranges[i]]; +} + +- (void)removeAllIndexes +{ + _ranges = []; + _count = 0; + _cachedRangeIndex = 0; +} + +- (void)removeIndexesInRange:(CPRange)aRange +{ + // FIXME: Should we really use SOERangeIndex here? There is no real + // reason the cached index would be a better guess than 0, and it + // would avoid a function call. + var i = SOERangeIndex(self, aRange.location), + count = _ranges.length, + maximum = CPMaxRange(aRange), + removal = CPMakeRange(CPNotFound, 0); + + for (; i < count; ++i) + { + var range = _ranges[i]; + + // Our range will not intersect with any coming ranges. + if (maximum < range.location) + break; + + var intersection = CPIntersectionRange(range, aRange); + + // If we don't have an intersection, then just continue iterating. + if (!intersection.length) + continue; + + // If the intersection consists of the entirety of this range, + // then remove it completely. + else if (intersection.length == range.length) + { + if (removal.location == CPNotFound) + removal = CPMakeRange(i, 1); + else + ++removal.length; + } + // If the intersection is contained entirely within this range, + // then split it into two and return. + else if (intersection.location > range.location && CPMaxRange(intersection) < CPMaxRange(range)) + { + var insert = CPMakeRange(CPMaxRange(intersection), CPMaxRange(range) - CPMaxRange(intersection)); + + range.length = intersection.location - range.location; + + _count -= intersection.length; + + return [_ranges insertObject:insert atIndex:i + 1]; + } + // Else if we at least have an intersection, then trim the existing range. + else + { + range.length -= intersection.length; + + if (intersection.location <= range.location) + range.location += intersection.length; + } + + _count -= intersection.length; + } + + if (removal.length) + [_ranges removeObjectsInRange:removal]; +} + +// Shifting Index Groups + +- (void)shiftIndexesStartingAtIndex:(unsigned)anIndex by:(int)aDelta +{ + if (!_count || aDelta == 0) + return; + + // Later indexes have a higher probability of being shifted + // than lower ones, so start at the end and work backwards. + var i = _ranges.length - 1, + shifted = CPMakeRange(CPNotFound, 0); + + for(; i >= 0; --i) + { + var range = _ranges[i], + maximum = CPMaxRange(range); + + if (anIndex > maximum) + break; + + // If our index is within our range, but not the first index, + // then this range will be split. + if (anIndex > range.location && anIndex < maximum) + { + // Split the range into shift and unshifted. + shifted = CPMakeRange(anIndex + aDelta, maximum - anIndex); + range.length = anIndex - range.location; + + // If our delta is positive, then we can simply add the range + // to the array. + if (aDelta > 0) + [_ranges insertObject:shifted atIndex:i + 1]; + // If it's negative, it needs to be added properly later. + else if (shifted.location < 0) + { + shifted.length = CPMaxRange(shifted); + shifted.location = 0; + } + + // We don't need to continue. + break; + } + + // Shift the range, and normalize it if the result is negative. + if ((range.location += aDelta) < 0) + { + range.length = CPMaxRange(range); + range.location = 0; + } + } + + // We need to add the shifted ranges if the delta is negative. + if (aDelta < 0) + { + var j = i + 1, + count = _ranges.length, + shifts = []; + + for (; j < count; ++j) + [shifts addObject:_ranges[j]]; + + if ((j = i + 1) < count) + { + [_ranges removeObjectsInRange:CPMakeRange(j, count - j)]; + + for (j = 0, count = shifts.length; j < count; ++j) + [self addIndexesInRange:shifts[j]]; + } + + if (shifted.location != CPNotFound) + [self addIndexesInRange:shifted]; + } +} + +@end + +var CPIndexSetCountKey = @"CPIndexSetCountKey", + CPIndexSetCachedRangeIndexKey = @"CPIndexSetCachedRangeIndexKey", + CPIndexSetRangeStringsKey = @"CPIndexSetRangeStringsKey"; + +@implementation CPIndexSet (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super init]; + + if (self) + { + _count = [aCoder decodeIntForKey:CPIndexSetCountKey]; + _cachedRangeIndex = [aCoder decodeIntForKey:CPIndexSetCachedRangeIndexKey]; + _ranges = []; + + var rangeStrings = [aCoder decodeObjectForKey:CPIndexSetRangeStringsKey], + index = 0, + count = rangeStrings.length; + + for (; index < count; ++index) + _ranges.push(CPRangeFromString(rangeStrings[index])); + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeInt:_count forKey:CPIndexSetCountKey]; + [aCoder encodeInt:_cachedRangeIndex forKey:CPIndexSetCachedRangeIndexKey]; + + var index = 0, + count = _ranges.length, + rangeStrings = []; + + for (; index < count; ++index) + rangeStrings[index] = CPStringFromRange(_ranges[index]); + + [aCoder encodeObject:rangeStrings forKey:CPIndexSetRangeStringsKey]; +} + +@end + +@implementation CPIndexSet (CPCopying) + +- (id)copy +{ + return [[[self class] alloc] initWithIndexSet:self]; +} + +- (id)mutableCopy +{ + return [[[self class] alloc] initWithIndexSet:self]; +} + +@end + +@implementation CPMutableIndexSet : CPIndexSet + +@end + +var SOERangeIndex = function(anIndexSet, anIndex) +{ + var ranges = anIndexSet._ranges, + cachedRangeIndex = 0;//anIndexSet._cachedRangeIndex; + + if(cachedRangeIndex < ranges.length && anIndex >= ranges[cachedRangeIndex].location) + return cachedRangeIndex; + + return 0; +} + +var GOERangeIndex = function(anIndexSet, anIndex) +{ + var ranges = anIndexSet._ranges, + cachedRangeIndex = anIndexSet._ranges.length;//anIndexSet._cachedRangeIndex; + + if(cachedRangeIndex < ranges.length && anIndex <= ranges[cachedRangeIndex].location) + return cachedRangeIndex; + + return ranges.length - 1; +} + +/* +new old method +X + (id)indexSet; +X + (id)indexSetWithIndex:(unsigned int)value; +X + (id)indexSetWithIndexesInRange:(NSRange)range; +X X - (id)init; +X X - (id)initWithIndex:(unsigned int)value; +X X - (id)initWithIndexesInRange:(NSRange)range; // designated initializer +X X - (id)initWithIndexSet:(NSIndexSet *)indexSet; // designated initializer +X - (BOOL)isEqualToIndexSet:(NSIndexSet *)indexSet; +X X - (unsigned int)count; +X X - (unsigned int)firstIndex; +X X - (unsigned int)lastIndex; +X X - (unsigned int)indexGreaterThanIndex:(unsigned int)value; +X X - (unsigned int)indexLessThanIndex:(unsigned int)value; +X X - (unsigned int)indexGreaterThanOrEqualToIndex:(unsigned int)value; +X X - (unsigned int)indexLessThanOrEqualToIndex:(unsigned int)value; +X - (unsigned int)getIndexes:(unsigned int *)indexBuffer maxCount:(unsigned int)bufferSize inIndexRange:(NSRangePointer)range; +X X - (BOOL)containsIndex:(unsigned int)value; +X X - (BOOL)containsIndexesInRange:(NSRange)range; +X X - (BOOL)containsIndexes:(NSIndexSet *)indexSet; +X X - (BOOL)intersectsIndexesInRange:(NSRange)range; +X X - (void)addIndexes:(NSIndexSet *)indexSet; +X - (void)removeIndexes:(NSIndexSet *)indexSet; +X X - (void)removeAllIndexes; +X - (void)addIndex:(unsigned int)value; +X - (void)removeIndex:(unsigned int)value; +X - (void)addIndexesInRange:(NSRange)range; +X - (void)removeIndexesInRange:(NSRange)range; + - (void)shiftIndexesStartingAtIndex:(unsigned int)index by:(int)delta; +*/ diff --git a/Foundation/CPInvocation.j b/Foundation/CPInvocation.j new file mode 100644 index 000000000..956688907 --- /dev/null +++ b/Foundation/CPInvocation.j @@ -0,0 +1,133 @@ +/* + * CPInvocation.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPObject.j" + +@implementation CPInvocation : CPObject +{ + id _returnValue; + CPMutableArray _arguments; + CPMethodSignature _methodSignature; +} + +// Creating CPInvocation Objects + ++ (id)invocationWithMethodSignature:(CPMethodSignature)aMethodSignature +{ + return [[self alloc] initWithMethodSignature:aMethodSignature]; +} + +- (id)initWithMethodSignature:(CPMethodSignature)aMethodSignature +{ + self = [super init]; + + if (self) + { + _arguments = []; + _methodSignature = aMethodSignature; + } + + return self; +} + +// Configuring an Invocation Object + +- (void)setSelector:(SEL)aSelector +{ + _arguments[1] = aSelector; +} + +- (SEL)selector +{ + return _arguments[1]; +} + +- (void)setTarget:(id)aTarget +{ + _arguments[0] = aTarget; +} + +- (id)target +{ + return _arguments[0]; +} + +- (void)setArgument:(id)anArgument atIndex:(unsigned)anIndex +{ + _arguments[anIndex] = anArgument; +} + +- (id)argumentAtIndex:(unsigned)anIndex +{ + return _arguments[anIndex]; +} + +- (void)setReturnValue:(id)aReturnValue +{ + _returnValue = aReturnValue; +} + +- (id)returnValue +{ + return _returnValue; +} + +// Dispatching an Invocation + +- (void)invoke +{ + _returnValue = objj_msgSend.apply(objj_msgSend, _arguments); +} + +- (void)invokeWithTarget:(id)aTarget +{ + _arguments[0] = aTarget; + _returnValue = objj_msgSend.apply(objj_msgSend, _arguments); +} + +@end + +var CPInvocationArguments = @"CPInvocationArguments", + CPInvocationReturnValue = @"CPInvocationReturnValue"; + +@implementation CPInvocation (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super init]; + + if (self) + { + _returnValue = [aCoder decodeObjectForKey:CPInvocationReturnValue]; + _arguments = [aCoder decodeObjectForKey:CPInvocationArguments]; + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeObject:_returnValue forKey:CPInvocationReturnValue]; + [aCoder encodeObject:_arguments forKey:CPInvocationArguments]; +} + +@end diff --git a/Foundation/CPJSONPConnection.j b/Foundation/CPJSONPConnection.j new file mode 100644 index 000000000..521b6661b --- /dev/null +++ b/Foundation/CPJSONPConnection.j @@ -0,0 +1,107 @@ +/* + * CPJSONPConnection.j + * Foundation + * + * Created by Ross Boucher. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import + +CPJSONPConnectionCallbacks = {}; + +@implementation CPJSONPConnection : CPObject +{ + CPURLRequest _request; + id _delegate; + + CPString _callbackParameter; + DOMElement _scriptTag; +} + ++ (CPData)sendRequest:(CPURLRequest)aRequest callback:(CPString)callbackParameter delegate:(id)aDelegate +{ + return [[[self class] alloc] initWithRequest:aRequest callback:callbackParameter delegate:aDelegate startImmediately:YES];; +} + +- (id)initWithRequest:(CPURLRequest)aRequest callback:(CPString)aString delegate:(id)aDelegate +{ + return [self initWithRequest:aRequest callback:aString delegate:aDelegate startImmediately: NO]; +} + +- (id)initWithRequest:(CPURLRequest)aRequest callback:(CPString)aString delegate:(id)aDelegate startImmediately:(BOOL)shouldStartImmediately +{ + self = [super init]; + + _request = aRequest; + _delegate = aDelegate; + + _callbackParameter = aString; + + CPJSONPConnectionCallbacks["callback"+[self hash]] = function(data) + { + [_delegate connection:self didReceiveData:data]; + [self removeScriptTag]; + }; + + if(shouldStartImmediately) + [self start]; + + return self; +} + +- (void)start +{ + try + { + var head = document.getElementsByTagName("head").item(0); + + var source = [_request URL]; + source += (source.indexOf('?') < 0) ? "?" : "&"; + source += _callbackParameter+"=CPJSONPConnectionCallbacks.callback"+[self hash]; + + _scriptTag = document.createElement("script"); + _scriptTag.setAttribute("type", "text/javascript"); + _scriptTag.setAttribute("charset", "utf-8"); + _scriptTag.setAttribute("src", source); + + head.appendChild(_scriptTag); + } + catch (exception) + { + [_delegate connection: self didFailWithError: exception]; + [self removeScriptTag]; + } +} + +- (void)removeScriptTag +{ + var head = document.getElementsByTagName("head").item(0); + + if(_scriptTag.parentNode == head) + head.removeChild(_scriptTag); + + CPJSONPConnectionCallbacks["callback"+[self hash]] = nil; + delete CPJSONPConnectionCallbacks["callback"+[self hash]]; +} + +- (void)cancel +{ + [self removeScriptTag]; +} + +@end \ No newline at end of file diff --git a/Foundation/CPKeyValueCoding.j b/Foundation/CPKeyValueCoding.j new file mode 100644 index 000000000..260179071 --- /dev/null +++ b/Foundation/CPKeyValueCoding.j @@ -0,0 +1,135 @@ +/* + * CPKeyValueCoding.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPObject.j" + +@implementation CPObject(CPKeyValueCoding) + ++ (BOOL)accessInstanceVariablesDirectly +{ + return YES; +} + ++ (SEL)_accessorForKey:(CPString)aKey +{ + var capitalizedKey = aKey.charAt(0).toUpperCase() + aKey.substr(1), + selector = CPSelectorFromString("get" + capitalizedKey); + + if ([self instancesRespondToSelector:selector] || + [self instancesRespondToSelector:selector = CPSelectorFromString(aKey)] || + [self instancesRespondToSelector:selector = CPSelectorFromString("is" + capitalizedKey)]) + return selector; + + return nil; +} + ++ (SEL)_modifierForKey:(CPString)aKey +{ + var selector = CPSelectorFromString("set" + aKey.charAt(0).toUpperCase() + aKey.substr(1) + ':'); + + if ([self instancesRespondToSelector:selector]) + return selector; + + return nil; +} + +- (CPString)_ivarForKey:(CPString)aKey +{ + var ivar, + isKey = "is" + aKey.charAt(0).toUpperCase() + aKey.substr(1); + + if (self[ivar = "_" + aKey] != undefined || self[ivar = "_" + isKey] != undefined || + self[ivar = aKey] != undefined || self[ivar = isKey] != undefined) ; + return ivar; + + return nil; +} + +- (id)valueForKey:(CPString)aKey +{ + var ivar, + theClass = [self class], + selector = [theClass _accessorForKey:aKey] + + if (selector) + return [self performSelector:selector]; + else if([theClass accessInstanceVariablesDirectly] && (ivar = [self _ivarForKey:aKey])) + return self[ivar]; + else + return [self valueForUndefinedKey:aKey]; +} + +- (id)valueForKeyPath:(CPString)aKeyPath +{ + var i = 0, + keys = aKeyPath.split("."), + count = keys.length, + value = self; + + for(; i valueForKey()]: this class is not key value coding-compliant for the key "+aKey+".]"); +} + +- (void)setValue:(id)aValue forKeyPath:(CPString)aKeyPath +{ + if (!aKeyPath) aKeyPath = "self"; + + var i = 0, + keys = aKeyPath.split("."), + count = keys.length - 1, + owner = self; + + for(; i < count; ++i) + owner = [owner valueForKey:keys[i]]; + + [owner setValue:aValue forKey:keys[i]]; +} + +- (void)setValue:(id)aValue forKey:(CPString)aKey +{ + var ivar, + theClass = [self class], + selector = [theClass _modifierForKey:aKey]; + + if (selector) + [self performSelector:selector withObject:aValue]; + else if([theClass accessInstanceVariablesDirectly] && (ivar = [self _ivarForKey:aKey])) + self[ivar] = aValue; + else + [self setValue:aValue forUndefinedKey:aKey]; +} + +- (void)setValue:(id)aValue forUndefinedKey:(CPString)aKey +{ + alert("IMPLEMENT EXCEPTIONS, also, setValueForKey died."); +// CPException.raise(CPUndefinedKeyException, "[<"+this.className()+" "+this+"> setValueForKey()]: this class is not key value coding-compliant for the key "+aKey+".]"); +} + +@end \ No newline at end of file diff --git a/Foundation/CPKeyedArchiver.j b/Foundation/CPKeyedArchiver.j new file mode 100644 index 000000000..02c71570c --- /dev/null +++ b/Foundation/CPKeyedArchiver.j @@ -0,0 +1,457 @@ +/* + * CPKeyedArchiver.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPData.j" +import "CPCoder.j" +import "CPArray.j" +import "CPString.j" +import "CPNumber.j" +import "CPDictionary.j" +import "CPValue.j" + +var CPArchiverReplacementClassNames = nil; + +var _CPKeyedArchiverDidEncodeObjectSelector = 1, + _CPKeyedArchiverWillEncodeObjectSelector = 2, + _CPKeyedArchiverWillReplaceObjectWithObjectSelector = 4, + _CPKeyedArchiverDidFinishSelector = 8, + _CPKeyedArchiverWillFinishSelector = 16; + +var _CPKeyedArchiverNullString = "$null", + _CPKeyedArchiverNullReference = nil, + + _CPKeyedArchiverUIDKey = "CP$UID", + + _CPKeyedArchiverTopKey = "$top", + _CPKeyedArchiverObjectsKey = "$objects", + _CPKeyedArchiverArchiverKey = "$archiver", + _CPKeyedArchiverVersionKey = "$version", + + _CPKeyedArchiverClassNameKey = "$classname", + _CPKeyedArchiverClassesKey = "$classes", + _CPKeyedArchiverClassKey = "$class"; + +var _CPKeyedArchiverStringClass = Nil, + _CPKeyedArchiverNumberClass = Nil; + +@implementation _CPKeyedArchiverValue : CPValue +{ +} +@end + +@implementation CPKeyedArchiver : CPCoder +{ + id _delegate; + unsigned _delegateSelectors; + + CPData _data; + + CPArray _objects; + + CPDictionary _UIDs; + CPDictionary _conditionalUIDs; + + CPDictionary _replacementObjects; + CPDictionary _replacementClassNames; + + id _plistObject; + CPMutableArray _plistObjects; + + CPPropertyListFormat _outputFormat; + +} + ++ (void)initialize +{ + if (self != [CPKeyedArchiver class]) + return; + + _CPKeyedArchiverStringClass = [CPString class]; + _CPKeyedArchiverNumberClass = [CPNumber class]; + + _CPKeyedArchiverNullReference = [CPDictionary dictionaryWithObject:0 forKey:_CPKeyedArchiverUIDKey]; +} + ++ (BOOL)allowsKeyedCoding +{ + return YES; +} + ++ (CPData)archivedDataWithRootObject:(id)anObject +{ + var data = [CPData dataWithPlistObject:nil], + archiver = [[self alloc] initForWritingWithMutableData:data]; + + [archiver encodeObject:anObject forKey:@"root"]; + [archiver finishEncoding]; + + return data; +} + +// Initializing an NSKeyedArchiver object + +- (id)initForWritingWithMutableData:(CPMutableData)data +{ + self = [super init]; + + if (self) + { + _data = data; + + _objects = []; + + _UIDs = [CPDictionary dictionary]; + _conditionalUIDs = [CPDictionary dictionary]; + + _replacementObjects = [CPDictionary dictionary]; + + _data = data; + + _plistObject = [CPDictionary dictionary]; + _plistObjects = [CPArray arrayWithObject:_CPKeyedArchiverNullString]; + } + + return self; +} + +// Archiving Data +- (void)finishEncoding +{ + if (_delegate && _delegateSelectors & _CPKeyedArchiverWillFinishSelector) + [_delegate archiverWillFinish:self]; + + var i = 0, + topObject = _plistObject, + classes = []; + + for (; i < _objects.length; ++i) + { + var object = _objects[i], + theClass = [object classForKeyedArchiver]; + + // Do whatever with the class, yo. + // We call willEncodeObject previously. + + _plistObject = _plistObjects[[_UIDs objectForKey:[object hash]]]; + [object encodeWithCoder:self]; + + if (_delegate && _delegateSelectors & _CPKeyedArchiverDidEncodeObjectSelector) + [_delegate archiver:self didEncodeObject:object]; + } + + _plistObject = [CPDictionary dictionary]; + + [_plistObject setObject:topObject forKey:_CPKeyedArchiverTopKey]; + [_plistObject setObject:_plistObjects forKey:_CPKeyedArchiverObjectsKey]; + [_plistObject setObject:[self className] forKey:_CPKeyedArchiverArchiverKey]; + [_plistObject setObject:@"100000" forKey:_CPKeyedArchiverVersionKey]; + + [_data setPlistObject:_plistObject]; + + if (_delegate && _delegateSelectors & _CPKeyedArchiverDidFinishSelector) + [_delegate archiverDidFinish:self]; +} + +- (void)outputFormat +{ + return _outputFormat; +} + +- (void)setOutputFormat:(CPPropertyListFormat)aPropertyListFormat +{ + _outputFormat = aPropertyListFormat; +} + +- (void)encodeBool:(BOOL)aBOOL forKey:(CPString)aKey +{ + [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, aBOOL, NO) forKey:aKey]; +} + +- (void)encodeDouble:(double)aDouble forKey:(CPString)aKey +{ + [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, aDouble, NO) forKey:aKey]; +} + +- (void)encodeFloat:(float)aFloat forKey:(CPString)aKey +{ + [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, aFloat, NO) forKey:aKey]; +} + +- (void)encodeInt:(float)anInt forKey:(CPString)aKey +{ + [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, anInt, NO) forKey:aKey]; +} + +// Managing Delegates + +- (void)setDelegate:(id)aDelegate +{ + _delegate = aDelegate; + + if ([_delegate respondsToSelector:@selector(archiver:didEncodeObject:)]) + _delegateSelectors |= _CPKeyedArchiverDidEncodeObjectSelector; + + if ([_delegate respondsToSelector:@selector(archiver:willEncodeObject:)]) + _delegateSelectors |= _CPKeyedArchiverWillEncodeObjectSelector; + + if ([_delegate respondsToSelector:@selector(archiver:willReplaceObject:withObject:)]) + _delegateSelectors |= _CPKeyedArchiverWillReplaceObjectWithObjectSelector; + + if ([_delegate respondsToSelector:@selector(archiver:didFinishEncoding:)]) + _delegateSelectors |= _CPKeyedArchiverDidFinishEncodingSelector; + + if ([_delegate respondsToSelector:@selector(archiver:willFinishEncoding:)]) + _delegateSelectors |= _CPKeyedArchiverWillFinishEncodingSelector; + +} + +- (id)delegate +{ + return _delegate; +} + +- (void)encodePoint:(CPPoint)aPoint forKey:(CPString)aKey +{ + [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, CPStringFromPoint(aPoint), NO) forKey:aKey]; +} + +- (void)encodeRect:(CPRect)aRect forKey:(CPString)aKey +{ + [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, CPStringFromRect(aRect), NO) forKey:aKey]; +} + +- (void)encodeSize:(CPSize)aSize forKey:(CPString)aKey +{ + [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, CPStringFromSize(aSize), NO) forKey:aKey]; +} + +- (void)encodeConditionalObject:(id)anObject forKey:(CPString)aKey +{ + [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, anObject, YES) forKey:aKey]; +} + +- (void)encodeNumber:(CPNumber)aNumber forKey:(CPString)aKey +{ + [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, aNuumber, NO) forKey:aKey]; +} + +- (void)encodeObject:(id)anObject forKey:(CPString)aKey +{ + [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, anObject, NO) forKey:aKey]; +} + +- (void)_encodeArrayOfObjects:(CPArray)objects forKey:(CPString)aKey +{ + var i = 0, + count = objects.length, + references = [CPArray arrayWithCapacity:count]; + + for (; i < count; ++i) + [references addObject:_CPKeyedArchiverEncodeObject(self, objects[i], NO)]; + + [_plistObject setObject:references forKey:aKey]; +} + +- (void)_encodeDictionaryOfObjects:(CPDictionary)aDictionary forKey:(CPString)aKey +{ + var key, + keys = [aDictionary keyEnumerator], + references = [CPDictionary dictionary]; + + while (key = [keys nextObject]) + [references setObject:_CPKeyedArchiverEncodeObject(self, [aDictionary objectForKey:key], NO) forKey:key]; + + [_plistObject setObject:references forKey:aKey]; +} + +// Managing classes and class names + ++ (void)setClassName:(CPString)aClassName forClass:(Class)aClass +{ + if (!CPArchiverReplacementClassNames) + CPArchiverReplacementClassNames = [CPDictionary dictionary]; + + [CPArchiverReplacementClassNames setObject:aClassName forKey:CPStringFromClass(aClass)]; +} + ++ (CPString)classNameForClass:(Class)aClass +{ + if (!CPArchiverReplacementClassNames) + return aClass.name; + + var className = [CPArchiverReplacementClassNames objectForKey:CPStringFromClass(aClassName)]; + + return className ? className : aClass.name; +} + +- (void)setClassName:(CPString)aClassName forClass:(Class)aClass +{ + if (!_replacementClassNames) + _replacementClassNames = [CPDictionary dictionary]; + + [_replacementClassNames setObject:aClassName forKey:CPStringFromClass(aClass)]; +} + +- (CPString)classNameForClass:(Class)aClass +{ + if (!_replacementClassNames) + return aClass.name; + + var className = [_replacementClassNames objectForKey:CPStringFromClass(aClassName)]; + + return className ? className : aClass.name; +} + +@end + +var _CPKeyedArchiverEncodeObject = function(self, anObject, isConditional) +{ + // We wrap primitive JavaScript objects in a unique subclass of CPValue. + // This way, when we unarchive, we know to unwrap it, since + // _CPKeyedArchiverValue should not be used anywhere else. + if (anObject != nil && !anObject.isa) + anObject = [_CPKeyedArchiverValue valueWithJSObject:anObject]; + + // Get the proper replacement object + var hash = [anObject hash], + object = [self._replacementObjects objectForKey:hash]; + + // If a replacement object doesn't exist, then actually ask for one. + // Explicitly compare to nil because object could be === 0. + if (object == nil) + { + object = [anObject replacementObjectForKeyedArchiver:self]; + + // Notify our delegate of this replacement. + if (self._delegate) + { + if (object != anObject && self._delegateSelectors & _CPKeyedArchiverWillReplaceObjectWithObjectSelector) + [self._delegate archiver:self willReplaceObject:anObject withObject:object]; + + if (self._delegateSelectors & _CPKeyedArchiverWillEncodeObjectSelector) + { + anObject = [self._delegate archiver:self willEncodeObject:object]; + + if (anObject != object && self._delegateSelectors & _CPKeyedArchiverWillReplaceObjectWithObjectSelector) + [self._delegate archiver:self willReplaceObject:object withObject:anObject]; + + object = anObject; + } + } + + [self._replacementObjects setObject:object forKey:hash]; + } + + // If we still don't have an object by this point, then return a + // reference to the null object. + // Explicitly compare to nil because object could be === 0. + if (object == nil) + return _CPKeyedArchiverNullReference; + + // If not, then grab the object's UID + var UID = [self._UIDs objectForKey:hash = [object hash]]; + + // If this object doesn't have a unique index in the object table yet, + // then it also hasn't been properly encoded. We explicitly compare + // index to nil since it could be 0, which would also evaluate to false. + if (UID == nil) + { + // If it is being conditionally encoded, then + if (isConditional) + { + // If we haven't already noted this conditional object... + if ((UID = [self._conditionalUIDs objectForKey:hash]) == nil) + { + // Use the null object as a placeholder. + [self._conditionalUIDs setObject:UID = [self._plistObjects count] forKey:hash]; + [self._plistObjects addObject:_CPKeyedArchiverNullString]; + } + } + else + { + var theClass = [anObject classForKeyedArchiver], + plistObject = nil, + shouldEncodeObject = NO; + + if (theClass == _CPKeyedArchiverStringClass || theClass == _CPKeyedArchiverNumberClass)// || theClass == _CPKeyedArchiverBooleanClass) + plistObject = object; + else + { + shouldEncodeObject = YES; + plistObject = [CPDictionary dictionary]; + } + + // If this object was previously encoded conditionally... + if ((UID = [self._conditionalUIDs objectForKey:hash]) == nil) + { + [self._UIDs setObject:UID = [self._plistObjects count] forKey:hash]; + [self._plistObjects addObject:plistObject]; + + // Only encode the object if it is not the same as the plist object. + if (shouldEncodeObject) + { + [self._objects addObject:object]; + + var className = [self classNameForClass:theClass]; + + if (!className) + className = [[self class] classNameForClass:theClass]; + + if (!className) + className = theClass.name; + else + theClass = window[className]; + + var classUID = [self._UIDs objectForKey:className]; + + if (!classUID) + { + var plistClass = [CPDictionary dictionary], + hierarchy = []; + + [plistClass setObject:className forKey:_CPKeyedArchiverClassNameKey]; + + do + { + [hierarchy addObject:CPStringFromClass(theClass)]; + } while (theClass = [theClass superclass]); + + [plistClass setObject:hierarchy forKey:_CPKeyedArchiverClassesKey]; + + classUID = [self._plistObjects count]; + [self._plistObjects addObject:plistClass]; + [self._UIDs setObject:classUID forKey:className]; + } + + [plistObject setObject:[CPDictionary dictionaryWithObject:classUID forKey:_CPKeyedArchiverUIDKey] forKey:_CPKeyedArchiverClassKey]; + } + } + else + { + [self._UIDs setObject:object forKey:UID]; + [self._plistObjects replaceObjectAtIndex:UID withObject:plistObject]; + } + } + } + + return [CPDictionary dictionaryWithObject:UID forKey:_CPKeyedArchiverUIDKey]; +} diff --git a/Foundation/CPKeyedUnarchiver.j b/Foundation/CPKeyedUnarchiver.j new file mode 100644 index 000000000..fb34849f6 --- /dev/null +++ b/Foundation/CPKeyedUnarchiver.j @@ -0,0 +1,353 @@ +/* + * CPKeyedUnarchiver.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPNull.j" +import "CPCoder.j" + + +var _CPKeyedUnarchiverCannotDecodeObjectOfClassNameOriginalClassSelector = 1, + _CPKeyedUnarchiverDidDecodeObjectSelector = 1 << 1, + _CPKeyedUnarchiverWillReplaceObjectWithObjectSelector = 1 << 2, + _CPKeyedUnarchiverWillFinishSelector = 1 << 3, + _CPKeyedUnarchiverDidFinishSelector = 1 << 4; + +var _CPKeyedArchiverNullString = "$null" + + _CPKeyedArchiverUIDKey = "CP$UID", + + _CPKeyedArchiverTopKey = "$top", + _CPKeyedArchiverObjectsKey = "$objects", + _CPKeyedArchiverArchiverKey = "$archiver", + _CPKeyedArchiverVersionKey = "$version", + + _CPKeyedArchiverClassNameKey = "$classname", + _CPKeyedArchiverClassesKey = "$classes", + _CPKeyedArchiverClassKey = "$class"; + +var _CPKeyedUnarchiverArrayClass = Nil, + _CPKeyedUnarchiverStringClass = Nil, + _CPKeyedUnarchiverDictionaryClass = Nil, + _CPKeyedUnarchiverArchiverValueClass = Nil; + +@implementation CPKeyedUnarchiver : CPCoder +{ + id _delegate; + unsigned _delegateSelectors; + + CPData _data; + + // FIXME: We need to support this! + CPDictionary _replacementClassNames; + + CPDictionary _objects; + CPDictionary _archive; + + CPDictionary _plistObject; + CPArray _plistObjects; +} + ++ (void)initialize +{ + if (self != [CPKeyedUnarchiver class]) + return; + + _CPKeyedUnarchiverArrayClass = [CPArray class]; + _CPKeyedUnarchiverStringClass = [CPString class]; + _CPKeyedUnarchiverDictionaryClass = [CPDictionary class]; + _CPKeyedUnarchiverArchiverValueClass = [_CPKeyedArchiverValue class]; +} + +- (id)initForReadingWithData:(CPData)data +{ + self = [super init]; + + if (self) + { + _archive = [data plistObject]; + _objects = [CPArray arrayWithObject:[CPNull null]]; + + _plistObject = [_archive objectForKey:_CPKeyedArchiverTopKey]; + _plistObjects = [_archive objectForKey:_CPKeyedArchiverObjectsKey]; + } + + return self; +} + ++ (id)unarchiveObjectWithData:(CPData)data +{ + var unarchiver = [[self alloc] initForReadingWithData:data], + object = [unarchiver decodeObjectForKey:@"root"]; + + [unarchiver finishDecoding]; + + return object; +} + ++ (id)unarchiveObjectWithFile:(CPString)aFilePath +{ +} + ++ (id)unarchiveObjectWithFile:(CPString)aFilePath asynchronously:(BOOL)aFlag +{ +} + +- (BOOL)containsValueForKey:(CPString)aKey +{ + return [_plistObject objectForKey:aKey] != nil; +} + +- (id)_decodeArrayOfObjectsForKey:(CPString)aKey +{ + var object = [_plistObject objectForKey:aKey]; + + if ([object isKindOfClass:_CPKeyedUnarchiverArrayClass]) + { + var index = 0, + count = object.length, + array = []; + + for (; index < count; ++index) + array[index] = _CPKeyedUnarchiverDecodeObjectAtIndex(self, [object[index] objectForKey:_CPKeyedArchiverUIDKey]); + + return array; + } + + return nil; +} + +- (void)_decodeDictionaryOfObjectsForKey:(CPString)aKey +{ + var object = [_plistObject objectForKey:aKey]; + + if ([object isKindOfClass:_CPKeyedUnarchiverDictionaryClass]) + { + var key, + keys = [object keyEnumerator], + dictionary = [CPDictionary dictionary]; + + while (key = [keys nextObject]) + [dictionary setObject:_CPKeyedUnarchiverDecodeObjectAtIndex(self, [[object objectForKey:key] objectForKey:_CPKeyedArchiverUIDKey]) forKey:key]; + + return dictionary; + } + + return nil; +} + +- (BOOL)decodeBoolForKey:(CPString)aKey +{ + return [self decodeObjectForKey:aKey]; +} + +- (float)decodeFloatForKey:(CPString)aKey +{ + return [self decodeObjectForKey:aKey]; +} + +- (double)decodeDoubleForKey:(CPString)aKey +{ + return [self decodeObjectForKey:aKey]; +} + +- (int)decodeIntForKey:(CPString)aKey +{ + return [self decodeObjectForKey:aKey]; +} + +- (CPPoint)decodePointForKey:(CPString)aKey +{ + var object = [self decodeObjectForKey:aKey]; + + if(object) + return CPPointFromString(object); + else + return CPPointMake(0.0, 0.0); +} + +- (CPRect)decodeRectForKey:(CPString)aKey +{ + var object = [self decodeObjectForKey:aKey]; + + if(object) + return CPRectFromString(object); + else + return CPRectMakeZero(); +} + +- (CPSize)decodeSizeForKey:(CPString)aKey +{ + var object = [self decodeObjectForKey:aKey]; + + if(object) + return CPSizeFromString(object); + else + return CPSizeMake(0.0, 0.0); +} + +- (id)decodeObjectForKey:(CPString)aKey +{ + var object = [_plistObject objectForKey:aKey]; + + if ([object isKindOfClass:_CPKeyedUnarchiverDictionaryClass]) + return _CPKeyedUnarchiverDecodeObjectAtIndex(self, [object objectForKey:_CPKeyedArchiverUIDKey]); + else if ([object isKindOfClass:[CPNumber class]]) + return object; +/* else + alert([object className] + " " + object + " " + aKey + " " + [_plistObject description]);*/ + + return nil; +} + +- (void)finishDecoding +{ + if (_delegateSelectors & _CPKeyedUnarchiverWillFinishSelector) + [_delegate unarchiverWillFinish:self]; + + if (_delegateSelectors & _CPKeyedUnarchiverDidFinishSelector) + [_delegate unarchiverDidFinish:self]; +} + +- (id)delegate +{ + return _delegate; +} + +- (void)setDelegate:(id)aDelegate +{ + _delegate = aDelegate; + + if ([_delegate respondsToSelector:@selector(unarchiver:CannotDecodeObjectOfClassName:originalClass:)]) + _delegateSelectors |= _CPKeyedUnarchiverCannotDecodeObjectOfClassNameOriginalClassSelector; + + if ([_delegate respondsToSelector:@selector(unarchiver:didDecodeObject:)]) + _delegateSelectors |= _CPKeyedUnarchiverDidDecodeObjectSelector; + + if ([_delegate respondsToSelector:@selector(unarchiver:willReplaceObject:withObject:)]) + _delegateSelectors |= _CPKeyedUnarchiverWillReplaceObjectWithObjectSelector; + + if ([_delegate respondsToSelector:@selector(unarchiverWillFinish:)]) + _delegateSelectors |= _CPKeyedUnarchiverWilFinishSelector; + + if ([_delegate respondsToSelector:@selector(unarchiverDidFinish:)]) + _delegateSelectors |= _CPKeyedUnarchiverDidFinishSelector; +} + +- (BOOL)allowsKeyedCoding +{ + return YES; +} + +@end + +var _CPKeyedUnarchiverDecodeObjectAtIndex = function(self, anIndex) +{ + var object = self._objects[anIndex]; + + if (object) + if (object == self._objects[0]) + return nil; + else + return object; + + var object, + plistObject = self._plistObjects[anIndex]; + + if ([plistObject isKindOfClass:_CPKeyedUnarchiverDictionaryClass]) + { + var plistClass = self._plistObjects[[[plistObject objectForKey:_CPKeyedArchiverClassKey] objectForKey:_CPKeyedArchiverUIDKey]], + className = [plistClass objectForKey:_CPKeyedArchiverClassNameKey], + classes = [plistClass objectForKey:_CPKeyedArchiverClassesKey], + theClass = CPClassFromString(className); + + object = [theClass alloc]; + + // It is important to do this before calling initWithCoder so that decoding can be self referential (something = self). + self._objects[anIndex] = object; + + var savedPlistObject = self._plistObject; + + self._plistObject = plistObject; + + var processedObject = [object initWithCoder:self]; + + self._plistObject = savedPlistObject; + + if (processedObject != object) + { + if (self._delegateSelectors & _CPKeyedUnarchiverWillReplaceObjectWithObjectSelector) + [self._delegate unarchiver:self willReplaceObject:object withObject:processedObject]; + + object = processedObject; + self._objects[anIndex] = processedObject; + } + + processedObject = [object awakeAfterUsingCoder:self]; + + if (processedObject == object) + { + if (self._delegateSelectors & _CPKeyedUnarchiverWillReplaceObjectWithObjectSelector) + [self._delegate unarchiver:self willReplaceObject:object withObject:processedObject]; + + object = processedObject; + self._objects[anIndex] = processedObject; + } + + if (self._delegate) + { + if (self._delegateSelectors & _CPKeyedUnarchiverDidDecodeObjectSelector) + processedObject = [self._delegate unarchiver:self didDecodeObject:object]; + + if (processedObject != object) + { + if (self._delegateSelectors & _CPKeyedUnarchiverWillReplaceObjectWithObjectSelector) + [self._delegate unarchiver:self willReplaceObject:object withObject:processedObject]; + + object = processedObject; + self._objects[anIndex] = processedObject; + } + } + } + else + { + self._objects[anIndex] = object = plistObject; + + if ([object class] == _CPKeyedUnarchiverStringClass) + { + if (object == _CPKeyedArchiverNullString) + { + self._objects[anIndex] = self._objects[0]; + + return nil; + } + else + self._objects[anIndex] = object = plistObject; + } + } + + // If this object is a member of _CPKeyedArchiverValue, then we know + // that it is a wrapper for a primitive JavaScript object. + if ([object isMemberOfClass:_CPKeyedUnarchiverArchiverValueClass]) + object = [object JSObject]; + + return object; +} + diff --git a/Foundation/CPLog.j b/Foundation/CPLog.j new file mode 100644 index 000000000..82d67a1d1 --- /dev/null +++ b/Foundation/CPLog.j @@ -0,0 +1,418 @@ +/* + * CPLog.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +window.CPLogDisable = false; + +var CPLogDefaultTitle = "Cappuccino"; + +var CPLogLevels = ["fatal", "error", "warn", "info", "debug", "trace"]; +var CPLogDefaultLevel = CPLogLevels[0]; + +var CPLogLevelsInverted = {}; +for (var i = 0; i < CPLogLevels.length; i++) + CPLogLevelsInverted[CPLogLevels[i]] = i; + +var _CPLogRegistrations = {}; + +// helpers: +var _randomInteger = function(max) { return Math.round(Math.random() * (typeof(max) != "undefined" ? max : (1 << 30))); } +var _randomArrayElement = function(element) { return element[_randomInteger(element.length)]; } + +var _CPFormatLogMessage = function(aString, aLevel, aTitle) +{ + var now = new Date(), + zero = function(number, zeros) + { + var digits = number.toString(); + return zeros.substring(0, zeros.length - digits.length) + digits; + } + + var level = aLevel ? " ["+aLevel+"]" : ""; + var message = + now.getFullYear() + "-" + zero(now.getMonth()+1, "00") + "-" + zero(now.getDate(), "00") + " " + + zero(now.getHours(), "00") + ":" + zero(now.getMinutes(), "00") + ":" + zero(now.getSeconds(), "00") + "." + + zero(now.getMilliseconds(), "000")+" " + aTitle + level + ": " + aString; + + return message; +} + +// Register Functions: + +// Register a logger for all levels, or up to an optional max level +function CPLogRegister(aProvider, aMaxLevel) +{ + CPLogRegisterRange(aProvider, CPLogLevels[0], aMaxLevel || CPLogLevels[CPLogLevels.length-1]); +} +// Register a logger for a range of levels +function CPLogRegisterRange(aProvider, aMinLevel, aMaxLevel) +{ + var min = CPLogLevelsInverted[aMinLevel]; + var max = CPLogLevelsInverted[aMaxLevel]; + + if (min != undefined && max != undefined) + for (var i = 0; i <= max; i++) + CPLogRegisterSingle(aProvider, CPLogLevels[i]); +} +// Regsiter a logger for +function CPLogRegisterSingle(aProvider, aLevel) +{ + if (_CPLogRegistrations[aLevel] == undefined) + _CPLogRegistrations[aLevel] = [aProvider]; + else + _CPLogRegistrations[aLevel].push(aProvider); +} + +// Main CPLog, which dispatches to individual loggers +function CPLog(aString, aLevel, aTitle) +{ + if (aTitle == undefined) + aTitle = CPLogDefaultTitle; + if (aLevel == undefined) + aLevel = CPLogDefaultLevel; + + if (_CPLogRegistrations[aLevel]) + for (var i = 0; i < _CPLogRegistrations[aLevel].length; i++) + _CPLogRegistrations[aLevel][i](aString, aLevel, aTitle); +} + +// Shortcuts for common log levels (CPLog.fatal(), CPLog.error(), etc) +for (var i = 0; i < CPLogLevels.length; i++) + CPLog[CPLogLevels[i]] = (function(level) { return function(message, title) { CPLog(message, level, title); }; })(CPLogLevels[i]); + +// Loggers: + +ANSI_ESC = String.fromCharCode(0x1B); +ANSI_CSI = ANSI_ESC + '['; +ANSI_TEXT_PROP = 'm'; +ANSI_RESET = '0'; +ANSI_BOLD = '1'; +ANSI_FAINT = '2'; // unsupported? +ANSI_NORMAL = '22'; +ANSI_ITALIC = '3'; // unsupported? +ANSI_UNDER = '4'; +ANSI_UNDER_DBL = '21'; // unsupported? +ANSI_UNDER_OFF = '24'; +ANSI_BLINK = '5'; +ANSI_BLINK_FAST = '6'; // unsupported? +ANSI_BLINK_OFF = '25'; +ANSI_REVERSE = '7'; +ANSI_POSITIVE = '27'; +ANSI_CONCEAL = '8'; +ANSI_REVEAL = '28'; +ANSI_FG = '3'; +ANSI_BG = '4'; +ANSI_FG_INTENSE = '9'; +ANSI_BG_INTENSE = '10'; +ANSI_BLACK = '0'; +ANSI_RED = '1'; +ANSI_GREEN = '2'; +ANSI_YELLOW = '3'; +ANSI_BLUE = '4'; +ANSI_MAGENTA = '5'; +ANSI_CYAN = '6'; +ANSI_WHITE = '7'; + +var colorCodeMap = { + "black" : ANSI_BLACK, + "red" : ANSI_RED, + "green" : ANSI_GREEN, + "yellow" : ANSI_YELLOW, + "blue" : ANSI_BLUE, + "magenta" : ANSI_MAGENTA, + "cyan" : ANSI_CYAN, + "white" : ANSI_WHITE +} + +ANSIControlCode = function(code, parameters) +{ + if (parameters == undefined) + parameters = ""; + else if (typeof(parameters) == 'object' && (parameters instanceof Array)) + parameters = parameters.join(';'); + return ANSI_CSI + String(parameters) + String(code); +} + +// simple text helpers: + +ANSITextApplyProperties = function(string, properties) +{ + return ANSIControlCode(ANSI_TEXT_PROP, properties) + String(string) + ANSIControlCode(ANSI_TEXT_PROP); +} + +ANSITextColorize = function(string, color) +{ + if (colorCodeMap[color] == undefined) + return string; + return ANSITextApplyProperties(string, ANSI_FG + colorCodeMap[color]); +} + +// CPLogPrint uses the print() functions present in many non-browser command line JavaScript interpreters +var levelColorMap = { + "fatal": "red", + "error": "red", + "warn" : "yellow", + "info" : "green", + "debug": "cyan", + "trace": "blue" +} + +function CPLogPrint(aString, aLevel, aTitle) +{ + if (typeof print != "undefined") + { + if (aLevel == "fatal" || aLevel == "error" || aLevel == "warn") + var message = ANSITextColorize(_CPFormatLogMessage(aString, aLevel, aTitle), levelColorMap[aLevel]); + else + var message = _CPFormatLogMessage(aString, ANSITextColorize(aLevel, levelColorMap[aLevel]), aTitle); + print(message); + } +} + +// CPLogAlert uses basic browser alert() functions +function CPLogAlert(aString, aLevel, aTitle) +{ + if (typeof alert != "undefined" && !window.CPLogDisable) + { + var message = _CPFormatLogMessage(aString, aLevel, aTitle); + window.CPLogDisable = !confirm(message + "\n\n(Click cancel to stop log alerts)"); + } +} + +// CPLogConsole uses the built in "console" object +function CPLogConsole(aString, aLevel, aTitle) +{ + if (typeof console != "undefined") + { + var message = _CPFormatLogMessage(aString, aLevel, aTitle); + + var logger = { + "fatal": "error", + "error": "error", + "warn": "warn", + "info": "info", + "debug": "debug", + "trace": "debug" + }[aLevel]; + + if (logger && console[logger]) + console[logger](message); + else if (console.log) + console.log(message); + } +} + +// CPLogPopup uses a slick popup window in the browser: +var CPLogWindow = null; +CPLogPopup = function(aString, aLevel, aTitle) +{ + try { + if (window.CPLogDisable || window.open == undefined) + return; + + if (!CPLogWindow || !CPLogWindow.document) + { + CPLogWindow = window.open("", "_blank", "width=600,height=400,status=no,resizable=yes,scrollbars=yes"); + + if (!CPLogWindow) { + window.CPLogDisable = !confirm(aString + "\n\n(Disable pop-up blocking for CPLog window; Click cancel to stop log alerts)"); + return; + } + + _CPLogInitPopup(CPLogWindow); + } + + var logDiv = CPLogWindow.document.createElement("div"); + logDiv.setAttribute("class", aLevel || "fatal"); + + var message = _CPFormatLogMessage(aString, null, aTitle); + + logDiv.appendChild(CPLogWindow.document.createTextNode(message)); + CPLogWindow.log.appendChild(logDiv); + + if (CPLogWindow.focusEnabled.checked) + CPLogWindow.focus(); + if (CPLogWindow.blockEnabled.checked) + CPLogWindow.blockEnabled.checked = CPLogWindow.confirm(message+"\nContinue blocking?"); + if (CPLogWindow.scrollEnabled.checked) + CPLogWindow.scrollToBottom(); + } catch(e) { + // TODO: some error handling/reporting + } +} + +var _CPLogInitPopup = function(logWindow) +{ + var doc = logWindow.document; + + // HACK so that head is available below: + doc.writeln(""); + + doc.title = CPLogDefaultTitle + " Run Log"; + + var head = doc.getElementsByTagName("head")[0]; + var body = doc.getElementsByTagName("body")[0]; + + var base = window.location.protocol + "//" + window.location.host + window.location.pathname; + base = base.substring(0,base.lastIndexOf("/")+1); + + var link = doc.createElement("link"); + link.setAttribute("type", "text/css"); + link.setAttribute("rel", "stylesheet"); + link.setAttribute("href", base+"Frameworks/Foundation/Resources/log.css"); + link.setAttribute("media", "screen"); + head.appendChild(link); + + var div = doc.createElement("div"); + div.setAttribute("id", "header"); + body.appendChild(div); + + // Enablers + var ul = doc.createElement("ul"); + ul.setAttribute("id", "enablers"); + div.appendChild(ul); + + for (var i = 0; i < CPLogLevels.length; i++) { + var li = doc.createElement("li"); + li.setAttribute("id", "en"+CPLogLevels[i]); + li.setAttribute("class", CPLogLevels[i]); + li.setAttribute("onclick", "toggle(this);"); + li.setAttribute("enabled", "yes"); + li.appendChild(doc.createTextNode(CPLogLevels[i])); + ul.appendChild(li); + } + + // Options + var ul = doc.createElement("ul"); + ul.setAttribute("id", "options"); + div.appendChild(ul); + + var options = {"focus":["Focus",false], "block":["Block",false], "wrap":["Wrap",false], "scroll":["Scroll",true], "close":["Close",true]}; + for (o in options) { + var li = doc.createElement("li"); + ul.appendChild(li); + + logWindow[o+"Enabled"] = doc.createElement("input"); + logWindow[o+"Enabled"].setAttribute("id", o); + logWindow[o+"Enabled"].setAttribute("type", "checkbox"); + if (options[o][1]) + logWindow[o+"Enabled"].setAttribute("checked", "checked"); + li.appendChild(logWindow[o+"Enabled"]); + + var label = doc.createElement("label"); + label.setAttribute("for", o); + label.appendChild(doc.createTextNode(options[o][0])); + li.appendChild(label); + } + + // Log + logWindow.log = doc.createElement("div"); + logWindow.log.setAttribute("class", "enerror endebug enwarn eninfo enfatal entrace"); + body.appendChild(logWindow.log); + + logWindow.toggle = function(elem) { + var enabled = (elem.getAttribute("enabled") == "yes") ? "no" : "yes"; + elem.setAttribute("enabled", enabled); + + if (enabled == "yes") + logWindow.log.className += " " + elem.id + else + logWindow.log.className = logWindow.log.className.replace(new RegExp("[\\s]*"+elem.id, "g"), ""); + } + + // Scroll + logWindow.scrollToBottom = function() { + logWindow.scrollTo(0, body.offsetHeight); + } + + // Wrap + logWindow.wrapEnabled.addEventListener("click", function() { + logWindow.log.setAttribute("wrap", logWindow.wrapEnabled.checked ? "yes" : "no"); + }, false); + + // Clear + logWindow.addEventListener("keydown", function(e) { + var e = e || logWindow.event; + if (e.keyCode == 75 && (e.ctrlKey || e.metaKey)) { + while (logWindow.log.firstChild) { + logWindow.log.removeChild(logWindow.log.firstChild); + } + e.preventDefault(); + } + }, "false"); + + // Parent closing + window.addEventListener("unload", function() { + if (logWindow && logWindow.closeEnabled && logWindow.closeEnabled.checked) { + window.CPLogDisable = true; + logWindow.close(); + } + }, false); + + // Log popup closing + logWindow.addEventListener("unload", function() { + if (!window.CPLogDisable) { + window.CPLogDisable = !confirm("Click cancel to stop logging"); + } + }, false); +} + +// CPLogServer sends log messages to the server +//var _CPLogServerBatch = true; +//var _CPLogServerSessionID = _randomInteger(); +//function CPLogServer(aString, aLevel, aTitle) +//{ +// var entry = { title: aTitle, message: aString, level: aLevel, timestamp: new Date().getTime() } +// +// if (_CPLogServerBatch) +// { +// } +// else +// { +// +// } +//} +// +//function _CPLogServerSubmit() +//{ +// +//} + +// Testing purposes: + +var lorem = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas fermentum, elit non lobortis cursus, orci velit suscipit est, id mollis turpis mi eget orci. Ut aliquam sollicitudin metus. Mauris at sapien sed sapien congue iaculis. Nulla lorem urna, bibendum id, laoreet iaculis, nonummy eget, massa. Phasellus ullamcorper commodo velit."; + +function CPLogTest(n) { + for(var i=0;i O(N^2)), so to avoid it, + // we keep track of whether observers are added or removed, and only do our + // rigorous testing in those cases. + var object = [aNotification object]; + + if (object != nil && (_postingObservers = [_objectObservers objectForKey:[object hash]])) + { + var observers = _postingObservers, + count = observers.length; + + _observerRemoval = NO; + while (count--) + { + var observer = _postingObservers[count]; + + // if there wasn't removal of an observer during this posting, or there + // was but we are still in the observer list... + if (!_observerRemoval || [observers indexOfObjectIdenticalTo:observer] != CPNotFound) + [observer postNotification:aNotification]; + + } + } + + // Now do the same for the nil object observers... + _postingObservers = [_objectObservers objectForKey:[[CPNull null] hash]]; + + if (!_postingObservers) + return; + + var observers = _postingObservers, + count = observers.length; + + _observerRemoval = NO; + while (count--) + { + var observer = _postingObservers[count]; + + // if there wasn't removal of an observer during this posting, or there + // was but we are still in the observer list... + if (!_observerRemoval || [observers indexOfObjectIdenticalTo:observer] != CPNotFound) + [observer postNotification:aNotification]; + } + + _postingObservers = nil; +} + +- (unsigned)count +{ + return [_objectObservers count]; +} + +@end + +@implementation _CPNotificationObserver : CPObject +{ + id _observer; + SEL _selector; +} + +- (id)initWithObserver:(id)anObserver selector:(SEL)aSelector +{ + if (self) + { + _observer = anObserver; + _selector = aSelector; + } + + return self; +} + +- (id)observer +{ + return _observer; +} + +-(void)postNotification:(CPNotification)aNotification +{ + [_observer performSelector:_selector withObject:aNotification]; +} + +@end diff --git a/Foundation/CPNull.j b/Foundation/CPNull.j new file mode 100644 index 000000000..7d267a1f9 --- /dev/null +++ b/Foundation/CPNull.j @@ -0,0 +1,47 @@ +/* + * CPNull.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPObject.j" + +var CPNullSharedNull = nil; + +@implementation CPNull : CPObject +{ +} + +/*+ (id)alloc +{ + if (CPNullSharedNull) + return CPNullSharedNull; + + return [super alloc]; +}*/ + ++ (CPNull)null +{ + if (!CPNullSharedNull) + CPNullSharedNull = [[CPNull alloc] init]; + + return CPNullSharedNull; +} + +@end \ No newline at end of file diff --git a/Foundation/CPNumber.j b/Foundation/CPNumber.j new file mode 100644 index 000000000..99ead4aaa --- /dev/null +++ b/Foundation/CPNumber.j @@ -0,0 +1,318 @@ +/* + * CPNumber.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPObject.j" +import "CPObjJRuntime.j" + +var __placeholder = new Number(), + _CPNumberHashes = { }; + +@implementation CPNumber : CPObject + ++ (id)alloc +{ + return __placeholder; +} + ++ (id)numberWithBool:(BOOL)aBoolean +{ + return aBoolean; +} + ++ (id)numberWithChar:(char)aChar +{ + if (aChar.charCodeAt) + return aChar.charCodeAt(0); + + return aChar; +} + ++ (id)numberWithDouble:(double)aDouble +{ + return aDouble; +} + ++ (id)numberWithFloat:(float)aFloat +{ + return aFloat; +} + ++ (id)numberWithInt:(int)anInt +{ + return anInt; +} + ++ (id)numberWithLong:(long)aLong +{ + return aLong; +} + ++ (id)numberWithLongLong:(long long)aLongLong +{ + return aLongLong; +} + ++ (id)numberWithShort:(short)aShort +{ + return aShort; +} + ++ (id)numberWithUnsignedChar:(unsigned char)aChar +{ + if (aChar.charCodeAt) + return aChar.charCodeAt(0); + + return aChar; +} + ++ (id)numberWithUnsignedInt:(unsigned)anUnsignedInt +{ + return anUnsignedInt; +} + ++ (id)numberWithUnsignedLong:(unsigned long)anUnsignedLong +{ + return anUnsignedLong; +} + ++ (id)numberWithUnsignedLongLong:(unsigned long long)anUnsignedLongLong +{ + return anUnsignedLongLong; +} + ++ (id)numberWithUnsignedShort:(unsigned short)anUnsignedShort +{ + return anUnsignedShort; +} + +- (id)initWithBool:(BOOL)aBoolean +{ + return aBoolean; +} + +- (id)initWithChar:(char)aChar +{ + if (aChar.charCodeAt) + return aChar.charCodeAt(0); + + return aChar; +} + +- (id)initWithDouble:(double)aDouble +{ + return aDouble; +} + +- (id)initWithFloat:(float)aFloat +{ + return aFloat; +} + +- (id)initWithInt:(int)anInt +{ + return anInt; +} + +- (id)initWithLong:(long)aLong +{ + return aLong; +} + +- (id)initWithLongLong:(long long)aLongLong +{ + return aLongLong; +} + +- (id)initWithShort:(short)aShort +{ + return aShort; +} + +- (id)initWithUnsignedChar:(unsigned char)aChar +{ + if (aChar.charCodeAt) + return aChar.charCodeAt(0); + + return aChar; +} + +- (id)initWithUnsignedInt:(unsigned)anUnsignedInt +{ + return anUnsignedInt; +} + +- (id)initWithUnsignedLong:(unsigned long)anUnsignedLong +{ + return anUnsignedLong; +} + +- (id)initWithUnsignedLongLong:(unsigned long long)anUnsignedLongLong +{ + return anUnsignedLongLong; +} + +- (id)initWithUnsignedShort:(unsigned short)anUnsignedShort +{ + return anUnsignedShort; +} + +- (CPString)hash +{ + if (!_CPNumberHashes[self]) + _CPNumberHashes[self] = _objj_generateObjectHash(); + + return _CPNumberHashes[self]; +} + +- (BOOL)boolValue +{ + // Ensure we return actual booleans. + return self ? true : false; +} + +- (char)charValue +{ + return String.fromCharCode(self); +} + +/* +FIXME: Do we need this? +*/ +- (CPDecimal)decimalValue +{ + objj_throw_exception("decimalValue: NOT YET IMPLEMENTED"); +} + +- (CPString)descriptionWithLocale:(CPDictionary)aDictionary +{ + if (!aDictionary) return toString(); + + objj_throw_exception("descriptionWithLocale: NOT YET IMPLEMENTED"); +} + +- (CPString)description +{ + return [self descriptionWithLocale:nil]; +} + +- (double)doubleValue +{ + if (typeof self == "boolean") return self ? 1 : 0; + return self; +} + +- (float)floatValue +{ + if (typeof self == "boolean") return self ? 1 : 0; + return self; +} + +- (int)intValue +{ + if (typeof self == "boolean") return self ? 1 : 0; + return self; +} + +- (long long)longLongValue +{ + if (typeof self == "boolean") return self ? 1 : 0; + return self; +} + +- (long)longValue +{ + if (typeof self == "boolean") return self ? 1 : 0; + return self; +} + +- (short)shortValue +{ + if (typeof self == "boolean") return self ? 1 : 0; + return self; +} + +- (CPString)stringValue +{ + return toString(); +} + +- (unsigned char)unsignedCharValue +{ + return String.fromCharCode(self); +} + +- (unsigned int)unsignedIntValue +{ + if (typeof self == "boolean") return self ? 1 : 0; + return self; +} + +- (unsigned long long)unsignedLongLongValue +{ + if (typeof self == "boolean") return self ? 1 : 0; + return self; +} + +- (unsigned long)unsignedLongValue +{ + if (typeof self == "boolean") return self ? 1 : 0; + return self; +} + +- (unsigned short)unsignedShortValue +{ + if (typeof self == "boolean") return self ? 1 : 0; + return self; +} + +- (CPComparisonResult)compare:(CPNumber)aNumber +{ + if (self > aNumber) return CPOrderedDescending; + else if (self < aNumber) return CPOrderedAscending; + + return CPOrderedSame; +} + +- (BOOL)isEqualToNumber:(CPNumber)aNumber +{ + return self == aNumber; +} + +@end + +@implementation CPNumber (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + return [aCoder decodeNumber]; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeNumber:self forKey:@"self"]; +} + +@end + +Number.prototype.isa = CPNumber; +Boolean.prototype.isa = CPNumber; +[CPNumber initialize]; diff --git a/Foundation/CPObjJRuntime.j b/Foundation/CPObjJRuntime.j new file mode 100644 index 000000000..fd789a6f9 --- /dev/null +++ b/Foundation/CPObjJRuntime.j @@ -0,0 +1,68 @@ +/* + * CPObjJRuntime.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPLog.j" + +function CPStringFromSelector(aSelector) +{ + return sel_getName(aSelector); +} + +function CPSelectorFromString(aSelectorName) +{ + return sel_registerName(aSelectorName); +} + +function CPClassFromString(aClassName) +{ + return objj_getClass(aClassName); +} + +function CPStringFromClass(aClass) +{ + return class_getName(aClass); +} + +CPOrderedAscending = -1; +CPOrderedSame = 0; +CPOrderedDescending = 1; + +CPNotFound = -1; + +MIN = Math.min; +MAX = Math.max; +ABS = Math.abs; + +/*function MIN(lhs, rhs) +{ + return Math.min(lhs, rhs); +} + +function MAX(lhs, rhs) +{ + return Math.max(lhs, rhs); +} + +function ABS(argument) +{ + return Math.abs(argument); +}*/ diff --git a/Foundation/CPObject.j b/Foundation/CPObject.j new file mode 100644 index 000000000..35587acec --- /dev/null +++ b/Foundation/CPObject.j @@ -0,0 +1,291 @@ +/* + * CPObject.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +@implementation CPObject +{ + Class isa; +} + ++ (void)load +{ +} + ++ (void)initialize +{ +// CPLog("calling initialize "+self.name); +} + ++ (id)new +{ + return [[self alloc] init]; +} + ++ (id)alloc +{ +// CPLog("calling alloc on " + self.name + "."); + return class_createInstance(self); +} + +- (id)init +{ + return self; +} + +- (id)copy +{ + return self; +} + +- (id)mutableCopy +{ + return [self copy]; +} + +- (void)dealloc +{ +} + +// Identifying classes + ++ (Class)class +{ + return self; +} + +- (Class)class +{ + return isa; +} + ++ (Class)superclass +{ + return super_class; +} + ++ (BOOL)isSubclassOfClass:(Class)aClass +{ + var theClass = self; + + for(; theClass; theClass = theClass.super_class) + if(theClass == aClass) return YES; + + return NO; +} + +- (BOOL)isKindOfClass:(Class)aClass +{ + return [isa isSubclassOfClass:aClass]; +} + +- (BOOL)isMemberOfClass:(Class)aClass +{ + return self.isa == aClass; +} + +- (BOOL)isProxy +{ + return NO; +} + +// Testing class functionality + ++ (BOOL)instancesRespondToSelector:(SEL)aSelector +{ + return class_getInstanceMethod(self, aSelector); +} + +- (BOOL)respondsToSelector:(SEL)aSelector +{ + return class_getInstanceMethod(isa, aSelector) != NULL; +} + +// Obtaining method information + +- (IMP)methodForSelector:(SEL)aSelector +{ + return class_getInstanceMethod(isa, aSelector); +} + ++ (IMP)instanceMethodForSelector:(SEL)aSelector +{ + return class_getInstanceMethod(isa, aSelector); +} + +- (CPMethodSignature)methodSignatureForSelector:(SEL)aSelector +{ + // FIXME: We need to implement method signatures. + return nil; +} + +// Describing objects + +- (CPString)description +{ + return "<" + isa.name + " 0x" + [CPString stringWithHash:[self hash]] + ">"; +} + +// Sending Messages + +- (id)performSelector:(SEL)aSelector +{ + return objj_msgSend(self, aSelector); +} + +- (id)performSelector:(SEL)aSelector withObject:(id)anObject +{ + return objj_msgSend(self, aSelector, anObject); +} + +- (id)performSelector:(SEL)aSelector withObject:(id)anObject withObject:(id)anotherObject +{ + return objj_msgSend(self, aSelector, anObject, anotherObject); +} + +// Forwarding Messages + +- (void)forwardInvocation:(CPInvocation)anInvocation +{ + [self doesNotRecognizeSelector:[anInvocation selector]]; +} + +- (void)forward:(SEL)aSelector :(marg_list)args +{ + var signature = [self methodSignatureForSelector:_cmd]; + + if (signature) + { + invocation = [CPInvocation invocationWithMethodSignature:signature]; + + [invocation setTarget:self]; + [invocation setSelector:aSelector]; + + var index = 2, + count = args.length; + + for (; index < count; ++index) + [invocation setArgument:args[index] atIndex:index]; + + [self forwardInvocation:invocation]; + + return [invocation returnValue]; + } + + [self doesNotRecognizeSelector:aSelector]; +} + +// Error Handling + +- (void)doesNotRecognizeSelector:(SEL)aSelector +{ + [CPException raise:CPInvalidArgumentException reason: + (class_isMetaClass(isa) ? "+" : "-") + " [" + [self className] + " " + aSelector + "] unrecognized selector sent to " + + (class_isMetaClass(isa) ? "class" : "instance") + " 0x" + [CPString stringWithHash:[self hash]]]; +} + +// Archiving + +- (void)awakeAfterUsingCoder:(CPCoder)aCoder +{ + return self; +} + +- (Class)classForKeyedArchiver +{ + return [self classForCoder]; +} + +- (Class)classForCoder +{ + return [self class]; +} + +- (id)replacementObjectForArchiver:(CPArchiver)anArchiver +{ + return [self replacementObjectForCoder:anArchiver]; +} + +- (id)replacementObjectForKeyedArchiver:(CPKeyedArchiver)anArchiver +{ + return [self replacementObjectForCoder:anArchiver]; +} + +- (id)replacementObjectForCoder:(CPCoder)aCoder +{ + return self; +} + ++ (id)setVersion:(int)aVersion +{ + version = aVersion; + + return self; +} + ++ (int)version +{ + return version; +} + +// Scripting (?) + +- (CPString)className +{ + return isa.name; +} + +// Extras + +- (id)autorelease +{ + return self; +} + +- (unsigned)hash +{ + return __address; +} + +- (BOOL)isEqual:(id)anObject +{ + return self === anObject; +} + +- (void)retain +{ + return self; +} + +- (void)release +{ +} + +- (id)self +{ + return self; +} + +- (Class)superclass +{ + return isa.super_class; +} + +@end diff --git a/Foundation/CPPropertyListSerialization.j b/Foundation/CPPropertyListSerialization.j new file mode 100644 index 000000000..0999ea4c3 --- /dev/null +++ b/Foundation/CPPropertyListSerialization.j @@ -0,0 +1,42 @@ +/* + * CPPropertyListSerialization.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +CPPropertyListOpenStepFormat = kCFPropertyListOpenStepFormat; +CPPropertyListXMLFormat_v1_0 = kCFPropertyListXMLFormat_v1_0; +CPPropertyListBinaryFormat_v1_0 = kCFPropertyListBinaryFormat_v1_0; +CPPropertyList280NorthFormat_v1_0 = kCFPropertyList280NorthFormat_v1_0; + +@implementation CPPropertyListSerialization : CPObject +{ +} + ++ (CPData)dataFromPropertyList:(id)aPlist format:(CPPropertyListFormat)aFormat errorDescription:({CPString})anErrorString +{ + return CPPropertyListCreateData(aPlist, aFormat); +} + ++ (id)propertyListFromData:(CPData)data format:(CSPropertyListFormat)aFormat errorDescription:({CPString})errorString +{ + return CPPropertyListCreateFromData(data, aFormat); +} + +@end diff --git a/Foundation/CPRange.j b/Foundation/CPRange.j new file mode 100755 index 000000000..30c36c86d --- /dev/null +++ b/Foundation/CPRange.j @@ -0,0 +1,83 @@ +/* + * CPRange.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +function CPMakeRange(location, length) +{ + return { location: location, length: length }; +} + +function CPCopyRange(aRange) +{ + return { location: aRange.location, length: aRange.length }; +} + +function CPMakeRangeCopy(aRange) +{ + return { location:aRange.location, length:aRange.length }; +} + +function CPEmptyRange(aRange) +{ + return aRange.length == 0; +} + +function CPMaxRange(aRange) +{ + return aRange.location + aRange.length; +} + +function CPEqualRanges(lhsRange, rhsRange) +{ + return ((lhsRange.location == rhsRange.location) && (lhsRange.length == rhsRange.length)); +} + +function CPLocationInRange(aLocation, aRange) +{ + return (aLocation >= aRange.location) && (aLocation < CPMaxRange(aRange)); +} + +function CPUnionRange(lhsRange, rhsRange) +{ + var location = Math.min(lhsRange.location, rhsRange.location); + return CPMakeRange(location, Math.max(CPMaxRange(lhsRange), CPMaxRange(rhsRange)) - location); +} + +function CPIntersectionRange(lhsRange, rhsRange) +{ + if(CPMaxRange(lhsRange) < rhsRange.location || CPMaxRange(rhsRange) < lhsRange.location) + return CPMakeRange(0, 0); + + var location = Math.max(lhsRange.location, rhsRange.location); + return CPMakeRange(location, Math.min(CPMaxRange(lhsRange), CPMaxRange(rhsRange)) - location); +} + +function CPStringFromRange(aRange) +{ + return "{" + aRange.location + ", " + aRange.length + "}"; +} + +function CPRangeFromString(aString) +{ + var comma = aString.indexOf(','); + + return { location:parseInt(aString.substr(1, comma - 1)), length:parseInt(aString.substring(comma + 1, aString.length)) }; +} diff --git a/Foundation/CPRunLoop.j b/Foundation/CPRunLoop.j new file mode 100644 index 000000000..57c9f690d --- /dev/null +++ b/Foundation/CPRunLoop.j @@ -0,0 +1,224 @@ +/* + * CPRunLoop.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPObject.j" +import "CPArray.j" +import "CPString.j" + +CPDefaultRunLoopMode = @"CPDefaultRunLoopMode"; + +function _CPRunLoopPerformCompare(lhs, rhs) +{ + return [rhs order] - [lhs order]; +} + +var _CPRunLoopPerformPool = [], + _CPRunLoopPerformPoolCapacity = 5; + +@implementation _CPRunLoopPerform : CPObject +{ + id _target; + SEL _selector; + id _argument; + unsigned _order; + CPArray _runLoopModes; +} + ++ (void)_poolPerform:(_CPRunLoopPerform)aPerform +{ + if (!aPerform || _CPRunLoopPerformPool.length >= _CPRunLoopPerformPoolCapacity) + return; + + _CPRunLoopPerformPool.push(aPerform); +} + ++ (_CPRunLoopPerform)performWithSelector:(SEL)aSelector target:(id)aTarget argument:(id)anArgument order:(unsigned)anOrder modes:(CPArray)modes +{ + if (_CPRunLoopPerformPool.length) + { + var perform = _CPRunLoopPerformPool.pop(); + + perform._target = aTarget; + perform._selector = aSelector; + perform._arguments = anArgument; + perform._order = anOrder; + perform._runLoopModes = modes; + + return perform; + } + + return [[self alloc] initWithSelector:aSelector target:aTarget argument:anArgument order:anOrder modes:modes]; +} + +- (id)initWithSelector:(SEL)aSelector target:(SEL)aTarget argument:(id)anArgument order:(unsigned)anOrder modes:(CPArray)modes +{ + self = [super init]; + + if (self) + { + _selector = aSelector; + _target = aTarget; + _argument = anArgument; + _order = anOrder; + _runLoopModes = modes; + } + + return self; +} + +- (SEL)selector +{ + return _selector; +} + +- (id)target +{ + return _target; +} + +- (id)argument +{ + return _argument; +} + +- (unsigned)order +{ + return _order; +} + +- (BOOL)fireInMode:(CPString)aRunLoopMode +{ + if ([_runLoopModes containsObject:aRunLoopMode]) + { + [_target performSelector:_selector withObject:_argument]; + + return YES; + } + + return NO; +} + +@end + +@implementation CPRunLoop : CPObject +{ + CPArray _queuedPerforms; + CPArray _orderedPerforms; + BOOL _isPerformingSelectors; +} + ++ (void)initialize +{ + if (self != [CPRunLoop class]) + return; + + CPMainRunLoop = [[CPRunLoop alloc] init]; +} + +- (id)init +{ + self = [super init]; + + if (self) + { + _queuedPerforms = []; + _orderedPerforms = []; + } + + return self; +} + ++ (CPRunLoop)currentRunLoop +{ + return CPMainRunLoop; +} + ++ (CPRunLoop)mainRunLoop +{ + return CPMainRunLoop; +} + +- (void)performSelector:(SEL)aSelector target:(id)aTarget argument:(id)anArgument order:(int)anOrder modes:(CPArray)modes +{ + var perform = [_CPRunLoopPerform performWithSelector:aSelector target:aTarget argument:anArgument order:anOrder modes:modes]; + + if (_isPerformingSelectors) + _queuedPerforms.push(perform); + else + { + var count = _orderedPerforms.length; + + // We sort ourselves in reverse because we iterate this list backwards. + while (count--) + if (anOrder < [_orderedPerforms[count] order]) + break; + + _orderedPerforms.splice(count + 1, 0, perform); + } +} + +- (void)cancelPerformSelector:(SEL)aSelector target:(id)aTarget argument:(id)anArgument +{ + var count = _orderedPerforms.length; + + while (count--) + { + var perform = _orderedPerforms[count]; + + if ([perform selector] == aSelector && [perform target] == aTarget && [perform argument] == anArgument) + [_orderedPerforms removeObjectAtIndex:count]; + } +} + +- (void)performSelectors +{ + if (_isPerformingSelectors) + return; + + _isPerformingSelectors = YES; + + var index = _orderedPerforms.length; + + while (index--) + { + var perform = _orderedPerforms[index]; + + if ([perform fireInMode:CPDefaultRunLoopMode]) + { + [_CPRunLoopPerform _poolPerform:perform]; + + _orderedPerforms.splice(index, 1); + } + } + + _isPerformingSelectors = NO; + + if (_queuedPerforms.length) + { + _orderedPerforms = _orderedPerforms.concat(_queuedPerforms); + _orderedPerforms.sort(_CPRunLoopPerformCompare); + } + + _queuedPerforms = []; +} + +@end \ No newline at end of file diff --git a/Foundation/CPSortDescriptor.j b/Foundation/CPSortDescriptor.j new file mode 100755 index 000000000..197cc7372 --- /dev/null +++ b/Foundation/CPSortDescriptor.j @@ -0,0 +1,83 @@ +/* + * CPSortDescriptor.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPObject.j" +import "CPObjJRuntime.j" + +@implementation CPSortDescriptor : CPObject +{ + CPString _key; + SEL _selector; + BOOL _ascending; +} + +// Initializing a sort descriptor + +- (id)initWithKey:(CPString)aKey ascending:(BOOL)isAscending +{ + return [self initWithKey:aKey ascending:isAscending selector:@selector(compare:)]; +} + +- (id)initWithKey:(CPString)aKey ascending:(BOOL)isAscending selector:(SEL)aSelector +{ + self = [super init]; + + if (self) + { + _key = aKey; + _ascending = isAscending; + _selector = aSelector; + } + + return self; +} + +// Getting information about a sort descriptor + +- (BOOL)ascending +{ + return _ascending; +} + +- (CPString)key +{ + return _key; +} + +- (SEL)selector +{ + return _selector; +} + +// Using sort descriptors + +- (CPComparisonResult)compareObject:(id)lhsObject withObject:(id)rhsObject +{ + return (_ascending ? 1 : -1) * [[lhsObject valueForKey:_key] performSelector:_selector withObject:[rhsObject valueForKey:_key]]; +} + +- (id)reversedSortDescriptor +{ + return [[[self class] alloc] initWithKey:_key ascending:!_ascending selector:_selector]; +} + +@end \ No newline at end of file diff --git a/Foundation/CPString.j b/Foundation/CPString.j new file mode 100644 index 000000000..d52d3df7f --- /dev/null +++ b/Foundation/CPString.j @@ -0,0 +1,285 @@ +/* + * CPString.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPObject.j" + + +CPCaseInsensitiveSearch = 1; +CPLiteralSearch = 2; +CPBackwardsSearch = 4; +CPAnchoredSearch = 8; +CPNumericSearch = 64; + +var CPStringHashes = new objj_dictionary(); + +@implementation CPString : CPObject + ++ (id)alloc +{ + return new String; +} + ++ (id)string +{ + return [[self alloc] init]; +} + ++ (id)stringWithHash:(unsigned)aHash +{ + var zeros = "000000", + digits = aHash.toString(16); + + return zeros.substring(0, zeros.length - digits.length) + digits; +} + ++ (id)stringWithString:(CPString)aString +{ + return [[self alloc] initWithString:aString]; +} + +- (id)initWithString:(CPString)aString +{ + return aString + ""; +} + +- (CPString)description +{ + return "<" + self.isa.name + " 0x" + [CPString stringWithHash:[self hash]] + " \"" + self + "\">"; +} + +- (int)length +{ + return length; +} + +- (char)characterAtIndex:(unsigned)anIndex +{ + return charAt(anIndex); +} + +// Combining strings + +- (CPString)stringByAppendingString:(CPString)aString +{ + return self + aString; +} + +- (CPString)stringByPaddingToLength:(unsigned)aLength withString:(CPString)aString startingAtIndex:(unsigned)anIndex +{ + if (length == aLength) + return self; + + if (aLength < length) + return substr(0, aLength); + + var string = self, + substring = aString.substr(anIndex), + difference = aLength - length; + + while ((difference -= substring.length) > 0) + string += substring; + + if (difference) string += substring.substr(difference + substring.length); +} + +- (CPArray)componentsSeparatedByString:(CPString)aString +{ + return split(aString); +} + +- (CPString)substringFromIndex:(unsigned)anIndex +{ + return substr(anIndex); +} + +- (CPString)substringWithRange:(CPRange)aRange +{ + return substr(aRange.location, aRange.length); +} + +- (CPString)substringToIndex:(unsigned)anIndex +{ + return substring(0, anIndex); +} + +// Finding characters and substrings + +- (CPRange)rangeOfString:(CPString)aString +{ + var location = indexOf(aString); + + return CPMakeRange(location, location == CPNotFound ? 0 : aString.length); +} + +- (CPRange)rangeOfString:(CPString)aString options:(int)aMask +{ + var string = self, + location = CPNotFound; + + if (aMask & CPCaseInsensitiveSearch) + { + string = string.toLowerCase(); + aString = aString.toLowerCase(); + } + + if (CPBackwardsSearch) location = lastIndexOf(aString, aMask & CPAnchoredSearch ? length - aString.length : 0); + else if (aMask & CPAnchoredSearch) location = substr(0, aString.length).indexOf(aString) != CPNotFound ? 0 : CPNotFound; + else location = indexOf(aString); + + return CPMakeRange(location, location == CPNotFound ? 0 : aString.length); +} + +// Identifying and comparing strings + +- (CPComparisonResult)caseInsensitiveCompare:(CPString)aString +{ + return [self compare:aString options:CPCaseInsensitiveSearch] +} + +- (CPComparisonResult)compare:(CPString)aString options:(int)aMask +{ + var lhs = self, + rhs = aString; + + if (aMask & CPCaseInsensitiveSearch) + { + lhs = lhs.toLowerCase(); + rhs = rhs.toLowerCase(); + } + + if (lhs < rhs) + return CPOrderedAscending; + else if (lhs > rhs) + return CPOrderedDescending; + + return CPOrderedSame; +} + +- (BOOL)hasPrefix:(CPString)aString +{ + return aString && aString != "" && indexOf(aString) == 0; +} + +- (BOOL)hasSuffix:(CPString)aString +{ + return aString && aString != "" && lastIndexOf(aString) == (length - aString.length); +} + +- (BOOL)isEqualToString:(CPString)aString +{ + return self == aString; +} + +- (unsigned)hash +{ + var hash = dictionary_getValue(CPStringHashes, self); + + if (!hash) + { + hash = _objj_generateObjectHash(); + dictionary_setValue(CPStringHashes, self, hash); + } + + return hash; +} + +- (CPString)capitalizedString +{ + var i = 0, + last = true, + capitalized = self; + + for(; i < length; ++i) + { + var character = charAt(i); + if (character == ' ' || character == '\t' || character == '\n') last = true; + else + { + if (last) capitalized = capitalized.substr(0, i - 1) + character.toUpperCase() + capitalized.substr(i); + last = false; + } + } + + return capitalized; +} + +- (CPString)lowercaseString +{ + return toLowerCase(); +} + +- (CPString)uppercaseString +{ + return toUpperCase(); +} + +- (double)doubleValue +{ + return eval(self); +} + +- (float)floatValue +{ + return eval(self); +} + +- (int)intValue +{ + return parseInt(self); +} + +- (CPArray)pathComponents +{ + return split('/'); +} + +- (CPString)pathExtension +{ + return substr(lastIndexOf('.')+1); +} + +- (CPString)lastPathComponent +{ + var components = [self pathComponents]; + return components[components.length -1]; +} + +- (CPString)stringByDeletingLastPathComponent +{ + // FIMXE: this is wrong: a/a/ returns a/a/. + return substr(0, lastIndexOf('/') + 1); +} + +- (CPString)stringByStandardizingPath +{ + return objj_standardize_path(self); +} + +- (CPString)copy +{ + return new String(self); +} + +@end + + +String.prototype.isa = CPString; diff --git a/Foundation/CPURLConnection.j b/Foundation/CPURLConnection.j new file mode 100644 index 000000000..a98acb9b1 --- /dev/null +++ b/Foundation/CPURLConnection.j @@ -0,0 +1,181 @@ +/* + * CPURLConnection.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPObject.j" +import "CPRunLoop.j" +import "CPURLRequest.j" +import "CPURLResponse.j" + + +var XMLHTTPRequestUninitialized = 0, + XMLHTTPRequestLoading = 1, + XMLHTTPRequestLoaded = 2, + XMLHTTPRequestInteractive = 3, + XMLHTTPRequestComplete = 4; + +var CPURLConnectionDelegate = nil; + +@implementation CPURLConnection : CPObject +{ + CPURLRequest _request; + id _delegate; + BOOL _isCanceled; + + XMLHTTPRequest _XMLHTTPRequest; +} + ++ (void)setClassDelegate:(id)delegate +{ + CPURLConnectionDelegate = delegate; +} + ++ (CPData)sendSynchronousRequest:(CPURLRequest)aRequest returningResponse:(CPURLResponse **)aURLResponse error:(CPError **)anError +{ + try + { + var request = objj_request_xmlhttp(); + + request.open([aRequest HTTPMethod], [aRequest URL], NO); + + var fields = [aRequest allHTTPHeaderFields], + key = nil, + keys = [fields keyEnumerator]; + + while (key = [keys nextObject]) + request.setRequestHeader(key, [fields objectForKey:key]); + + request.send([aRequest HTTPBody]); + + return [CPData dataWithString:request.responseText]; + } + catch (anException) + { + } + + return nil; +} + ++ (CPURLConnection)connectionWithRequest:(CPURLRequest)aRequest delegate:(id)aDelegate +{ + return [[self alloc] initWithRequest:aRequest delegate:aDelegate]; +} + +- (id)initWithRequest:(CPURLRequest)aRequest delegate:(id)aDelegate startImmediately:(BOOL)shouldStartImmediately +{ + self = [super init]; + + if (self) + { + _request = aRequest; + _delegate = aDelegate; + _isCanceled = NO; + + _XMLHTTPRequest = objj_request_xmlhttp(); + + if (shouldStartImmediately) + [self start]; + } + + return self; +} + +- (id)initWithRequest:(CPURLRequest)aRequest delegate:(id)aDelegate +{ + return [self initWithRequest:aRequest delegate:aDelegate startImmediately:YES]; +} + +- (id)delegate +{ + return _delegate; +} + +- (void)start +{ + _isCanceled = NO; + + try + { + _XMLHTTPRequest.open([_request HTTPMethod], [_request URL], YES); + + _XMLHTTPRequest.onreadystatechange = function() { [self _readyStateDidChange]; } + + var fields = [_request allHTTPHeaderFields], + key = nil, + keys = [fields keyEnumerator]; + + while (key = [keys nextObject]) + _XMLHTTPRequest.setRequestHeader(key, [fields objectForKey:key]); + + _XMLHTTPRequest.send([_request HTTPBody]); + } + catch (anException) + { + [_delegate connection:self didFailWithError:anException]; + } +} + +- (void)cancel +{ + _isCanceled = YES; + + try + { + _XMLHTTPRequest.abort(); + } + // We expect an exception in some browsers like FireFox. + catch (anException) + { + } +} + +- (void)_readyStateDidChange +{ + if (_XMLHTTPRequest.readyState == XMLHTTPRequestComplete) + { + var statusCode = _XMLHTTPRequest.status; + + if ([_delegate respondsToSelector:@selector(connection:didReceiveResponse:)]) + [_delegate connection:self didReceiveResponse:[[CPHTTPURLResponse alloc] _initWithStatusCode:statusCode]]; + + if (!_isCanceled) + { + if (statusCode == 200) + { + [_delegate connection:self didReceiveData:_XMLHTTPRequest.responseText]; + [_delegate connectionDidFinishLoading:self]; + } + else if (statusCode == 401 && [CPURLConnectionDelegate respondsToSelector:@selector(connectionDidReceiveAuthenticationChallenge:)]) + [CPURLConnectionDelegate connectionDidReceiveAuthenticationChallenge:self]; + else + [_delegate connection:self didFailWithError:_XMLHTTPRequest.status] + } + } + + [[CPRunLoop currentRunLoop] performSelectors]; +} + +- (void)_XMLHTTPRequest +{ + return _XMLHTTPRequest; +} + +@end diff --git a/Foundation/CPURLRequest.j b/Foundation/CPURLRequest.j new file mode 100644 index 000000000..7a8e61a2a --- /dev/null +++ b/Foundation/CPURLRequest.j @@ -0,0 +1,103 @@ +/* + * CPURLRequest.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPObject.j" + +@implementation CPURLRequest : CPObject +{ + CPURL _URL; + + // FIXME: this should be CPData + CPString _HTTPBody; + CPString _HTTPMethod; + CPDictionary _HTTPHeaderFields; +} + ++ (id)requestWithURL:(CPURL)aURL +{ + return [[CPURLRequest alloc] initWithURL:aURL]; +} + +- (id)initWithURL:(CPURL)aURL +{ + self = [super init]; + + if (self) + { + _URL = aURL; + _HTTPBody = @""; + _HTTPMethod = @"GET"; + _HTTPHeaderFields = [CPDictionary dictionary]; + + [self setValue:"Thu, 1 Jan 1970 00:00:00 GMT" forHTTPHeaderField:"If-Modified-Since"]; + [self setValue:"no-cache" forHTTPHeaderField:"Cache-Control"]; + } + + return self; +} + +- (CPURL)URL +{ + return _URL; +} + +- (void)setURL:(CPURL)aURL +{ + _URL = aURL; +} + +- (void)setHTTPBody:(CPString)anHTTPBody +{ + _HTTPBody = anHTTPBody; +} + +- (CPString)HTTPBody +{ + return _HTTPBody; +} + +- (void)setHTTPMethod:(CPString)anHTTPMethod +{ + _HTTPMethod = anHTTPMethod; +} + +- (CPString)HTTPMethod +{ + return _HTTPMethod; +} + +- (CPDictionary)allHTTPHeaderFields +{ + return _HTTPHeaderFields; +} + +- (CPString)valueForHTTPHeaderField:(CPString)aField +{ + return [_HTTPHeaderFields objectForKey:aField]; +} + +- (void)setValue:(CPString)aValue forHTTPHeaderField:(CPString)aField +{ + [_HTTPHeaderFields setObject:aValue forKey:aField]; +} + +@end diff --git a/Foundation/CPURLResponse.j b/Foundation/CPURLResponse.j new file mode 100644 index 000000000..4362c2d08 --- /dev/null +++ b/Foundation/CPURLResponse.j @@ -0,0 +1,67 @@ +/* + * CPURLResponse.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPObject.j" + + +/* + CPURL _URL; + CPString _MIMEType; + unsigned _expectedContentLength; + CPString _textEncodingName; +*/ +@implementation CPURLResponse : CPObject +{ +} +/* +Creating a Response +Ð initWithURL:MIMEType:expectedContentLength:textEncodingName: +Getting the Response Properties +Ð expectedContentLength +Ð suggestedFilename +Ð MIMEType +Ð textEncodingName +Ð URL +*/ +@end + +@implementation CPHTTPURLResponse : CPURLResponse +{ + int _statusCode; +} + +- (id)_initWithStatusCode:(int)aStatusCode +{ + self = [super init]; + + if (self) + _statusCode = aStatusCode; + + return self; +} + +- (int)statusCode +{ + return _statusCode; +} + +@end diff --git a/Foundation/CPUndoManager.j b/Foundation/CPUndoManager.j new file mode 100644 index 000000000..e25703b72 --- /dev/null +++ b/Foundation/CPUndoManager.j @@ -0,0 +1,599 @@ +/* + * CPUndoManager.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPObject.j" +import "CPInvocation.j" + +var CPUndoManagerNormal = 0, + CPUndoManagerUndoing = 1, + CPUndoManagerRedoing = 2; + +CPUndoManagerCheckpointNotification = @"CPUndoManagerCheckpointNotification"; +CPUndoManagerDidOpenUndoGroupNotification = @"CPUndoManagerDidOpenUndoGroupNotification"; +CPUndoManagerDidRedoChangeNotification = @"CPUndoManagerDidRedoChangeNotification"; +CPUndoManagerDidUndoChangeNotification = @"CPUndoManagerDidUndoChangeNotification"; +CPUndoManagerWillCloseUndoGroupNotification = @"CPUndoManagerWillCloseUndoGroupNotification"; +CPUndoManagerWillRedoChangeNotification = @"CPUndoManagerWillRedoChangeNotification"; +CPUndoManagerWillUndoChangeNotification = @"CPUndoManagerWillUndoChangeNotification"; + +CPUndoCloseGroupingRunLoopOrdering = 350000; + +var _CPUndoGroupingPool = [], + _CPUndoGroupingPoolCapacity = 5; + +@implementation _CPUndoGrouping : CPObject +{ + _CPUndoGrouping _parent; + CPMutableArray _invocations; +} + ++ (void)_poolUndoGrouping:(_CPUndoGrouping)anUndoGrouping +{ + if (!anUndoGrouping || _CPUndoGroupingPool.length >= _CPUndoGroupingPoolCapacity) + return; + + _CPUndoGroupingPool.push(anUndoGrouping); +} + ++ (id)undoGroupingWithParent:(_CPUndoGrouping)anUndoGrouping +{ + if (_CPUndoGroupingPool.length) + { + var grouping = _CPUndoGroupingPool.pop(); + + grouping._parent = anUndoGrouping; + + if (grouping._invocations.length) + grouping._invocations = []; + + return grouping; + } + + return [[self alloc] initWithParent:anUndoGrouping]; +} + +- (id)initWithParent:(_CPUndoGrouping)anUndoGrouping +{ + self = [super init]; + + if (self) + { + _parent = anUndoGrouping; + _invocations = []; + } + + return self; +} + +- (_CPUndoGrouping)parent +{ + return _parent; +} + +- (void)addInvocation:(CPInvocation)anInvocation +{ + _invocations.push(anInvocation); +} + +- (void)addInvocationsFromArray:(CPArray)invocations +{ + [_invocations addObjectsFromArray:invocations]; +} + +- (BOOL)removeInvocationsWithTarget:(id)aTarget +{ + var index = _invocations.length; + + while (index--) + if ([_invocations[index] target] == aTarget) + _invocations.splice(index, 1); +} + +- (CPArray)invocations +{ + return _invocations; +} + +- (void)invoke +{ + var index = _invocations.length; + + while (index--) + [_invocations[index] invoke]; +} + +@end + +var _CPUndoGroupingParentKey = @"_CPUndoGroupingParentKey", + _CPUndoGroupingInvocationsKey = @"_CPUndoGroupingInvocationsKey"; + +@implementation _CPUndoGrouping (CPCoder) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super init]; + + if (self) + { + _parent = [aCoder decodeObjectForKey:_CPUndoGroupingParentKey]; + _invocations = [aCoder decodeObjectForKey:_CPUndoGroupingInvocationsKey]; + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeObject:_parent forKey:_CPUndoGroupingParentKey]; + [aCoder encodeObject:_invocations forKey:_CPUndoGroupingInvocationsKey]; +} + +@end + +@implementation CPUndoManager : CPObject +{ + CPMutableArray _redoStack; + CPMutableArray _undoStack; + + BOOL _groupsByEvent; + int _disableCount; + int _levelsOfUndo; + id _currentGrouping; + int _state; + CPString _actionName; + id _preparedTarget; + + CPArray _runLoopModes; + BOOL _registeredWithRunLoop; +} + +- (id)init +{ + self = [super init]; + + if (self) + { + _redoStack = []; + _undoStack = []; + + _state = CPUndoManagerNormal; + + [self setRunLoopModes:[CPDefaultRunLoopMode]]; + [self setGroupsByEvent:YES]; + _performRegistered = NO; + } + + return self; +} + +// Registering Undo Operations + +- (void)registerUndoWithTarget:(id)aTarget selector:(SEL)aSelector object:(id)anObject +{ + if (_disableCount > 0) + return; + +/* if (_currentGroup == nil) + [NSException raise:NSInternalInconsistencyException + format:@"forwardInvocation called without first opening an undo group"]; +*/ + //signature = [target methodSignatureForSelector:selector]; + // FIXME: we need method signatures. + var invocation = [CPInvocation invocationWithMethodSignature:nil]; + + [invocation setTarget:aTarget]; + [invocation setSelector:aSelector]; + [invocation setArgument:anObject atIndex:2]; + + [_currentGrouping addInvocation:invocation]; + + if (_state == CPUndoManagerNormal) + [_redoStack removeAllObjects]; +} + +- (id)prepareWithInvocationTarget:(id)aTarget +{ + _preparedTarget = aTarget; + + return self; +} + +-(CPMethodSignature)methodSignatureForSelector:(SEL)aSelector +{ + if ([_preparedTarget respondsToSelector:aSelector]) + return 1; + + return nil;//[_preparedTarget methodSignatureForSelector:selector]; +} + +- (void)forwardInvocation:(CPInvocation)anInvocation +{ + if (_disableCount > 0) + return; + +/* if (_preparedTarget == nil) + [NSException raise:NSInternalInconsistencyException + format:@"forwardInvocation called without first preparing a target"]; + if (_currentGroup == nil) + [NSException raise:NSInternalInconsistencyException + format:@"forwardInvocation called without first opening an undo group"]; +*/ + [anInvocation setTarget:_preparedTarget]; + [_currentGrouping addInvocation:anInvocation]; + + if (_state == CPUndoManagerNormal) + [_redoStack removeAllObjects]; + + _preparedTarget = nil; +} + +// Checking Undo Ability + +- (BOOL)canRedo +{ + return _redoStack.length > 0; +} + +- (BOOL)canUndo +{ + if (_undoStack.length > 0) + return YES; + + return [_currentGrouping actions].length > 0; +} + +// Preform Undo and Redo + +- (void)undo +{ + if ([self groupingLevel] == 1) + [self endUndoGrouping]; + + [self undoNestedGroup]; +} + +- (void)undoNestedGroup +{ + if (_undoStack.length == 0) + return; + + var defaultCenter = [CPNotificationCenter defaultCenter]; +/* [[NSNotificationCenter defaultCenter] postNotificationName:NSUndoManagerCheckpointNotification + object:self]; +*/ + [defaultCenter postNotificationName:CPUndoManagerWillUndoChangeNotification object:self]; + + var undoGrouping = _undoStack.pop(); + + _state = CPUndoManagerUndoing; + + [self beginUndoGrouping]; + [undoGrouping invoke]; + [self endUndoGrouping]; + + [_CPUndoGrouping _poolUndoGrouping:undoGrouping]; + + _state = CPUndoManagerNormal; + + [defaultCenter postNotificationName:CPUndoManagerDidUndoChangeNotification object:self]; +} + +- (void)redo +{ + // Don't do anything if we have no redos. + if (_redoStack.length == 0) + return; + +/* if (_state == NSUndoManagerUndoing) + [NSException raise:NSInternalInconsistencyException + format:@"redo called while undoing"]; + + [[NSNotificationCenter defaultCenter] postNotificationName:NSUndoManagerCheckpointNotification + object:self]; +*/ + var defaultCenter = [CPNotificationCenter defaultCenter]; + + [defaultCenter postNotificationName:CPUndoManagerWillRedoChangeNotification object:self]; + + var oldUndoGrouping = _currentGrouping, + undoGrouping = _redoStack.pop(); + + _currentGrouping = nil; + _state = CPUndoManagerRedoing; + + [self beginUndoGrouping]; + [undoGrouping invoke]; + [self endUndoGrouping]; + + [_CPUndoGrouping _poolUndoGrouping:undoGrouping]; + + _currentGrouping = oldUndoGrouping; + _state = CPUndoManagerNormal; + + [defaultCenter postNotificationName:CPUndoManagerDidRedoChangeNotification object:self]; +} + +// Creating Undo Groups + +- (void)beginUndoGrouping +{ + _currentGrouping = [_CPUndoGrouping undoGroupingWithParent:_currentGrouping]; +} + +- (void)endUndoGrouping +{ + if (!_currentGrouping) + alert("FIXME: this should be an exception endUndoGrouping - currentUndoGrouping = nil."); + + var parent = [_currentGrouping parent]; + + if (!parent && [_currentGrouping invocations].length > 0) + { + [[CPNotificationCenter defaultCenter] + postNotificationName:CPUndoManagerWillCloseUndoGroupNotification + object:self]; + + // Put this group on the redo stack if we are currently undoing, otherwise + // put it on the undo stack. That way, "undos" become "redos". + var stack = _state == CPUndoManagerUndoing ? _redoStack : _undoStack; + + stack.push(_currentGrouping); + + if (_levelsOfUndo > 0 && stack.length > _levelsOfUndo) + stack.splice(0, 1); + } + + // Nested Undo Grouping + else + { + [parent addInvocationsFromArray:[_currentGrouping invocations]]; + + [_CPUndoGrouping _poolUndoGrouping:_currentGrouping]; + } + + _currentGrouping = parent; +} + +- (void)enableUndoRegistration +{ + if (_disableCount <= 0) + return; + + _disableCount--; +} + +- (BOOL)groupsByEvent +{ + return _groupsByEvent; +} + +- (void)setGroupsByEvent:(BOOL)aFlag +{ + if (_groupsByEvent == aFlag) + return; + + _groupsByEvent = aFlag; + + if (_groupsByEvent) + { + [self _registerWithRunLoop]; + + // There is a chance that the event loop selector won't fire before our first register, + // so kick it off here. + if (!_currentGrouping) + [self beginUndoGrouping]; + } + else + [self _unregisterWithRunLoop]; +} + +- (unsigned)groupingLevel +{ + var grouping = _currentGrouping, + level = _currentGrouping != nil; + + while (grouping = [grouping parent]) + ++level; + + return level; +} + +// Disabling Undo + +- (void)disableUndoRegistration +{ + ++_disableCount; +} + +- (BOOL)isUndoRegistrationEnabled +{ + return _disableCount == 0; +} + +// Checking Whether Undo or Redo Is Being Performed + +- (BOOL)isUndoing +{ + return _state == CPUndoManagerUndoing; +} + +- (BOOL)isRedoing +{ + return _state == CPUndoManagerRedoing; +} + +// Clearing Undo Operations + +- (void)removeAllActions +{ + _redoStack = []; + _undoStack = []; + _disableCount = 0; +} + +- (void)removeAllActionsWithTarget:(id)aTarget +{ + [_currentGrouping removeInvocationsWithTarget:aTarget]; + + var index = _redoStack.length; + + while (index--) + { + var grouping = _redoStack[index]; + + [grouping removeInvocationsWithTarget:aTarget]; + + if (![grouping invocations].length) + _redoStack.splice(index, 1); + } + + index = _undoStack.length; + + while (index--) + { + var grouping = _undoStack[index]; + + [grouping removeInvocationsWithTarget:aTarget]; + + if (![grouping invocations].length) + _undoStack.splice(index, 1); + } +} + +// Managing the Action Name + +- (void)setActionName:(CPString)anActionName +{ + _actionName = anActionName; +} + +- (CPString)redoActionName +{ + return [self canRedo] ? _actionName : nil; +} + +- (CPString)undoActionName +{ + return [self canUndo] ? _actionName : nil; +} + +// Working With Run Loops + +- (CPArray)runLoopModes +{ + return _runLoopModes; +} + +- (void)setRunLoopModes:(CPArray)modes +{ + _runLoopModes = modes; + + [self _unregisterWithRunLoop]; + + if (_groupsByEvent) + [self _registerWithRunLoop]; +} + +- (void)beginUndoGroupingForEvent +{ + if (!_groupsByEvent) + return; + + if (_currentGrouping != nil) + [self endUndoGrouping]; + + [self beginUndoGrouping]; + + [[CPRunLoop currentRunLoop] performSelector:@selector(beginUndoGroupingForEvent) + target:self argument:nil order:CPUndoCloseGroupingRunLoopOrdering modes:_runLoopModes]; +} + +- (void)_registerWithRunLoop +{ + if (_registeredWithRunLoop) + return; + + _registeredWithRunLoop = YES; + [[CPRunLoop currentRunLoop] performSelector:@selector(beginUndoGroupingForEvent) + target:self argument:nil order:CPUndoCloseGroupingRunLoopOrdering modes:_runLoopModes]; +} + +- (void)_unregisterWithRunLoop +{ + if (!_registeredWithRunLoop) + return; + + _registeredWithRunLoop = NO; + [[CPRunLoop currentRunLoop] cancelPerformSelector:@selector(beginUndoGroupingForEvent) target:self argument:nil]; +} + +@end + +var CPUndoManagerRedoStackKey = @"CPUndoManagerRedoStackKey", + CPUndoManagerUndoStackKey = @"CPUndoManagerUndoStackKey"; + + CPUndoManagerLevelsOfUndoKey = @"CPUndoManagerLevelsOfUndoKey"; + CPUndoManagerActionNameKey = @"CPUndoManagerActionNameKey"; + CPUndoManagerCurrentGroupingKey = @"CPUndoManagerCurrentGroupingKey"; + + CPUndoManagerRunLoopModesKey = @"CPUndoManagerRunLoopModesKey"; + CPUndoManagerGroupsByEventKey = @"CPUndoManagerGroupsByEventKey"; + +@implementation CPUndoManager (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super init]; + + if (self) + { + _redoStack = [aCoder decodeObjectForKey:CPUndoManagerRedoStackKey]; + _undoStack = [aCoder decodeObjectForKey:CPUndoManagerUndoStackKey]; + + _levelsOfUndo = [aCoder decodeObjectForKey:CPUndoManagerLevelsOfUndoKey]; + _actionName = [aCoder decodeObjectForKey:CPUndoManagerActionNameKey]; + _currentGrouping = [aCoder decodeObjectForKey:CPUndoManagerCurrentGroupingKey]; + + _state = CPUndoManagerNormal; + + [self setRunLoopModes:[aCoder decodeObjectForKey:CPUndoManagerRunLoopModesKey]]; + [self setGroupsByEvent:[aCoder decodeBoolForKey:CPUndoManagerGroupsByEventKey]]; + } + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeObject:_redoStack forKey:CPUndoManagerRedoStackKey]; + [aCoder encodeObject:_undoStack forKey:CPUndoManagerUndoStackKey]; + + [aCoder encodeInt:_levelsOfUndo forKey:CPUndoManagerLevelsOfUndoKey]; + [aCoder encodeObject:_actionName forKey:CPUndoManagerActionNameKey]; + + [aCoder encodeObject:_currentGrouping forKey:CPUndoManagerCurrentGroupingKey]; + + [aCoder encodeObject:_runLoopModes forKey:CPUndoManagerRunLoopModesKey]; + [aCoder encodeBool:_groupsByEvent forKey:CPUndoManagerGroupsByEventKey]; +} + +@end diff --git a/Foundation/CPUserSessionManager.j b/Foundation/CPUserSessionManager.j new file mode 100644 index 000000000..97fd32362 --- /dev/null +++ b/Foundation/CPUserSessionManager.j @@ -0,0 +1,98 @@ +/* + * CPUserSessionManager.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import +import + + +CPUserSessionUndeterminedStatus = 0; +CPUserSessionLoggedInStatus = 1; +CPUserSessionLoggedOutStatus = 2; + +CPUserSessionManagerStatusDidChangeNotification = @"CPUserSessionManagerStatusDidChangeNotification"; +CPUserSessionManagerUserIdentifierDidChangeNotification = @"CPUserSessionManagerUserIdentifierDidChangeNotification"; + +var CPDefaultUserSessionManager = nil; + +@implementation CPUserSessionManager : CPObject +{ + CPUserSessionStatus _status; + + CPString _userIdentifier; +} + ++ (id)defaultManager +{ + if (!CPDefaultUserSessionManager) + CPDefaultUserSessionManager = [[CPUserSessionManager alloc] init]; + + return CPDefaultUserSessionManager; +} + +- (id)init +{ + self = [super init]; + + if (self) + _status = CPUserSessionUndeterminedStatus; + + return self; +} + +- (CPUserSessionStatus)status +{ + return _status; +} + +- (void)setStatus:(CPUserSessionStatus)aStatus +{ + if (_status == aStatus) + return; + + _status = aStatus; + + [[CPNotificationCenter defaultCenter] + postNotificationName:CPUserSessionManagerStatusDidChangeNotification + object:self]; + + if (_status != CPUserSessionLoggedInStatus) + [self setUserIdentifier:nil]; +} + +- (CPString)userIdentifier +{ + return _userIdentifier; +} + +- (void)setUserIdentifier:(CPString)anIdentifier +{ + if (_userIdentifier == anIdentifier) + return; + + _userIdentifier = anIdentifier; + + [[CPNotificationCenter defaultCenter] + postNotificationName:CPUserSessionManagerUserIdentifierDidChangeNotification + object:self]; +} + +@end diff --git a/Foundation/CPValue.j b/Foundation/CPValue.j new file mode 100644 index 000000000..7bfd6c5a7 --- /dev/null +++ b/Foundation/CPValue.j @@ -0,0 +1,196 @@ +/* + * CPValue.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPObject.j" +import "CPCoder.j" + +@implementation CPValue : CPObject +{ + JSObject _JSObject; +} + ++ (id)valueWithJSObject:(JSObject)aJSObject +{ + return [[self alloc] initWithJSObject:aJSObject]; +} + +- (id)initWithJSObject:(JSObject)aJSObject +{ + self = [super init]; + + if (self) + _JSObject = aJSObject; + + return self; +} + +- (JSObject)JSObject +{ + return _JSObject; +} + +@end + +var CPValueValueKey = @"CPValueValueKey"; + +@implementation CPValue (CPCoding) + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super init]; + + if (self) + _JSObject = CPJSObjectCreateWithJSON([aCoder decodeObjectForKey:CPValueValueKey]); + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeObject:CPJSObjectCreateJSON(_JSObject) forKey:CPValueValueKey]; +} + +@end + +var _JSONCharacterEncodings = {}; + +_JSONCharacterEncodings['\b'] = "\\b"; +_JSONCharacterEncodings['\t'] = "\\t"; +_JSONCharacterEncodings['\n'] = "\\n"; +_JSONCharacterEncodings['\f'] = "\\f"; +_JSONCharacterEncodings['\r'] = "\\r"; +_JSONCharacterEncodings['"'] = "\\\""; +_JSONCharacterEncodings['\\'] = "\\\\"; + +// FIXME: Workaround for https://trac.280north.com/ticket/16 +var _JSONEncodedCharacters = new RegExp("[\\\"\\\\\\x00-\\x1f\\x7f-\\x9f]", 'g'); + +function CPJSObjectCreateJSON(aJSObject) +{ + // typeof new Number() and new String() gives you "object", + // so valueof in those cases. + var type = typeof aJSObject, + valueOf = aJSObject.valueOf(), + typeValueOf = typeof valueOf; + + if (type != typeValueOf) + { + type = typeValueOf; + aJSObject = valueOf; + } + + switch (type) + { + case "string": // If the string contains no control characters, no quote characters, and no + // backslash characters, then we can safely slap some quotes around it. + // Otherwise we must also replace the offending characters with safe sequences. + + if (!_JSONEncodedCharacters.test(aJSObject)) + return '"' + aJSObject + '"'; + + return '"' + aJSObject.replace(_JSONEncodedCharacters, _CPJSObjectEncodeCharacter) + '"'; + + + case "number": // JSON numbers must be finite. Encode non-finite numbers as null. + return isFinite(aJSObject) ? String(aJSObject) : "null"; + + case "boolean": + case "null": return String(aJSObject); + + case "object": // Due to a specification blunder in ECMAScript, + // typeof null is 'object', so watch out for that case. + + if (!aJSObject) + return "null"; + + // If the object has a toJSON method, call it, and stringify the result. + + if (typeof aJSObject.toJSON === "function") + return CPJSObjectCreateJSON(aJSObject.toJSON()); + + var array = []; + + // If the object is an array. Stringify every element. Use null as a placeholder + // for non-JSON values. + if (aJSObject.slice) + { + var index = 0, + count = aJSObject.length; + + for (; index < count; ++index) + array.push(CPJSObjectCreateJSON(aJSObject[index]) || "null"); + + // Join all of the elements together and wrap them in brackets. + return '[' + array.join(',') + ']'; + } + + + // Otherwise, iterate through all of the keys in the object. + var key = NULL; + + for (key in aJSObject) + { + if (!(typeof key === "string")) + continue; + + var value = CPJSObjectCreateJSON(aJSObject[key]); + + if (value) + array.push(CPJSObjectCreateJSON(key) + ':' + value); + } + + // Join all of the member texts together and wrap them in braces. + return '{' + array.join(',') + '}'; + } +} + +var _CPJSObjectEncodeCharacter = function(aCharacter) +{ + var encoding = _JSONCharacterEncodings[aCharacter]; + + if (encoding) + return encoding; + + encoding = aCharacter.charCodeAt(0); + + return '\\u00' + FLOOR(encoding / 16).toString(16) + (encoding % 16).toString(16); +} + +var _JSONBackslashCharacters = new RegExp("\\\\.", 'g'), + _JSONSimpleValueTokens = new RegExp("\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?", 'g'), + _JSONValidOpenBrackets = new RegExp("(?:^|:|,)(?:\\s*\\[)+", 'g'), + _JSONValidExpression = new RegExp("^[\\],:{}\\s]*$"); + +function CPJSObjectCreateWithJSON(aString) +{ + if (_JSONValidExpression.test(aString.replace(_JSONBackslashCharacters, '@').replace(_JSONSimpleValueTokens, ']').replace(_JSONValidOpenBrackets, ''))) + return eval('(' + aString + ')'); + + return nil; +} + +/* +var _JSONBackslashCharacters = /\\./g, + _JSONSimpleValueTokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + _JSONValidOpenBrackets = /(?:^|:|,)(?:\s*\[)+/g, + _JSONValidExpression = /^[\],:{}\s]*$/; +*/ diff --git a/Foundation/Foundation.j b/Foundation/Foundation.j new file mode 100755 index 000000000..d1e8d97c7 --- /dev/null +++ b/Foundation/Foundation.j @@ -0,0 +1,53 @@ +/* + * Foundation.j + * Foundation + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +import "CPArray.j" +import "CPBundle.j" +import "CPCoder.j" +import "CPData.j" +import "CPDictionary.j" +import "CPEnumerator.j" +import "CPException.j" +import "CPIndexSet.j" +import "CPInvocation.j" +import "CPJSONPConnection.j" +import "CPKeyedArchiver.j" +import "CPKeyedUnarchiver.j" +import "CPKeyValueCoding.j" +import "CPLog.j" +import "CPNotification.j" +import "CPNotificationCenter.j" +import "CPNull.j" +import "CPNumber.j" +import "CPObject.j" +import "CPObjJRuntime.j" +import "CPPropertyListSerialization.j" +import "CPRange.j" +import "CPRunLoop.j" +import "CPSortDescriptor.j" +import "CPString.j" +import "CPUndoManager.j" +import "CPURLConnection.j" +import "CPURLRequest.j" +import "CPURLResponse.j" +import "CPUserSessionManager.j" +import "CPValue.j" diff --git a/Foundation/Foundation.steam b/Foundation/Foundation.steam new file mode 100644 index 000000000..05f157698 --- /dev/null +++ b/Foundation/Foundation.steam @@ -0,0 +1,40 @@ + + + + + name + Foundation + Targets + + + name + Foundation + + + Configurations + + + name + Debug + Settings + + PREPROCESS + + FLAGS + -DDEBUG + + + + name + Release + Settings + + PREPROCESS + + PREINTERPRET + + + + + + diff --git a/Foundation/Info.plist b/Foundation/Info.plist new file mode 100644 index 000000000..c16e019ed --- /dev/null +++ b/Foundation/Info.plist @@ -0,0 +1,14 @@ + + + + + CPBundleIdentifier + com.280n.Foundation + CPBundleInfoDictionaryVersion + 6.0 + CPBundleName + Foundation + CPBundlePackageType + FMWK + + diff --git a/Foundation/Resources/log.css b/Foundation/Resources/log.css new file mode 100644 index 000000000..8a4ed37bc --- /dev/null +++ b/Foundation/Resources/log.css @@ -0,0 +1,72 @@ +body { + font: 10px Monaco, Courier, "Courier New", monospace, mono; + padding-top: 15px; +} + +div > .fatal, div > .error, div > .warn, div > .info, div > .debug, div > .trace { + display: none; + overflow: hidden; + white-space: pre; + padding: 0px 5px 0px 5px; + margin-top: 2px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} + +div[wrap="yes"] > div { + white-space: normal; +} + +.fatal { background-color: #ffb2b3; } +.error { background-color: #ffe2b2; } +.warn { background-color: #fdffb2; } +.info { background-color: #e4ffb2; } +.debug { background-color: #a0e5a0; } +.trace { background-color: #99b9ff; } + +.enfatal .fatal, .enerror .error, .enwarn .warn, .eninfo .info, .endebug .debug, .entrace .trace { display: block; } + +div#header { + background-color: rgba(240,240,240,0.82); + position: fixed; + top: 0px; + left: 0px; + width: 100%; + border-bottom: 1px solid rgba(0,0,0,0.33); + text-align: center; + /*opacity: 0.2;*/ +} +/* +div#header:hover { + opacity: 1.0; +} +*/ +ul#enablers { + display: inline-block; + margin: 1px 15px 0 15px; + padding: 2px 0 2px 0; +} + +ul#enablers li { + display: inline; + padding: 0px 5px 0px 5px; + margin-left: 4px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} + +[enabled="no"] { + opacity: 0.25; +} + +ul#options { + display: inline-block; + margin: 0 15px 0px 15px; + padding: 0 0px; +} + +ul#options li { + margin: 0 0 0 0; + padding: 0 0 0 0; + display: inline; +} \ No newline at end of file diff --git a/Foundation/build.xml b/Foundation/build.xml new file mode 100644 index 000000000..d72125d16 --- /dev/null +++ b/Foundation/build.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..9ef3d701d --- /dev/null +++ b/LICENSE @@ -0,0 +1,503 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + diff --git a/Objective-J/Object.j b/Objective-J/Object.j new file mode 100644 index 000000000..0e96b94b2 --- /dev/null +++ b/Objective-J/Object.j @@ -0,0 +1,41 @@ +/* + * Object.j + * Objective-J + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +@implementation Object +{ + Class isa; +} + ++ (void)initialize +{ +} + +- (void)doesNotRecognizeSelector:(SEL)aSelector +{ +} + +- (id)forwardSelector:(SEL)selector arguments:(void *)args +{ + return nil; +} + +@end diff --git a/Objective-J/build.xml b/Objective-J/build.xml new file mode 100644 index 000000000..b4ec11492 --- /dev/null +++ b/Objective-J/build.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Objective-J/constants.js b/Objective-J/constants.js new file mode 100644 index 000000000..c0b97bd5f --- /dev/null +++ b/Objective-J/constants.js @@ -0,0 +1,101 @@ +/* + * constants.js + * Objective-J + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + // Objective-J Constants +var NO = false, + YES = true, + + nil = null, + Nil = null, + NULL = null, + + // In IE, it is much faster to call these global methods than their Math. equivalents. + // We var them in order to make them DontDelete globals, which are known to be much faster in Safari. + ABS = Math.abs, + + ASIN = Math.asin, + ACOS = Math.acos, + ATAN = Math.atan, + ATAN2 = Math.atan2, + + SIN = Math.sin, + COS = Math.cos, + TAN = Math.tan, + + EXP = Math.exp, + POW = Math.pow, + + CEIL = Math.ceil, + FLOOR = Math.floor, + ROUND = Math.round, + + MIN = Math.min, + MAX = Math.max, + + RAND = Math.random, + SQRT = Math.sqrt, + + E = Math.E, + + LN2 = Math.LN2, + LN10 = Math.LN10, + LOG2E = Math.LOG2E, + LOG10E = Math.LOG10E, + + PI = Math.PI, + PI2 = Math.PI * 2.0, + PI_2 = Math.PI / 2.0, + + SQRT1_2 = Math.SQRT1_2, + SQRT2 = Math.SQRT2; + +// Detecting Browser Features +#define ACTIVE_X window.ActiveXObject +#define OPERA window.opera +#define NATIVE_XMLHTTPREQUEST window.XMLHttpRequest + +#define IF(FEATURE) if (FEATURE) { +#define ELSE } else { +#define ELIF(FEATURE) } else if (FEATURE) { +#define ENDIF } + +// +// FIXME: Should we just override normal alerts? +var objj_continue_alerting = NO; + +function objj_alert(aString) +{ + if (!objj_continue_alerting) + return; + + objj_continue_alerting = confirm(aString + "\n\nClick cancel to prevent further alerts."); +} + +function objj_fprintf(stream, string) +{ + stream(string); +} + +function objj_printf(string) +{ + objj_fprintf(alert, string); +} diff --git a/Objective-J/dictionary.js b/Objective-J/dictionary.js new file mode 100644 index 000000000..80fc82f2f --- /dev/null +++ b/Objective-J/dictionary.js @@ -0,0 +1,119 @@ +/* + * dictionary.js + * Objective-J + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +function objj_dictionary() +{ + this.keys = []; + this.count = 0; + this.buckets = {}; + this.__address = _objj_generateObjectHash(); +} + +function dictionary_containsKey(aDictionary, aKey) +{ + return aDictionary.buckets[aKey] != NULL; +} + +#define dictionary_containsKey(aDictionary, aKey) ((aDictionary).buckets[aKey] != NULL) + +function dictionary_getCount(aDictionary) +{ + return aDictionary.count; +} + +#define dictionary_getCount(aDictionary) ((aDictionary).count) + +function dictionary_getValue(aDictionary, aKey) +{ + return aDictionary.buckets[aKey]; +} + +#define dictionary_getValue(aDictionary, aKey) ((aDictionary).buckets[aKey]) + +function dictionary_setValue(aDictionary, aKey, aValue) +{ + if (aDictionary.buckets[aKey] == NULL) + { + aDictionary.keys.push(aKey); + ++aDictionary.count; + } + + if ((aDictionary.buckets[aKey] = aValue) == NULL) + --aDictionary.count; +} + +#define dictionary_setValue(aDictionary, aKey, aValue)\ +{\ + if ((aDictionary).buckets[aKey] == NULL)\ + {\ + (aDictionary).keys.push(aKey);\ + ++(aDictionary).count;\ + }\ +\ + if (((aDictionary).buckets[aKey] = aValue) == NULL) \ + --(aDictionary).count;\ +} + + +function dictionary_removeValue(aDictionary, aKey) +{ + if (aDictionary.buckets[aKey] == NULL) + return; + + --aDictionary.count; + if (aDictionary.keys.indexOf) + aDictionary.keys.splice(aDictionary.keys.indexOf(aKey), 1); + else + { + var keys = aDictionary.keys, + index = 0, + count = keys.length; + + for (; index < count; ++index) + if (keys[index] == aKey) + { + keys.splice(index, 1); + break; + } + } + + delete aDictionary.buckets[aKey]; +} + +function dictionary_replaceValue(aDictionary, aKey, aValue) +{ + if (aDictionary[aKey] == NULL) + return; + +// FIXME: Implement +// aDictionary.keys.splice(aDictionary.keys.indexOf(aKey), 1); +} + +function dictionary_description(aDictionary) +{ + str = "{ "; + for ( x in aDictionary.buckets) + str += x + ":" + aDictionary.buckets[x] + ","; + str += " }"; + + return str; +} diff --git a/Objective-J/evaluate.js b/Objective-J/evaluate.js new file mode 100644 index 000000000..c325dc9c1 --- /dev/null +++ b/Objective-J/evaluate.js @@ -0,0 +1,239 @@ +/* + * evaluate.js + * Objective-J + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +var objj_included_files = { }; + +var FRAGMENT_CODE = 1, + + FRAGMENT_FILE = 1 << 2, + FRAGMENT_LOCAL = 1 << 3, + FRAGMENT_IMPORT = 1 << 4; + +function objj_fragment() +{ + this.info = NULL; + this.type = 0; + this.context = NULL; + this.bundle = NULL; + this.file = NULL; +} + +#define EVALUATION_PERIOD 3000 + +function objj_context() +{ + this.fragments = []; + this.scheduled = NO; + this.blocked = NO; +} + +#define SET_CONTEXT(aFragment, aContext) aFragment.context = aContext +#define GET_CONTEXT(aFragment) aFragment.context + +#define SET_TYPE(aFragment, aType) aFragment.type = (aType) +#define GET_TYPE(aFragment) aFragment.type + +#define GET_CODE(aFragment) aFragment.info +#define SET_CODE(aFragment, aCode) aFragment.info = (aCode) + +#define GET_PATH(aFragment) aFragment.info +#define SET_PATH(aFragment, aPath) aFragment.info = aPath + +#define GET_BUNDLE(aFragment) aFragment.bundle +#define SET_BUNDLE(aFragment, aBundle) aFragment.bundle = aBundle + +#define GET_FILE(aFragment) aFragment.file +#define SET_FILE(aFragment, aFile) aFragment.file = aFile + +#define IS_FILE(aFragment) (aFragment.type & FRAGMENT_FILE) +#define IS_LOCAL(aFragment) (aFragment.type & FRAGMENT_LOCAL) +#define IS_IMPORT(aFragment) (aFragment.type & FRAGMENT_IMPORT) + +function fragment_create_code(aCode, aBundle, aFile) +{ + var fragment = new objj_fragment(); + + SET_TYPE(fragment, FRAGMENT_CODE); + SET_CODE(fragment, aCode); + SET_BUNDLE(fragment, aBundle); + SET_FILE(fragment, aFile); + + return fragment; +} + +function fragment_create_file(aPath, aBundle, isLocal, isImport, aFile) +{ + var fragment = new objj_fragment(); + + SET_TYPE(fragment, FRAGMENT_FILE | (FRAGMENT_LOCAL * isLocal) | (FRAGMENT_IMPORT * isImport)); + SET_PATH(fragment, aPath); + SET_BUNDLE(fragment, aBundle); + SET_FILE(fragment, aFile); + + return fragment; +} + +objj_context.prototype.evaluate = function() +{ + this.scheduled = NO; + + // If we're blocked by IO, then just reschedule. + if (this.blocked) + return this.schedule(); + + // If not, begin the evaluation loop. + var sleep = NO, + start = new Date(), + fragments = this.fragments; + + while (!sleep && fragments.length) + { + var fragment = fragments.pop(); + + if (IS_FILE(fragment)) + sleep = fragment_evaluate_file(fragment); + else + sleep = fragment_evaluate_code(fragment); + + // Sleep evaluation if we've been at it too long to avoid + // unresponsive script errors. + sleep = sleep || ((new Date() - start) > EVALUATION_PERIOD); + } + + if (sleep) + this.schedule(); + + else if (this.didCompleteCallback) + this.didCompleteCallback(this); +} + +objj_context.prototype.schedule = function() +{ + if (this.scheduled) + return; + + this.scheduled = YES; + + var context = this; + + window.setTimeout(function () { context.evaluate(); }, 0); +} + +objj_context.prototype.pushFragment = function(aFragment) +{ + SET_CONTEXT(aFragment, this); + + this.fragments.push(aFragment); +} + +function fragment_evaluate_code(aFragment) +{ + var compiled; + + OBJJ_CURRENT_BUNDLE = GET_BUNDLE(aFragment); + + try + { + compiled = new Function(GET_CODE(aFragment)); + } + catch(anException) + { + objj_exception_report(anException, GET_FILE(aFragment)); + } + + try + { + compiled(); + } + catch(anException) + { + objj_exception_report(anException, GET_FILE(aFragment)); + } + + return NO; +} + +function fragment_evaluate_file(aFragment) +{ + var context = GET_CONTEXT(aFragment), + requiresSleep = YES; + + // Make us IO Blocked until we receive the file. + context.blocked = YES; + + objj_request_file(GET_PATH(aFragment), IS_LOCAL(aFragment), function(aFile) + { + // Use the captured value from the closure. If objj_request_file + // returns immediately, then this will cause us to avoid breaking, + // but if it doesn't, then this will have no effect. + requiresSleep = NO; + + // We've received the file, so no longer block execution. + context.blocked = NO; + + // FIXME: We need to actually support this, and handle it better + // as well. + if (aFile == OBJJ_NO_FILE) + objj_alert("uh oh!"); + + // If this file has already been included, skip it and bail. + if (objj_included_files[aFile.path]) + return; + + // If not, then mark it as included, for future imports. + objj_included_files[aFile.path] = YES; + + // Grab the file's fragments if it has them, or preprocess it if not. + var fragments = aFile.fragments ? aFile.fragments : objj_preprocess(aFile.contents, aFile.bundle, aFile), + count = fragments.length, + directory = aFile.path.substr(0, aFile.path.lastIndexOf('/') + 1); + + // Put the individual fragments at the head of the evaluation + // stack to be evaluated. + while (count--) + { + var fragment = fragments[count]; + + if (IS_FILE(fragment)) + { + if (IS_LOCAL(fragment)) + SET_PATH(fragment, directory + GET_PATH(fragment)); + + objj_request_file(GET_PATH(fragment), IS_LOCAL(fragment), NULL); + } + + context.pushFragment(fragment); + } + }); + + return requiresSleep; +} + +function objj_import(aPath, isLocal, didCompleteCallback) +{ + var context = new objj_context(); + + context.didCompleteCallback = didCompleteCallback; + context.pushFragment(fragment_create_file(aPath, isLocal, YES)); + + context.evaluate(); +} diff --git a/Objective-J/exception.js b/Objective-J/exception.js new file mode 100644 index 000000000..df317d495 --- /dev/null +++ b/Objective-J/exception.js @@ -0,0 +1,66 @@ +/* + * exception.js + * Objective-J + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +var OBJJ_EXCEPTION_OUTPUT_STREAM = NULL; + +function objj_exception(aName, aReason, aUserInfo) +{ + this.name = aName; + this.reason = aReason; + this.userInfo = aUserInfo; + this.__address = _objj_generateObjectHash(); +} + +objj_exception.prototype.toString = function() +{ + return this.reason; +} + +function objj_exception_throw(anException) +{ + throw anException; +} + +function objj_exception_report(anException, aSourceFile) +{ + objj_fprintf(OBJJ_EXCEPTION_OUTPUT_STREAM, aSourceFile.path + "\n" + anException); + + throw anException; +} + +function objj_exception_setOutputStream(aStream) +{ + OBJJ_EXCEPTION_OUTPUT_STREAM = aStream; +} + +#if COMPILER +importPackage(java.lang); + +objj_exception_setOutputStream(function (aString) { System.out.println(aString) } ); +#elif DEBUG +if (window.console && window.console.error) + objj_exception_setOutputStream(function (aString) { console.error(aString) } ); +else + objj_exception_setOutputStream(alert); +#else +objj_exception_setOutputStream(function(aString) { }); +#endif diff --git a/Objective-J/file.js b/Objective-J/file.js new file mode 100644 index 000000000..d9b268c03 --- /dev/null +++ b/Objective-J/file.js @@ -0,0 +1,533 @@ +/* + * file.js + * Objective-J + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Notes: requests may return immediately (i.e. in IE when a file has been cached). Don't assume +// One line of code thus follows another, it may call the callback first! + +// FIXME: If we ever have bundles that replace only some files, we will definitely run into problems. +// Look inside bundleResponseCallback. + + +#define DIRECTORY(aPath) (aPath).substr(0, (aPath).lastIndexOf('/') + 1) + +OBJJFileNotFoundException = "OBJJFileNotFoundException"; +OBJJExecutableNotFoundException = "OBJJExecutableNotFoundException"; + +var objj_files = { }, + objj_bundles = { }, + objj_bundlesForClass = { }, + objj_searches = { }; + +var OBJJ_NO_FILE = {}, + OBJJ_INCLUDE_PATHS = ["Frameworks", "SomethingElse"]; + +var OBJJ_BASE_URI = ""; + +IF (OPERA) + +var DOMBaseElement = document.getElementsByTagName("base")[0]; + +if (DOMBaseElement) + OBJJ_BASE_URI = DIRECTORY(DOMBaseElement.getAttribute('href')); + +ENDIF + +function objj_file() +{ + this.path = NULL; + this.bundle = NULL; + + this.included = NO; + + this.contents = NULL; + this.fragments = NULL; +} + +function objj_bundle() +{ + this.path = NULL; + this.info = NULL; + + this.__address = _objj_generateObjectHash(); +} + +function objj_getBundleWithPath(aPath) +{ + return objj_bundles[aPath]; +} + +function objj_bundleForClass(aClass) +{ + return objj_bundlesForClass[aClass.name]; +} + +function objj_addClassForBundle(aClass, aBundle) +{ + objj_bundlesForClass[aClass.name] = aBundle; +} + +function objj_request_file(aFilePath, shouldSearchLocally, aCallback) +{ + new objj_search(aFilePath, shouldSearchLocally, aCallback).attemptNextSearchPath(); +} + +var objj_search = function(aFilePath, shouldSearchLocally, aCallback) +{ + this.filePath = aFilePath; + + this.bundle = NULL; + this.bundleObservers = []; + + this.searchPath = NULL; + this.searchedPaths = []; + this.includePathsIndex = shouldSearchLocally ? -1 : 0; + + this.searchRequest = NULL; + + this.didCompleteCallback = aCallback; +} + +objj_search.prototype.nextSearchPath = function() +{ + // FIXME: Path searching should be more complex (go up directories, etc). + var path = objj_standardize_path((this.includePathsIndex == -1 ? "" : OBJJ_INCLUDE_PATHS[this.includePathsIndex] + '/') + this.filePath); + + ++this.includePathsIndex; + + return path; +} + +objj_search.prototype.attemptNextSearchPath = function() +{ + var searchPath = this.nextSearchPath(), + file = objj_files[searchPath]; + + objj_alert("Will attempt to find " + this.filePath + " at " + searchPath); + + // If a file for this search path already exists, then it has already been downloaded. + // If there is a callback, we can just call it, if not, we can simply return. + if (file) + { + objj_alert("The file request at " + this.filePath + " has already been downloaded at " + searchPath); + if (this.didCompleteCallback) + this.didCompleteCallback(file); + + return; + } + + var existingSearch = objj_searches[searchPath]; + + // If there is already an ongoing search for this search path, then we can let it find + // the file for us. Make sure to assign it our callback, if we have one, since only + // one search can have a callback at a time. + if (existingSearch) + { + if (this.didCompleteCallback) + existingSearch.didCompleteCallback = this.didCompleteCallback; + + return; + } + + // At this point we have a legitimate search, so we should take note of this search path + // in our search paths. + this.searchedPaths.push(this.searchPath = searchPath); + + // Before we kick off our ajax requests, see whether this directory already has + // a bundle associated with it. + var infoPath = objj_standardize_path(DIRECTORY(searchPath) + "Info.plist") + bundle = objj_bundles[infoPath]; + + // If there is, then simply look for the file in question. + if (bundle) + { + this.bundle = bundle; + this.request(searchPath, this.didReceiveSearchResponse); + } + else + { + // If there isn't a bundle associated with this directory, then we also have to + // search for an Info.plist. + var existingBundleSearch = objj_searches[infoPath]; + + // Again, if a search already exists for this bundle, then add ourselves to the list + // of observers for when this bundle is either found or created. + if (existingBundleSearch) + { + --this.includePathsIndex; + this.searchedPaths.pop(); + if (this.searchedPaths.length) + this.searchPath = this.searchedPaths[this.searchedPaths.length - 1]; + else + this.searchPath = NULL; + + existingBundleSearch.bundleObservers.push(this); + return; + } + // If not, then look for it. + else + { + this.bundleObservers.push(this); + this.request(infoPath, this.didReceiveBundleResponse); + + // Requests may return immediately, so by this point, we may have already gotten the bundle and replaced the file. + if (!this.searchReplaced) + this.searchRequest = this.request(searchPath, this.didReceiveSearchResponse); + } + } +} + +IF (ACTIVE_X) + +objj_search.responseCallbackLock = NO; +objj_search.responseCallbackQueue = []; + +objj_search.removeResponseCallbackForFilePath = function(aFilePath) +{ + var queue = objj_search.responseCallbackQueue, + index = queue.length; + + while (index--) + if (queue[index][3] == aFilePath) + { + queue.splice(index, 1); + return; + } +} + +objj_search.serializeResponseCallback = function(aMethod, aSearch, aResponse, aFilePath) +{ + var queue = objj_search.responseCallbackQueue; + + queue.push([aMethod, aSearch, aResponse, aFilePath]); + + if (objj_search.responseCallbackLock) + return; + objj_search.responseCallbackLock = YES; + + while (queue.length) + { + var callback = queue[0]; + queue.splice(0, 1); + + callback[0].apply(callback[1], [callback[2]]); + } + + objj_search.responseCallbackLock = NO; +} + +ENDIF + +objj_search.prototype.request = function(aFilePath, aMethod) +{ + var search = this, + isPlist = aFilePath.substr(aFilePath.length - 6, 6) == ".plist", + request = objj_request_xmlhttp(), + response = objj_response_xmlhttp(); + + response.filePath = aFilePath; + + request.onreadystatechange = function() + { + if (request.readyState == 4) + { + if (response.success = (request.status != 404 && request.responseText && request.responseText.length) ? YES : NO) + { + if (window.files_total) + { + if (!window.files_loaded) + window.files_loaded = 0; + + window.files_loaded += request.responseText.length; + + if (window.update_progress) + window.update_progress(window.files_loaded / window.files_total); + } + + if (isPlist) + response.xml = objj_standardize_xml(request); + else + response.text = request.responseText; + } + + if (ACTIVE_X) + objj_search.serializeResponseCallback(aMethod, search, response, aFilePath); + else + aMethod.apply(search, [response]); + } + } + + objj_searches[aFilePath] = this; + + if (request.overrideMimeType && isPlist) + request.overrideMimeType('text/xml'); + + if (OPERA && aFilePath.charAt(0) != '/') + aFilePath = OBJJ_BASE_URI + aFilePath; + + try + { + request.open("GET", aFilePath, YES); + request.send(""); + } + catch (anException) + { + response.success = NO; + + if (ACTIVE_X) + objj_search.serializeResponseCallback(aMethod, search, response, aFilePath); + else + aMethod.apply(search, [response]); + } + + return request; +} + +objj_search.prototype.didReceiveSearchResponse = function(aResponse) +{ + // If we do not have a bundle yet, we cannot appropriately + // handle this response, so wait. + if (!this.bundle) + { + this.cachedSearchResponse = aResponse; + return; + } + + if (aResponse.success) + { + file = new objj_file(); + + file.path = aResponse.filePath; + file.bundle = this.bundle + file.contents = aResponse.text; + + this.complete(file); + } + else if (this.includePathsIndex < OBJJ_INCLUDE_PATHS.length) + { + // Clear out the bundle since it will no longer be valid. + // FIXME: FIXME: FIXME: WARNING: Wouldn't it be cleaner to just always do this in attemptNextSearchPath? + this.bundle = NULL; + this.attemptNextSearchPath(); + } + else + objj_exception_throw(new objj_exception(OBJJFileNotFoundException, "*** Could not locate file named \"" + this.filePath + "\" in search paths.")); +} + +objj_search.prototype.didReceiveBundleResponse = function(aResponse) +{ + var bundle = new objj_bundle(); + + bundle.path = aResponse.filePath; + + if (aResponse.success) + bundle.info = CPPropertyListCreateFromXMLData(aResponse.xml); + else + bundle.info = new objj_dictionary(); + + objj_bundles[aResponse.filePath] = bundle; + + var executablePath = dictionary_getValue(bundle.info, "CPBundleExecutable"); + + if (executablePath) + { + this.request(DIRECTORY(aResponse.filePath) + executablePath, this.didReceiveExecutableResponse); + + // FIXME: Is this the right approach? + // Request the compiled file regardless of whether our current inquiry + var directory = DIRECTORY(aResponse.filePath), + replacedFiles = dictionary_getValue(bundle.info, "CPBundleReplacedFiles"), + index = 0, + count = replacedFiles.length; + + for (; index < count; ++index) + { + // Halt any forward searches of these files from taking place. + objj_searches[directory + replacedFiles[index]] = this; + + if (directory + replacedFiles[index] == this.searchPath) + { + this.searchReplaced = YES; + + if (!this.cachedSearchResponse && this.searchRequest) + this.searchRequest.abort(); + + if (ACTIVE_X) + objj_search.removeResponseCallbackForFilePath(this.searchPath); + } + } + } + this.bundle = bundle; + var observers = this.bundleObservers, + index = 0, + count = observers.length; + + for(; index < count; ++index) + { + var observer = observers[index]; + + // Force the observer to just attempt the path all over again, + // since it may have been replaced by the executable. + // FIXME: we should be just reattempting the ones that collided. + if (observer != this) + observer.attemptNextSearchPath(); + + // If we have a cached response and the search has not been + // replaced by the executable, then let it proceed. + else if (this.cachedSearchResponse && !this.searchReplaced) + this.didReceiveSearchResponse(this.cachedSearchResponse); + } + + this.bundleObservers = []; +} + +objj_search.prototype.didReceiveExecutableResponse = function(aResponse) +{ + if (!aResponse.success) + objj_exception_throw(new objj_exception(OBJJExecutableNotFoundException, "*** The specified executable could not be located at \"" + this.filePath + "\".")); + + var files = objj_decompile(aResponse.text, this.bundle), + index = 0, + count = files.length, + length = this.filePath.length; + + for (; index < count; ++index) + { + var file = files[index], + path = file.path; + + if (this.filePath == path.substr(path.length - length)) + this.complete(file); + else + objj_files[path] = file; + } +} + +objj_search.prototype.complete = function(aFile) +{ + var index = 0, + count = this.searchedPaths.length; + + for (; index < count; ++index) + { + objj_files[this.searchedPaths[index]] = aFile; + //FIXME: uncomment this: + //delete objj_inquiries[anInquiry.searchedPaths[index]]; + } + + if (this.didCompleteCallback) + this.didCompleteCallback(aFile); +} + +// objj_standardize_path +// +// Standardizes the input path by removing extrenenous components and resolving +// references to parent directories. + +function objj_standardize_path(aPath) +{ + if (aPath.indexOf("/./") != -1 && aPath.indexOf("//") != -1 && aPath.indexOf("/../") != -1) + return aPath; + + var index = 0, + components = aPath.split('/'); + + for(;index < components.length; ++index) + if(components[index] == "..") + { + components.splice(index - 1, 2); + index -= 2; + } + else if(index != 0 && !components[index].length || components[index] == '.' || components[index] == "..") + components.splice(index--, 1); + + return components.join('/'); +} + +IF (ACTIVE_X) + +objj_standardize_xml = function(aRequest) +{ + var XMLData = new ActiveXObject("Microsoft.XMLDOM"); + XMLData.loadXML(aRequest.responseText.substr(aRequest.responseText.indexOf(".dtd\">") + 6)); + + return XMLData; +} + +ELSE + +objj_standardize_xml = function(aRequest) +{ + return aRequest.responseXML; +} + +ENDIF + +function objj_response_xmlhttp() +{ + return new Object; +} + +// objj_request_xmlhttp() +// +// To be used as a browser-independent implementation of XMLHttpRequest. +// Currently known to support Safari, Firefox, IE 6/7, and Opera. +// +// Throws a primitive exception if XMLHttpRequests are not supported on +// the given browser. + +IF (NATIVE_XMLHTTPREQUEST) + +objj_request_xmlhttp = function() +{ + return new XMLHttpRequest(); +} + +ELIF (ACTIVE_X) + +// DON'T try 4.0 and 5.0. Should we be trying anything other than 3.0 and 6.0? +// http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx +var MSXML_XMLHTTP_OBJECTS = [ "Microsoft.XMLHTTP", "Msxml2.XMLHTTP", "Msxml2.XMLHTTP.3.0", "Msxml2.XMLHTTP.6.0" ],//"Msxml2.XMLHTTP.4.0", "Msxml2.XMLHTTP.5.0" ], + index = MSXML_XMLHTTP_OBJECTS.length; + +while (index--) +{ + try + { + new ActiveXObject(MSXML_XMLHTTP_OBJECTS[index]); + break; + } + catch (anException) + { + } +} + +var MSXML_XMLHTTP = MSXML_XMLHTTP_OBJECTS[index]; + +delete index; +delete MSXML_XMLHTTP_OBJECTS; + +objj_request_xmlhttp = function() +{ + return new ActiveXObject(MSXML_XMLHTTP); +} + +ENDIF diff --git a/Objective-J/license.txt b/Objective-J/license.txt new file mode 100644 index 000000000..40190756c --- /dev/null +++ b/Objective-J/license.txt @@ -0,0 +1,22 @@ +/* + * Objective-J.js + * Objective-J + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + diff --git a/Objective-J/plist.js b/Objective-J/plist.js new file mode 100644 index 000000000..d03ede527 --- /dev/null +++ b/Objective-J/plist.js @@ -0,0 +1,661 @@ +/* + * plist.js + * Objective-J + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +kCFPropertyListOpenStepFormat = 1; +kCFPropertyListXMLFormat_v1_0 = 100; +kCFPropertyListBinaryFormat_v1_0 = 200; +kCFPropertyList280NorthFormat_v1_0 = -1000; + +OBJJPlistParseException = "OBJJPlistParseException"; + +var kCFPropertyList280NorthMagicNumber = "280NPLIST"; + +/*var BASE64_TABLE = [ + "A", "B", "C", "D", "E", "F", "G", "H", + "I", "J", "K", "L", "M", "N", "O", "P", + "Q", "R", "S", "T", "U", "V", "W", "X", + "Y", "Z", "a", "b", "c", "d", "e", "f", + "g", "h", "i", "j", "k", "l", "m", "n", + "o", "p", "q", "r", "s", "t", "u", "v", + "w", "x", "y", "z", "0", "1", "2", "3", + "4", "5", "6", "7", "8", "9", "+", "/" +];*/ + +function objj_data() +{ + this.string = ""; + this._plistObject = NULL; + this.bytes = NULL; + this.base64 = NULL; +} + +/*function data_setBytes(data, bytes) +{ + this.bytes = bytes; + this.base64 = NULL; +} + +function data_getBytes(data) +{ + return this.bytes; +} + +function data_getBase64String() +{ + if (!this.base64) + { + this.base64 = ""; + + var offset = 0, + bytes = this.bytes, + length = bytes.length; + + uint24 = this.bytes[offset] << 16 | this.bytes[offset + 1] << 8 | this.bytes[offset + 2]; + this.base64 += BASE64_TABLE[ ( uint24 & 0xFC0000 ) >> 18 ]); + this.base64 += BASE64_TABLE[ ( uint24 & 0x03F000 ) >> 12 ]); + this.base64 += BASE64_TABLE[ ( uint24 & 0x0FC0 ) >> 6 ]); + this.base64 += BASE64_TABLE[ ( uint24 & 0x3F ) ]); + + for (;offset < length; ++offset) + { + this.base64 = BASE64_TABLE[bytes[offset] >> 2]; + this.base64 = BASE64_TABLE[((bytes[offset] & 3) << 4) | (bytes[++offset] >> 4)]; + this.base64 = offset < length ? "=" : BASE64_TABLE[((bytes[offset] & 15) << 2) | (bytes[++offset] >> 6)]; + this.base64 = offset < length ? "=" : BASE64_TABLE[bytes[offset] & 63]; + } + } + + return this.base64; +}*/ + +var objj_markedStream = function(aString) +{ + var index = aString.indexOf(';'); + + // Grab the magic number. + this._magicNumber = aString.substr(0, index); + + this._location = aString.indexOf(';', ++index); + + // Grab the version number. + this._version = aString.substring(index, this._location++); + this._string = aString; +} + +objj_markedStream.prototype.magicNumber = function() +{ + return this._magicNumber; +} + +objj_markedStream.prototype.version = function() +{ + return this._version; +} + +objj_markedStream.prototype.getMarker = function() +{ + var string = this._string, + location = this._location; + + if (location >= string.length) + return NULL; + + var next = string.indexOf(';', location); + + if (next < 0) + return NULL; + + var marker = string.substring(location, next); + + this._location = next + 1; + + return marker; +} + +objj_markedStream.prototype.getString = function() +{ + var string = this._string, + location = this._location; + + if (location >= string.length) + return NULL; + + var next = string.indexOf(';', location); + + if (next < 0) + return NULL; + + var size = parseInt(string.substring(location, next)), + text = string.substr(next + 1, size); + + this._location = next + 1 + size; + + return text; +} + +// + +function CPPropertyListCreateData(aPlistObject, aFormat) +{ + if (aFormat == kCFPropertyListXMLFormat_v1_0) + return CPPropertyListCreateXMLData(aPlistObject); + + if (aFormat == kCFPropertyList280NorthFormat_v1_0) + return CPPropertyListCreate280NorthData(aPlistObject); + + return NULL; +} + +function CPPropertyListCreateFromData(aData, aFormat) +{ + if (!aFormat) + { + // Attempt to guess the format. + if (aData instanceof objj_data) + { + var string = aData.string ? aData.string : objj_msgSend(aData, "string"); + + if (string.substr(0, kCFPropertyList280NorthMagicNumber.length) == kCFPropertyList280NorthMagicNumber) + aFormat = kCFPropertyList280NorthFormat_v1_0; + else + aFormat = kCFPropertyListXMLFormat_v1_0; + } + else + aFormat = kCFPropertyListXMLFormat_v1_0; + } + + if (aFormat == kCFPropertyListXMLFormat_v1_0) + return CPPropertyListCreateFromXMLData(aData); + + if (aFormat == kCFPropertyList280NorthFormat_v1_0) + return CPPropertyListCreateFrom280NorthData(aData); + + return NULL; +} + +var _CPPropertyListSerializeObject = function(aPlist, serializers) +{ + var type = typeof aPlist, + valueOf = aPlist.valueOf(), + typeValueOf = typeof valueOf; + + if (type != typeValueOf) + { + type = typeValueOf; + aPlist = valueOf; + } + + if (type == "string") + return serializers["string"](aPlist, serializers); + + else if (aPlist === true || aPlist === false) + return serializers["boolean"](aPlist, serializers); + + else if (type == "number") + { + var integer = FLOOR(aPlist); + + if (integer == aPlist) + return serializers["integer"](aPlist, serializers); + else + return serializers["real"](aPlist, serializers); + } + + else if (aPlist.slice) + return serializers["array"](aPlist, serializers); + + else + return serializers["dictionary"](aPlist, serializers); +} + +// XML Format 1.0 + +var XML_XML = "xml", + XML_DOCUMENT = "#document", + + PLIST_PLIST = "plist", + PLIST_KEY = "key", + PLIST_DICTIONARY = "dict", + PLIST_ARRAY = "array", + PLIST_STRING = "string", + PLIST_BOOLEAN_TRUE = "true", + PLIST_BOOLEAN_FALSE = "false", + PLIST_NUMBER_REAL = "real", + PLIST_NUMBER_INTEGER = "integer"; + +#if RHINO + +#define NODE_NAME(anXMLNode) (String(anXMLNode.getNodeName())) +#define NODE_TYPE(anXMLNode) (anXMLNode.getNodeType()) +#define NODE_VALUE(anXMLNode) (String(anXMLNode.getNodeValue())) +#define FIRST_CHILD(anXMLNode) (anXMLNode.getFirstChild()) +#define NEXT_SIBLING(anXMLNode) (anXMLNode.getNextSibling()) +#define PARENT_NODE(anXMLNode) (anXMLNode.getParentNode()) +#define DOCUMENT_ELEMENT(aDocument) (aDocument.getDocumentElement()) + +#else + +#define NODE_NAME(anXMLNode) (anXMLNode.nodeName) +#define NODE_TYPE(anXMLNode) (anXMLNode.nodeType) +#define NODE_VALUE(anXMLNode) (anXMLNode.nodeValue) +#define FIRST_CHILD(anXMLNode) (anXMLNode.firstChild) +#define NEXT_SIBLING(anXMLNode) (anXMLNode.nextSibling) +#define PARENT_NODE(anXMLNode) (anXMLNode.parentNode) +#define DOCUMENT_ELEMENT(aDocument) (aDocument.documentElement) + +#endif + +#define IS_OF_TYPE(anXMLNode, aType) (NODE_NAME(anXMLNode) == aType) +#define IS_PLIST(anXMLNode) IS_OF_TYPE(anXMLNode, PLIST_PLIST) + +#define IS_WHITESPACE(anXMLNode) (NODE_TYPE(anXMLNode) == 8 || NODE_TYPE(anXMLNode) == 3) +#define IS_DOCUMENTTYPE(anXMLNode) (NODE_TYPE(anXMLNode) == 10) + +#define PLIST_NEXT_SIBLING(anXMLNode) while ((anXMLNode = NEXT_SIBLING(anXMLNode)) && IS_WHITESPACE(anXMLNode)) ; +#define PLIST_FIRST_CHILD(anXMLNode) anXMLNode = FIRST_CHILD(anXMLNode); if (anXMLNode != NULL && IS_WHITESPACE(anXMLNode)) PLIST_NEXT_SIBLING(anXMLNode) + +// FIXME: no first child? +#define CHILD_VALUE(anXMLNode) (NODE_VALUE(FIRST_CHILD(anXMLNode))) + +var _plist_traverseNextNode = function(anXMLNode, stayWithin, stack) +{ + var node = anXMLNode; + + PLIST_FIRST_CHILD(node); + + // If this element has a child, traverse to it. + if (node) + return node; + + // If not, first check if it is a container class (as opposed to a designated leaf). + // If it is, then we have to pop this container off the stack, since it is empty. + if (NODE_NAME(anXMLNode) == PLIST_ARRAY || NODE_NAME(anXMLNode) == PLIST_DICTIONARY) + stack.pop(); + + // If not, next check whether it has a sibling. + else + { + if (node == stayWithin) + return NULL; + + node = anXMLNode; + + PLIST_NEXT_SIBLING(node); + + if (node) + return node; + } + + // If it doesn't, start working our way back up the node tree. + node = anXMLNode; + + // While we have a node and it doesn't have a sibling (and we're within our stayWithin), + // keep moving up. + while (node) + { + var next = node; + + PLIST_NEXT_SIBLING(next); + + // If we have a next sibling, just go to it. + if (next) + return next; + + var node = PARENT_NODE(node); + + // If we are being asked to move up, and our parent is the stay within, then just + if (stayWithin && node == stayWithin) + return NULL; + + // Pop the stack if we have officially "moved up" + stack.pop(); + } + + return NULL; +} + +function CPPropertyListCreateFromXMLData(XMLNodeOrData) +{ + var XMLNode = XMLNodeOrData; + + if (XMLNode.string) + { +#if RHINO + XMLNode = DOCUMENT_ELEMENT(Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( + new Packages.org.xml.sax.InputSource(new Packages.java.io.StringReader(XMLNode.string)))); +#else + if (window.ActiveXObject) + { + XMLNode = new ActiveXObject("Microsoft.XMLDOM"); + XMLNode.loadXML(XMLNodeOrData.string.substr(XMLNodeOrData.string.indexOf(".dtd\">") + 6)); + } + else + XMLNode = DOCUMENT_ELEMENT(new DOMParser().parseFromString(XMLNodeOrData.string, "text/xml")); +#endif + } + + // Skip over DOCTYPE and so forth. + while (IS_OF_TYPE(XMLNode, XML_DOCUMENT) || IS_OF_TYPE(XMLNode, XML_XML)) + PLIST_FIRST_CHILD(XMLNode); + + // Skip over the DOCTYPE... see a pattern? + if (IS_DOCUMENTTYPE(XMLNode)) + PLIST_NEXT_SIBLING(XMLNode); + + // If this is not a PLIST, bail. + if (!IS_PLIST(XMLNode)) + return NULL; + + var key = "", + object = NULL, + plistObject = NULL, + + plistNode = XMLNode, + + containers = [], + currentContainer = NULL; + + while (XMLNode = _plist_traverseNextNode(XMLNode, plistNode, containers)) + { + var count = containers.length; + + if (count) + currentContainer = containers[count - 1]; + + if (NODE_NAME(XMLNode) == PLIST_KEY) + { + key = CHILD_VALUE(XMLNode); + PLIST_NEXT_SIBLING(XMLNode); + } + + switch (NODE_NAME(XMLNode)) + { + case PLIST_ARRAY: object = [] + containers.push(object); + break; + case PLIST_DICTIONARY: object = new objj_dictionary(); + containers.push(object); + break; + + case PLIST_NUMBER_REAL: object = parseFloat(CHILD_VALUE(XMLNode)); + break; + case PLIST_NUMBER_INTEGER: object = parseInt(CHILD_VALUE(XMLNode)); + break; + + case PLIST_STRING: object = decodeURIComponent(FIRST_CHILD(XMLNode) ? CHILD_VALUE(XMLNode) : ""); + break; + + case PLIST_BOOLEAN_TRUE: object = true; + break; + case PLIST_BOOLEAN_FALSE: object = false; + break; + + default: objj_exception_throw(new objj_exception(OBJJPlistParseException, "*** " + NODE_NAME(XMLNode) + " tag not recognized in Plist.")); + } + + if (!plistObject) + plistObject = object; + + else if (currentContainer) + // If the container is an array... + if (currentContainer.slice) + currentContainer.push(object); + else + dictionary_setValue(currentContainer, key, object); + } + + return plistObject; +} + +function CPPropertyListCreateXMLData(aPlist) +{ + var data = new objj_data(); + + data.string = ""; + + data.string += ""; + data.string += ""; + data.string += ""; + + _CPPropertyListAppendXMLData(data, aPlist, ""); + + data.string += ""; + + return data; +} + +// CPPropertyListCreateXMLData Helper Functions + +var _CPArrayAppendXMLData = function(XMLData, anArray) +{ + var i = 0, + count = anArray.length; + + XMLData.string += ""; + + for (; i < count; ++i) + _CPPropertyListAppendXMLData(XMLData, anArray[i]); + + XMLData.string += ""; +} + +var _CPDictionaryAppendXMLData = function(XMLData, aDictionary) +{ + var keys = aDictionary.keys, + i = 0, + count = keys.length; + + XMLData.string += ""; + + for (; i < count; ++i) + { + XMLData.string += "" + keys[i] + ""; + _CPPropertyListAppendXMLData(XMLData, dictionary_getValue(aDictionary, keys[i])); + } + + XMLData.string += ""; +} + +var _CPPropertyListAppendXMLData = function(XMLData, aPlist) +{ + var type = typeof aPlist, + valueOf = aPlist.valueOf(), + typeValueOf = typeof valueOf; + + if (type != typeValueOf) + { + type = typeValueOf; + aPlist = valueOf; + } + + if (type == "string") + XMLData.string += "" + encodeURIComponent(aPlist) + ""; + + else if (aPlist === true) + XMLData.string += ""; + else if (aPlist === false) + XMLData.string += ""; + + else if (type == "number") + { + var integer = FLOOR(aPlist); + + if (integer == aPlist) + XMLData.string += "" + aPlist + ""; + else + XMLData.string += "" + aPlist + ""; + } + + else if (aPlist.slice) + _CPArrayAppendXMLData(XMLData, aPlist); + + else + _CPDictionaryAppendXMLData(XMLData, aPlist); +} + +// 280 North Plist Format + +var ARRAY_MARKER = "A", + DICTIONARY_MARKER = "D", + FLOAT_MARKER = "f", + INTEGER_MARKER = "d", + STRING_MARKER = "S", + TRUE_MARKER = "T", + FALSE_MARKER = "F", + KEY_MARKER = "K", + END_MARKER = "E"; + +function CPPropertyListCreateFrom280NorthData(aData) +{ + var stream = new objj_markedStream(aData.string), + + marker = NULL, + + key = "", + object = NULL, + plistObject = NULL, + + containers = [], + currentContainer = NULL; + + while (marker = stream.getMarker()) + { + if (marker == END_MARKER) + { + containers.pop(); + continue; + } + + var count = containers.length; + + if (count) + currentContainer = containers[count - 1]; + + if (marker == KEY_MARKER) + { + key = stream.getString(); + marker = stream.getMarker(); + } + + switch (marker) + { + case ARRAY_MARKER: object = [] + containers.push(object); + break; + case DICTIONARY_MARKER: object = new objj_dictionary(); + containers.push(object); + break; + + case FLOAT_MARKER: object = parseFloat(stream.getString()); + break; + case INTEGER_MARKER: object = parseInt(stream.getString()); + break; + + case STRING_MARKER: object = stream.getString(); + break; + + case TRUE_MARKER: object = true; + break; + case FALSE_MARKER: object = false; + break; + + default: objj_exception_throw(new objj_exception(OBJJPlistParseException, "*** " + marker + " marker not recognized in Plist.")); + } + + if (!plistObject) + plistObject = object; + + else if (currentContainer) + // If the container is an array... + if (currentContainer.slice) + currentContainer.push(object); + else + dictionary_setValue(currentContainer, key, object); + } + + return plistObject; +} + +function CPPropertyListCreate280NorthData(aPlist) +{ + var data = new objj_data(); + + data.string = kCFPropertyList280NorthMagicNumber + ";1.0;" + _CPPropertyListSerializeObject(aPlist, _CPPropertyList280NorthSerializers); + + return data; +} + +var _CPPropertyList280NorthSerializers = {}; + +_CPPropertyList280NorthSerializers["string"] = function(aString) +{ + return STRING_MARKER + ';' + aString.length + ';' + aString; +} + +_CPPropertyList280NorthSerializers["boolean"] = function(aBoolean) +{ + return (aBoolean ? TRUE_MARKER : FALSE_MARKER) + ';'; +} + +_CPPropertyList280NorthSerializers["integer"] = function(anInteger) +{ + var string = "" + anInteger; + + return INTEGER_MARKER + ';' + string.length + ';' + string; +} + +_CPPropertyList280NorthSerializers["real"] = function(aFloat) +{ + var string = "" + aFloat; + + return FLOAT_MARKER + ';' + string.length + ';' + string; +} + +_CPPropertyList280NorthSerializers["array"] = function(anArray, serializers) +{ + var index = 0, + count = anArray.length, + string = ARRAY_MARKER + ';'; + + for (; index < count; ++index) + string += _CPPropertyListSerializeObject(anArray[index], serializers); + + return string + END_MARKER + ';'; +} + +_CPPropertyList280NorthSerializers["dictionary"] = function(aDictionary, serializers) +{ + var keys = aDictionary.keys, + index = 0, + count = keys.length, + string = DICTIONARY_MARKER +';'; + + for (; index < count; ++index) + { + var key = keys[index]; + + string += KEY_MARKER + ';' + key.length + ';' + key; + string += _CPPropertyListSerializeObject(dictionary_getValue(aDictionary, key), serializers); + } + + return string + END_MARKER + ';'; +} diff --git a/Objective-J/preprocess.js b/Objective-J/preprocess.js new file mode 100644 index 000000000..b7e736214 --- /dev/null +++ b/Objective-J/preprocess.js @@ -0,0 +1,568 @@ +/* + * preprocess.js + * Objective-J + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +OBJJParseException = "OBJJParseException"; +OBJJClassNotFoundException = "OBJJClassNotFoundException"; + +var TOKEN_NEW = "new", + TOKEN_SUPER = "super", + TOKEN_CLASS = "class", + TOKEN_IMPORT = "import", + TOKEN_FUNCTION = "function", + TOKEN_SELECTOR = "selector", + TOKEN_IMPLEMENTATION = "implementation", + + TOKEN_PLUS = '+', + TOKEN_MINUS = '-', + TOKEN_COLON = ':', + TOKEN_COMMA = ',', + TOKEN_PERIOD = '.', + TOKEN_ASTERISK = '*', + TOKEN_SEMICOLON = ';', + TOKEN_LESS_THAN = '<', + TOKEN_OPEN_BRACE = '{', + TOKEN_CLOSE_BRACE = '}', + TOKEN_GREATER_THAN = '>', + TOKEN_OPEN_BRACKET = '[', + TOKEN_DOUBLE_QUOTE = '"', + TOKEN_PREPROCESSOR = '@', + TOKEN_CLOSE_BRACKET = ']', + TOKEN_QUESTION_MARK = '?', + TOKEN_OPEN_PARENTHESIS = '(', + TOKEN_CLOSE_PARENTHESIS = ')'; + + +// FIXME: This could break with static preinterpretation. +var SUPER_CLASSES = new objj_dictionary(), + CURRENT_SUPER_CLASS = NULL, + CURRENT_CLASS_NAME = NULL; + +var OBJJ_CURRENT_BUNDLE = NULL; + +// FIXME: Used fixed regex +var objj_lexer = function(aString, aSourceFile) +{ + this._index = 0; + this._tokens = (aString + '\n').match(/\/\/.*(\r|\n)?|\/\*(?:.|\n|\r)*?\*\/|\w+\b|[+-]?\d+(([.]\d+)*([eE][+-]?\d+))?|"[^"\\]*(\\.[^"\\]*)*"|'[^'\\]*(\\.[^'\\]*)*'|\s+|./g); + + this.file = aSourceFile; + + return this; +} + +objj_lexer.prototype.next = function() +{ + return this._tokens[this._index++]; +} + +objj_lexer.prototype.previous = function() +{ + return this._tokens[--this._index]; +} + +objj_lexer.prototype.last = function() +{ + if (this._index > 1) + return this._tokens[this._index - 2]; + + return NULL; +} + +objj_lexer.prototype.skip_whitespace= function() +{ + var token; + while((token = this.next()) && (!(/\S/).test(token) || token.substr(0,2) == "//" || token.substr(0,2) == "/*")) ; + + return token; +} + +var objj_preprocess_method = function(tokens, count, array_name) +{ + var token, + selector = "", + parameters = new Array(); + + while((token = tokens.skip_whitespace()) && token != TOKEN_OPEN_BRACE) + { + if (token == TOKEN_COLON) + { + // Colons are part of the selector name + selector += token; + + token = tokens.skip_whitespace(); + + if (token == TOKEN_OPEN_PARENTHESIS) + { + // Swallow parameter/return type. Perhaps later we can use this for debugging? + while((token = tokens.skip_whitespace()) && token != TOKEN_CLOSE_PARENTHESIS) ; + + token = tokens.skip_whitespace(); + } + + // Since this follows a colon, this must be the parameter name. + parameters[parameters.length] = token; + } + else if (token == TOKEN_OPEN_PARENTHESIS) + // Since :( is handled above, this must be the return type, just swallow it. + while((token = tokens.skip_whitespace()) && token != TOKEN_CLOSE_PARENTHESIS) ; + // Argument list ", ..." + else if (token == TOKEN_COMMA) + { + // At this point, "..." MUST follow. + if ((token = tokens.skip_whitespace()) != TOKEN_PERIOD || tokens.next() != TOKEN_PERIOD || tokens.next() != TOKEN_PERIOD) + objj_exception_throw(new objj_exception(OBJJParseException, "*** Argument list expected after ','.")); + + // FIXME: Shouldn't allow any more after this. + } + // Build selector name. + else + selector += token; + } + + var i= 0, + length = parameters.length, + selectorDisplayName = "$"+CURRENT_CLASS_NAME+"__"+selector.replace(/:/g, "_"), + preprocessed = array_name + "["+count+"] = new objj_method(sel_registerName(\""+selector+"\"), function "+selectorDisplayName+"(self, _cmd"; + + for(; i < length; ++i) + preprocessed += ", " + parameters[i]; + +#if FIREBUG + // FireBug auto expands and doesn't allow you to resize, so truncate it. + var truncatedSelector = "["+CURRENT_CLASS_NAME+" "+(selector.length > 60 ? selector.substring(0, 60) + "..." : selector)+"]"; + return preprocessed + ")\n{ \"__FIREBUG_FNAME__"+truncatedSelector+"\".length;\n with(self)\n{" + objj_preprocess_tokens(tokens, TOKEN_CLOSE_BRACE, TOKEN_OPEN_BRACE) + "}\n});\n"; +#else + return preprocessed + ")\n{ with(self)\n{" + objj_preprocess_tokens(tokens, TOKEN_CLOSE_BRACE, TOKEN_OPEN_BRACE) + "}\n});\n"; +#endif +} + +var objj_preprocess_implementation= function(tokens) +{ + var token = "", + category = NO, + preprocessed = "", + class_name = tokens.skip_whitespace(), + superclass_name = "Nil", + class_method_count = 0, + instance_method_count = 0; + + if (!(/^\w/).test(class_name)) + objj_exception_throw(new objj_exception(OBJJParseException, "*** Expected class name, found \"" + class_name + "\".")); + + CURRENT_SUPER_CLASS = NULL; + CURRENT_CLASS_NAME = class_name; + + // NOTE: This behavior is currently turned off. + // addWorkingClass(class_name); + + // If we reach an open parenthesis, we are declaring a category. + if((token = tokens.skip_whitespace()) == TOKEN_OPEN_PARENTHESIS) + { + token = tokens.skip_whitespace(); + + if(tokens.skip_whitespace() != TOKEN_CLOSE_PARENTHESIS) + objj_exception_throw(new objj_exception(OBJJParseException, "*** Improper Category Definition for class \""+class_name+"\".")); + + preprocessed += "{\nvar the_class = objj_getClass(\"" + class_name + "\")\n"; + preprocessed += "if(!the_class) objj_exception_throw(new objj_exception(OBJJClassNotFoundException, \"*** Could not find definition for class \\\"" + class_name + "\\\"\"));\n"; + preprocessed += "var meta_class = the_class.isa;"; + + var superclass_name = dictionary_getValue(SUPER_CLASSES, class_name); + + // FIXME: We should have a better solution for this case, although it's actually not much slower than the real case. + if (!superclass_name) + CURRENT_SUPER_CLASS = "objj_getClass(\"" + class_name + "\").super_class"; + else + CURRENT_SUPER_CLASS = "objj_getClass(\"" + superclass_name + "\")"; + } + else + { + // If we reach a colon (':'), then a superclass is being declared. + if(token == TOKEN_COLON) + { + token = tokens.skip_whitespace(); + if (!(/^\w/).test(token)) + objj_exception_throw(new objj_exception(OBJJParseException, "*** Expected class name, found \"" + token + "\".")); + + superclass_name = token; + CURRENT_SUPER_CLASS = "objj_getClass(\"" + superclass_name + "\")"; + + dictionary_setValue(SUPER_CLASSES, class_name, superclass_name); + + token = tokens.skip_whitespace(); + } + + preprocessed += "{var the_class = objj_allocateClassPair(" + superclass_name + ", \"" + class_name + "\"),\nmeta_class = the_class.isa;"; + + // If we are at an opening curly brace ('{'), then we have an ivar declaration. + if (token == TOKEN_OPEN_BRACE) + { + var ivar = true, + ivar_count = 0; + + while((token = tokens.skip_whitespace()) && token != TOKEN_CLOSE_BRACE) + { + if (token != TOKEN_SEMICOLON && (ivar = !ivar)) + { + if (ivar_count++ == 0) + preprocessed += "class_addIvars(the_class, ["; + else + preprocessed += ", "; + + preprocessed += "new objj_ivar(\"" + token + "\")"; + } + } + + if (ivar_count) + preprocessed += "]);\n"; + + if (!token) + objj_exception_throw(new objj_exception(OBJJParseException, "*** Expected '}'")); + } + else tokens.previous(); + + // We must make a new class object for our class definition. + preprocessed += "objj_registerClassPair(the_class);\n"; + + // Add this class to the current bundle. + preprocessed += "objj_addClassForBundle(the_class, objj_getBundleWithPath(OBJJ_CURRENT_BUNDLE.path));\n"; + } + + while((token = tokens.skip_whitespace())) + { + if(token == TOKEN_PLUS) preprocessed += (class_method_count ? "" : "var class_methods = [];\n") + objj_preprocess_method(tokens, class_method_count++, "class_methods"); + else if(token == TOKEN_MINUS) preprocessed += (instance_method_count ? "" : "var instance_methods = [];\n") + objj_preprocess_method(tokens, instance_method_count++, "instance_methods"); + // Check if we've reached @end... + else if(token == TOKEN_PREPROCESSOR) + { + // The only preprocessor directive we should ever encounter at this point is @end. + if((token = tokens.next()) == "end") + break; + else + objj_exception_throw(new objj_exception(OBJJParseException, "*** Expected \"@end\", found \"@" + token + "\".")); + } + } + + // Do the instance methods first because they could override the class methods if not. + if (instance_method_count) preprocessed += "class_addMethods(the_class, instance_methods);\n"; + if (class_method_count) preprocessed += "class_addMethods(meta_class, class_methods);\n"; + + return preprocessed + '}'; +} + +var objj_preprocess_directive = function(tokens) +{ + // Grab the next token, preprocessor directives follow '@' immediately. + token = tokens.next(); + + // To provide compatibility with Objective-C files, we convert NSString literals into + // toll-freed JavaScript/CPString strings. + if(token.charAt(0) == TOKEN_DOUBLE_QUOTE) return token; + // Currently we simply swallow forward declarations and only provide them to allow + // compatibility with Objective-C files. + else if(token == TOKEN_CLASS) { tokens.skip_whitespace(); return ""; } + // @implementation Class implementations + else if(token == TOKEN_IMPLEMENTATION) return objj_preprocess_implementation(tokens); + // @selector + else if(token == TOKEN_SELECTOR) + { + // Swallow open parenthesis. + if (tokens.skip_whitespace() != TOKEN_OPEN_PARENTHESIS) + objj_exception_throw(new objj_exception(OBJJParseException, "*** Expected ')'")); + return "sel_registerName(\"" + objj_preprocess_tokens(tokens, TOKEN_CLOSE_PARENTHESIS) +"\")"; + } + + return ""; +} + +var objj_preprocess_brackets = function(tokens) +{ + // We maintain two parallel interpretations through the process, + // One which assumes the brackets form a literal array, and + // another that builds the possible message dispatch composed of + // a receiver, a selector, and a number of marg_list. + var literal = '[', + receiver = "", + selector = "", + marg_list = new Array(), + preprocessed = "objj_msgSend"; + + // We keep track of the current iterative token, the previous + // expression, tertiary operations, and parenthesis. + var token = "", + array = false, + previous = "", + + braces = 0, + tertiary = 0, + parenthesis = 0; + + while((token = tokens.skip_whitespace()) && token != TOKEN_CLOSE_BRACKET) + { + // We should attempt to preprocess our message code only if we are + // not within parenthesis or a tertiary statement. + var preprocess = !braces && !tertiary && !parenthesis && !array; + + // Generally we are unconcerned with whitespace, however the new + // operator is a special case since it could alse be part of an identifier. + if(token == TOKEN_NEW) token = "new "; + // We handle the special case where the receiver is super. In this case, + // use an objj_super object and use objj_msgSendSuper instead of objj_msgSend. + else if(token == TOKEN_SUPER) + { + if (!receiver.length) + { + preprocessed = "objj_msgSendSuper"; + token = "{ receiver:self, super_class:" + CURRENT_SUPER_CLASS + " }"; + } + else + objj_exception_throw(new objj_exception(OBJJParseException, "*** Can't use 'super' in this context.")); + } + else if (token == TOKEN_OPEN_BRACE) ++braces; + else if (token == TOKEN_CLOSE_BRACE) --braces; + // Tertiary expressions have the potential to confuse the preprocessor, + // so keep track of them to avoid misidentifying a colon (':') for an + // argument. + else if(token == TOKEN_QUESTION_MARK) ++tertiary; + // Keep track of expressions within parenthesis. + else if(token == TOKEN_OPEN_PARENTHESIS) ++parenthesis; + else if(token == TOKEN_CLOSE_PARENTHESIS) --parenthesis; + // If we reach a nested bracket, preprocess it first and interpret + // the result as the current token. + else if(token == TOKEN_OPEN_BRACKET) token = objj_preprocess_brackets(tokens); + else if(token == TOKEN_PREPROCESSOR) token = objj_preprocess_directive(tokens); + + // Preprocess tokens only if we're not within parenthesis or in a + // tertiary statement. + if(preprocess) + { + // If we ever reach a comma that is not in a sub expression, + // and we haven't yet begun to construct a selector, then + // we can be sure that this is not a message dispatch, and + // we should simply return so that the lexer can continue + // to preprocess normally. + if(token == TOKEN_COMMA && !selector.length) + array = true;//return literal + token; + // A colon (':') alerts us that we've reached the end of a label. + if(token == TOKEN_COLON) + { + // If the previous token was actually white space, so this + // is an empty label. + var last = tokens.last(); + + if (last && (!(/\S/).test(last) || last.substr(0, 2) == "//" || last.substr(0, 2) == "/*")) + { + selector += ':'; + marg_list[marg_list.length - 1] += previous; + marg_list[marg_list.length] = previous = ""; + } + + // If not the previous token was was part of the label and + // thus should be appended to the selector. + else + { + selector += previous + ":"; + marg_list[marg_list.length] = previous = ""; + } + } + else + { + // If we've already begun building our selector, then the token + // should be applied to the current argument. + if (selector.length) + marg_list[marg_list.length - 1] += previous; + // If not, then it belongs to the receiver. + else + receiver += previous; + + previous = token; + } + } + // If not, add it to previous to be interpreted as one block. + else + { + // We know this colon (':') to match a previous tertiary expression. + // FIXME PARSER_BUG: This does not properly account for interspersed { } and ?: + // https://trac.280north.com/ticket/15 + if(token == TOKEN_COLON && !braces) + --tertiary; + previous += token; + } + + // The literal interpretation is always handled in the same + // manner, simply aggregate the tokens. + literal += token; + } + + // If we have a selector, then add the remaining string to the argument. + if (selector.length) marg_list[marg_list.length - 1] += previous; + // If not, check whether the final character of our proposed receiver + // is an operator or the new keyword. Also check that the previous + // expression does not begin with a parenthesis, since this means it + // definitely can't be a selector. + // FIXME: There is probably a more concise and efficient way to represent + // these regular expressions. + // FIXME: Should the second expression be the same as the first. For example, + // array[i%] becomes arrayobjj_msgSend(i,"%") if not. This is an error either + // way though. https://trac.280north.com/ticket/6 + else if(!array && receiver.length && !((/[\:\+\-\*\/\=\<\>\&\|\!\.\%]/).test(receiver.charAt(receiver.length - 1))) && + receiver != "new " && !(/[\+\-\*\/\=\<\>\&\|\!\.\[\^\(]/).test(previous.charAt(0))) + selector = previous; + // If we did not build a selector through the parsing process, then we + // are either a single entry literal array, or an array index, and so + // we should simply return our literal string. + else return literal + ']'; + + // NOTE: For now, turn this behavior off. + // Classes act much like keywords since they are not directly manipulatable. + // We thus check whether it exists in our class hash or working hash, and if + // instead use a reference to it if it does. + // if (tokens.containsClass(receiver) || objj_getClass(receiver)) receiver = "objj_getClass(\"" + receiver + "\")"; + + // The first two arguments are always the receiver and the selector. + preprocessed += '(' + receiver + ", \"" + sel_registerName(selector) + "\""; + + // Populate the remaining parameters with the provided arguments. + var i = 0, + length = marg_list.length; + + for(; i < length; ++i) + preprocessed += ", " + marg_list[i]; + + // Return the fully preprocessed message dispatch. + return preprocessed + ')'; +} + +function objj_preprocess_tokens(tokens, terminator, instigator, segment) +{//if (window.p) alert("objj_preprocess_tokens"); + var count = 0, + token = "", + fragments = [], + preprocessed = ""; + + while((token = tokens.next()) && ((token != terminator) || count)) + { + if (instigator) + { + if (token == instigator) ++count; + else if (token == terminator) --count; + } + + // We convert import statements into objj_request_import function calls, converting + // the the file paths to use the proper search arguments. + if(token == TOKEN_IMPORT) + { + if ((/[^\s]/).test(preprocessed)) + fragments.push(fragment_create_code(preprocessed, OBJJ_CURRENT_BUNDLE, tokens.file)); + + preprocessed = ""; + + var path = "", + token = tokens.skip_whitespace(), + isLocal = token != TOKEN_LESS_THAN; + + if(token == TOKEN_LESS_THAN) + { + while((token= tokens.next()) && token != TOKEN_GREATER_THAN) path+= token; + if(!token) objj_throw("Parser Error - Unterminated import statement."); + } + else if(token.charAt(0) == TOKEN_DOUBLE_QUOTE) path= token.substr(1, token.length-2); + else + objj_exception_throw(new objj_exception(OBJJParseException, "*** Expecting '<' or '\"', found \"" + token + "\".")); + + fragments.push(fragment_create_file(path, NULL, isLocal, YES, tokens.file)); + } + // Safari can't handle function declarations of the form function [name]([arguments]) { } + // in evals. It requires them to be in the form [name] = function([arguments]) { }. So we + // need to find these and fix them. + else if(token == TOKEN_FUNCTION) + {//if (window.p) alert("function"); + var accumulator= ""; + + // Following the function identifier we can either have an open parenthesis or an identifier: + while((token = tokens.next()) && token != TOKEN_OPEN_PARENTHESIS && !(/^\w/).test(token)) + accumulator += token; + + // If the next token is an open parenthesis, we have a standard function and we don't have to + // change it: + if(token == TOKEN_OPEN_PARENTHESIS) + preprocessed+= "function"+accumulator+'('; + // If it's not a parenthesis, we know we have a non-supported function declaration, so fix it: + else + { + preprocessed += token + "= function"; + +#if FIREBUG + var functionName = token; + + // Skip everything until the next close parenthesis. + while((token = tokens.next()) && token != TOKEN_CLOSE_PARENTHESIS) + preprocessed += token; + + // Don't forget the last token! + preprocessed += token; + + // Skip everything until the next open curly brace. + while((token = tokens.next()) && token != TOKEN_OPEN_BRACE) + preprocessed += token; + + // Place the open curly brace as well, and the function name + preprocessed += token + "\n \"__FIREBUG_FNAME__" + functionName + "\".length;\n"; +#endif + } + } + // If we reach an @ symbol, we are at a preprocessor directive. + else if(token == TOKEN_PREPROCESSOR) + preprocessed+= objj_preprocess_directive(tokens); + // If we reach a bracket, we will either be preprocessing a message send, a literal + // array, or an array index. + else if(token == TOKEN_OPEN_BRACKET) + preprocessed += objj_preprocess_brackets(tokens); + // If not simply append the token. + else + preprocessed += token; + } + + if (preprocessed.length && (/[^\s]/).test(preprocessed)) + fragments.push(fragment_create_code(preprocessed, OBJJ_CURRENT_BUNDLE, tokens.file)); + + if (!segment) + return fragments.length ? fragments[0].info : ""; + + return fragments; +} + +function objj_preprocess(aString, aBundle, aSourceFile) +{ + try + { + OBJJ_CURRENT_BUNDLE = aBundle; + + return objj_preprocess_tokens(new objj_lexer(aString, aSourceFile), nil, nil, YES); + } + catch (anException) + { + objj_exception_report(anException, aSourceFile); + } + + return []; +} diff --git a/Objective-J/runtime.js b/Objective-J/runtime.js new file mode 100644 index 000000000..17231cf42 --- /dev/null +++ b/Objective-J/runtime.js @@ -0,0 +1,571 @@ +/* + * runtime.js + * Objective-J + * + * Created by Francisco Tolmasky. + * Copyright 2008, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +var CLS_CLASS = 0x1, + CLS_META = 0x2, + CLS_INITIALIZED = 0x4, + CLS_INITIALIZING = 0x8; + +#define CHANGEINFO(aClass, aSetInfoMask, aClearInfoMask) aClass.info = (aClass.info | (aSetInfoMask)) & ~(aClearInfoMask) +#define GETINFO(aClass, anInfoMask) (aClass.info & (anInfoMask)) +#define SETINFO(aClass, anInfoMask) CHANGEINFO(aClass, anInfoMask, 0) +#define CLEARINFO(aClass, anInfoMask) CHANGEINFO(aClass, 0, anInfoMask) +#define ISMETA(aClass) (GETINFO(aClass, CLS_META)) +#define GETMETA(aClass) (ISMETA(aClass) ? aClass : aClass.isa) +#define ISINITIALIZED(aClass) GETINFO(GETMETA(aClass), CLS_INITIALIZED) + +function objj_ivar(/*String*/ aName, /*String*/ aType) +{ + this.name = aName; + this.type = aType; +} + +function objj_method(/*String*/ aName, /*IMP*/ anImplementation, /*String*/ types) +{ + this.name = aName; + this.method_imp = anImplementation; + this.types = types; +} + +function objj_class() +{ + this.isa = NULL; + + this.super_class = NULL; + this.sub_classes = []; + + this.name = NULL; + this.info = 0; + this.ivars = []; + + this.method_list = []; + this.method_hash = {}; + + this.method_store = function() { }; + this.method_dtable = this.method_store.prototype; + + this.allocator = function() { }; + this.__address = -1; +} + +function objj_object() +{ + this.isa = NULL; + this.__address = -1; +} + +// Addressing Objects + +var OBJECT_COUNT = 0; + +function _objj_generateObjectHash() +{ + return OBJECT_COUNT++; +} + +#define _objj_generateObjectHash() (OBJECT_COUNT++) + +// Working with Classes + +function class_getName(/*Class*/ aClass) +{ + if (aClass == Nil) + return ""; + + return aClass.name; +} + +function class_isMetaClass(/*Class*/ aClass) +{ + if (!aClass) + return NO; + + return ISMETA(aClass); +} + +function class_getSuperclass(/*Class*/ aClass) +{ + if (aClass == Nil) + return Nil; + + return aClass.super_class; +} + +function class_setSuperclass(/*Class*/ aClass, /*Class*/ aSuperClass) +{ + // FIXME: implement. +} + +function class_isMetaClass(/*Class*/ aClass) +{ + return ISMETA(aClass); +} + +function class_addIvar(/*Class*/ aClass, /*String*/ aName, /*String*/ aType) +{ + var thePrototype = aClass.allocator.prototype; + + if (typeof thePrototype[aName] != "undefined") + return NO; + + aClass.ivars.push(new objj_ivar(aName, aType)); + thePrototype[aName] = NULL; + + return YES; +} + +function class_addIvars(/*Class*/ aClass, /*Array*/ivars) +{ + var index = 0, + count = ivars.length, + thePrototype = aClass.allocator.prototype; + + for (; index < count; ++index) + { + var ivar = ivars[index], + name = ivar.name; + + if (typeof thePrototype[name] == "undefined") + { + aClass.ivars.push(ivar); + thePrototype[name] = NULL; + } + } +} + +function class_copyIvarList(/*Class*/ aClass) +{ + return aClass.ivars.slice(0); +} + +//#define class_copyIvarList(aClass) (aClass.ivars.slice(0)) + +function class_addMethod(/*Class*/ aClass, /*SEL*/ aName, /*IMP*/ anImplementation, /*String*/types) +{ + if (aClass.method_hash[aName]) + return NO; + + var method = new objj_method(aName, anImplementation, aType); + + aClass.method_list.push(method); + aClass.method_dtable[aName] = method; + + // FIXME: Should this be done here? + // If this is a root class... + if (!ISMETA(aClass) && GETMETA(aClass).isa == GETMETA(aClass)) + class_addMethods(GETMETA(aClass), methods); + + return YES; +} + +function class_addMethods(/*Class*/ aClass, /*Array*/ methods) +{ + var index = 0, + count = methods.length, + + method_list = aClass.method_list, + method_dtable = aClass.method_dtable; + + for (; index < count; ++index) + { + var method = methods[index]; + + if (aClass.method_hash[method.name]) + continue; + + method_list.push(method); + method_dtable[method.name] = method; + } + + // If this is a root class... + if (!ISMETA(aClass) && GETMETA(aClass).isa == GETMETA(aClass)) + class_addMethods(GETMETA(aClass), methods); +} + +function class_getInstanceMethod(/*Class*/ aClass, /*SEL*/ aSelector) +{ + if (!aClass || !aSelector) + return NULL; + + var method = aClass.method_dtable[aSelector]; + + return method ? method : NULL; +} + +function class_getClassMethod(/*Class*/ aClass, /*SEL*/ aSelector) +{ + if (!aClass || !aSelector) + return NULL; + + var method = GETMETA(aClass).method_dtable[aSelector]; + + return method ? method : NULL; +} + +function class_copyMethodList(/*Class*/ aClass) +{ + return aClass.method_list.slice(0); +} + +var _class_initialize = function(/*Class*/ aClass) +{ + var meta = GETMETA(aClass); + + if (GETINFO(aClass, CLS_META)) + aClass = objj_getClass(aClass.name); + + if (aClass.super_class && !ISINITIALIZED(aClass.super_class)) + _class_initialize(aClass.super_class); + + if (!GETINFO(meta, CLS_INITIALIZED) && !GETINFO(meta, CLS_INITIALIZING)) + { + SETINFO(meta, CLS_INITIALIZING); + + objj_msgSend(aClass, "initialize"); + + CHANGEINFO(meta, CLS_INITIALIZED, CLS_INITIALIZING); + } +} + +var _objj_forward = new objj_method("forward", function(self, _cmd) +{ + return objj_msgSend(self, "forward::", _cmd, arguments); +}); + +// I think this forward:: may need to be a common method, instead of defined in CPObject. +#define CLASS_GET_METHOD_IMPLEMENTATION(aMethodImplementation, aClass, aSelector)\ + if (!ISINITIALIZED(aClass))\ + _class_initialize(aClass);\ + \ + var method = aClass.method_dtable[aSelector];\ + \ + if (!method)\ + method = _objj_forward;\ + \ + aMethodImplementation = method.method_imp; + +function class_getMethodImplementation(/*Class*/ aClass, /*SEL*/ aSelector) +{ + CLASS_GET_METHOD_IMPLEMENTATION(var implementation, aClass, aSelector); + + return implementation; +} + +// Adding Classes + +var GLOBAL_NAMESPACE = this, + REGISTERED_CLASSES = {}; + +function objj_allocateClassPair(/*Class*/ superclass, /*String*/ aName) +{ + var classObject = new objj_class(), + metaClassObject = new objj_class(), + rootClassObject = classObject; + + // If we don't have a superclass, we are the root class. + if (superclass) + { + rootClassObject = superclass; + + while (rootClassObject.superclass) + rootClassObject = rootClassObject.superclass; + + // Give our current allocator all the instance variables of our super class' allocator. + classObject.allocator.prototype = new superclass.allocator; + + // "Inheret" parent methods. + classObject.method_store.prototype = new superclass.method_store; + classObject.method_dtable = classObject.method_store.prototype; + + metaClassObject.method_store.prototype = new superclass.isa.method_store; + metaClassObject.method_dtable = metaClassObject.method_store.prototype; + + // Set up the actual class hierarchy. + classObject.super_class = superclass; + metaClassObject.super_class = superclass.isa; + } + else + classObject.allocator.prototype = new objj_object(); + + classObject.isa = metaClassObject; + classObject.name = aName; + classObject.info = CLS_CLASS; + classObject.__address = _objj_generateObjectHash(); + + metaClassObject.isa = rootClassObject.isa; + metaClassObject.name = aName; + metaClassObject.info = CLS_META; + metaClassObject.__address = _objj_generateObjectHash(); + + return classObject; +} + +function objj_registerClassPair(/*Class*/ aClass) +{ + GLOBAL_NAMESPACE[aClass.name] = aClass; + REGISTERED_CLASSES[aClass.name] = aClass; +} + +// Instantiating Classes + +function class_createInstance(/*Class*/ aClass) +{ + if (!aClass) + objj_exception_throw(new objj_exception(OBJJNilClassException, "*** Attempting to create object with Nil class.")); + + var object = new aClass.allocator; + + object.__address = _objj_generateObjectHash(); + object.isa = aClass; + + return object; +} + +// Opera 9.5.1 has a bug where prototypes "inheret" members from instances when "with" is used. +// Given that the Opera team is so fond of bug-testing instead of version-testing, we'll go +// ahead and do that. + +var prototype_bug = function() { } + +prototype_bug.prototype.member = false; + +with (new prototype_bug()) + member = true; + +// If the bug exists, go down the slow path. +if (new prototype_bug().member) +{ + +var fast_class_createInstance = class_createInstance; + +class_createInstance = function(/*Class*/ aClass) +{ + var object = fast_class_createInstance(aClass); + + if (object) + { + var theClass = object.isa, + actualClass = theClass; + + while (theClass) + { + var ivars = theClass.ivars; + count = ivars.length; + + while (count--) + object[ivars[count].name] = NULL; + + theClass = theClass.super_class; + } + + object.isa = actualClass; + } + + return object; +} + +} + +// Working with Instances + +function object_getClassName(/*id*/ anObject) +{ + if (!anObject) + return ""; + + var theClass = anObject.isa; + + return theClass ? class_getName(theClass) : ""; +} + +//objc_getClassList +function objj_lookUpClass(/*String*/ aName) +{ + var theClass = REGISTERED_CLASSES[aName]; + + return theClass ? theClass : Nil; +} + +function objj_getClass(/*String*/ aName) +{ + var theClass = REGISTERED_CLASSES[aName]; + + if (!theClass) + { + // class handler callback??? + } + + return theClass ? theClass : Nil; +} + +//objc_getRequiredClass +function objj_getMetaClass(/*String*/ aName) +{ + var theClass = objj_getClass(aName); + + return GETMETA(theClass); +} + +// Working with Instance Variables + +function ivar_getName(anIvar) +{ + return anIvar.name; +} + +function ivar_getTypeEncoding(anIvar) +{ + return anIvar.type; +} + +// Sending Messages + +function objj_msgSend(/*id*/ aReceiver, /*SEL*/ aSelector) +{ + if (aReceiver == nil) + return nil; + +#if DEBUG + objj_debug_backtrace.push("[" + GETMETA(aReceiver).name + " " + aSelector + "]"); + + try + { + var result = class_getMethodImplementation(aReceiver.isa, aSelector).apply(aReceiver, arguments); + } + catch (anException) + { + CPLog.error("Exception " + anException + " in [" + GETMETA(aReceiver).name + " " + aSelector + "]"); + objj_debug_print_backtrace(); + } + + objj_debug_backtrace.pop(); + + return result; +#else + CLASS_GET_METHOD_IMPLEMENTATION(var implementation, aReceiver.isa, aSelector); + + return implementation.apply(aReceiver, arguments); +#endif +} + +function objj_msgSendSuper(/*id*/ aSuper, /*SEL*/ aSelector) +{ +#if DEBUG + objj_debug_backtrace.push("[" + GETMETA(aSuper.receiver).name + " " + aSelector + "]"); +#endif + var super_class = aSuper.super_class; + + arguments[0] = aSuper.receiver; + +#if !DEBUG + CLASS_GET_METHOD_IMPLEMENTATION(var implementation, super_class, aSelector); + + return implementation.apply(aSuper.receiver, arguments); +#else + try + { + var result = class_getMethodImplementation(super_class, aSelector).apply(aSuper.receiver, arguments); + } + catch (anException) + { + CPLog.error("Exception " + anException + " in [" + GETMETA(aSuper.receiver).name + " " + aSelector + "]"); + objj_debug_print_backtrace(); + } + + objj_debug_backtrace.pop(); + + return result; +#endif +} + +#if DEBUG +// FIXME: This could be much better. +var objj_debug_backtrace = []; + +function objj_debug_print_backtrace() +{ + CPLog.trace(objj_debug_backtrace_string()); +} + +function objj_debug_backtrace_string() +{ + var i = objj_debug_backtrace.length, + backtrace = ""; + + while (i--) + backtrace += objj_debug_backtrace[i] + "\n"; + + return backtrace; +} +#endif + +// Working with Methods + +function method_getName(/*Method*/ aMethod) +{ + return aMethod.name; +} + +function method_getImplementation(/*Method*/ aMethod) +{ + return aMethod.method_imp; +} + +function method_setImplementation(/*Method*/ aMethod, /*IMP*/ anImplementation) +{ + var oldImplementation = aMethod.method_imp; + + aMethod.method_imp = anImplementation; + + return oldImplementation; +} + +function method_exchangeImplementations(/*Method*/ lhs, /*Method*/ rhs) +{ + var lhs_imp = method_getImplementation(lhs), + rhs_imp = method_getImplementation(rhs); + + method_setImplementation(lhs, rhs_imp); + method_setImplementation(rhs, lhs_imp); +} + +// Working with Selectors + +function sel_getName(aSelector) +{ + return aSelector ? aSelector : ""; +} + +function sel_getUid(/*String*/ aName) +{ + return aName; +} + +function sel_isEqual(/*SEL*/ lhs, /*SEL*/ rhs) +{ + return lhs == rhs; +} + +function sel_registerName(aName) +{ + return aName; +} diff --git a/Objective-J/static.js b/Objective-J/static.js new file mode 100644 index 000000000..c25353e48 --- /dev/null +++ b/Objective-J/static.js @@ -0,0 +1,70 @@ + +OBJJUnrecognizedFormatException = "OBJJUnrecognizedFormatException"; + +var STATIC_MAGIC_NUMBER = "@STATIC", + MARKER_PATH = "p", + MARKER_CODE = "c", + MARKER_IMPORT_STD = 'I', + MARKER_IMPORT_LOCAL = 'i'; + +var STATIC_EXTENSION = "sj"; + +function objj_preprocess_file(aFilePath, fileContents) +{ + // Preprocess contents into fragments. + var fragments = objj_preprocess(fileContents, { path:"/x" }, { path:aFilePath}), + index = 0, + count = fragments.length, + preprocessed = MARKER_PATH + ';' + aFilePath.length() + ';' + aFilePath; + + // Writer preprocessed fragments out. + for (; index < count; ++index) + { + var fragment = fragments[index]; + + if (IS_FILE(fragment)) + preprocessed += (IS_LOCAL(fragment) ? MARKER_IMPORT_LOCAL : MARKER_IMPORT_STD) + ';' + GET_PATH(fragment).length + ';' + GET_PATH(fragment); + else + preprocessed += MARKER_CODE + ';' + GET_CODE(fragment).length + ';' + GET_CODE(fragment); + } + + return preprocessed; +} + +function objj_decompile(aString, bundle) +{ + var stream = new objj_markedStream(aString); + + if (stream.magicNumber() != STATIC_MAGIC_NUMBER) + objj_exception_throw(new objj_exception(OBJJUnrecognizedFormatException, "*** Could not recognize executable code format.")); + + if (stream.version() != 1.0) + objj_exception_throw(new objj_exception(OBJJUnrecognizedFormatException, "*** Could not recognize executable code format.")); + + var file = NULL, + files = []; + + while (marker = stream.getMarker()) + { + var text = stream.getString(); + + switch (marker) + { + case MARKER_PATH: file = new objj_file(); + file.path = DIRECTORY(bundle.path) + text; + file.bundle = bundle; + file.fragments = []; + + files.push(file); + break; + case MARKER_CODE: file.fragments.push(fragment_create_code(text, bundle, file)); + break; + case MARKER_IMPORT_STD: file.fragments.push(fragment_create_file(text, bundle, NO, YES, file)); + break; + case MARKER_IMPORT_LOCAL: file.fragments.push(fragment_create_file(text, bundle, YES, YES, file)); + break; + } + } + + return files; +} diff --git a/README b/README new file mode 100644 index 000000000..e69de29bb diff --git a/Tools/Install/build.xml b/Tools/Install/build.xml new file mode 100644 index 000000000..d4dc9ad45 --- /dev/null +++ b/Tools/Install/build.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Tools/Install/install-tools b/Tools/Install/install-tools new file mode 100755 index 000000000..5adacedab --- /dev/null +++ b/Tools/Install/install-tools @@ -0,0 +1,59 @@ +#!/bin/sh + +usage() +{ + echo "$0 [--prefix install_directory]" + exit 1 +} + +INSTALL_DIR="/usr/local" + +# Parse parameters +while [ $# -ge 1 ]; do + case $1 in + --prefix) + INSTALL_DIR=$2 + shift + ;; + *) + usage + ;; + esac + shift +done + +mkdir -p $INSTALL_DIR/bin +mkdir -p $INSTALL_DIR/share + +cp -fR objj/ $INSTALL_DIR/share/objj + +ln -sf $INSTALL_DIR/share/objj/bin/objj $INSTALL_DIR/bin/objj +ln -sf $INSTALL_DIR/share/objj/bin/objjc $INSTALL_DIR/bin/objjc +ln -sf $INSTALL_DIR/share/objj/bin/steam $INSTALL_DIR/bin/steam +ln -sf $INSTALL_DIR/share/objj/bin/bake $INSTALL_DIR/bin/bake + +cat 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 literal 0 HcmV?d00001 diff --git a/Tools/Jars/bsf.jar b/Tools/Jars/bsf.jar new file mode 100644 index 0000000000000000000000000000000000000000..3028967306ce10e0f82d4ba14938c2d1d0b8df34 GIT binary patch literal 113369 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 literal 0 HcmV?d00001 diff --git a/Tools/Jars/commons-logging-1.1.jar b/Tools/Jars/commons-logging-1.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..2ff9bbd90d63f92cdffea944869ed9bea7ead49c GIT binary patch literal 52915 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 TS2tko1Nh1OwZ!fF_38fs60)DA literal 0 HcmV?d00001 diff --git a/Tools/Jars/js.jar b/Tools/Jars/js.jar new file mode 100644 index 0000000000000000000000000000000000000000..2b926505d024e480e00e18ed2dbeb4359591a8ed GIT binary patch literal 708951 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%0AY*%HUocuJ{9Y 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 n|5!#o-U06V%l5Y4K5y8Fiy+ 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

0`;H_ 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

tLcnraz2eH)?S6Z^~ zs52ITvoSmd)maD^G)?doTY@HisiLrx6rG){B(PJIBz7vA_7zG7J5%Y+E>!ko7byeS z#mXRdi87pBs*GS)Du=L@$~d-4DP*ga$?O`XgsoAgvUSRIc0IZQHz@Pijmmr$Mt9&Q zrIFpNG_hNhW7)0B$?SGz1-nZ*i>+5KV6EsPY*4OY8)FvQ6mN?ofVbk11{J30$N<&2;t*^RO3LGJA>n*~=`8 zy~6sl*Vq8|78}Oi#^u4g>=5=LD_|e7V)hA|)-TaqeudWJYgWy^K?VLTD%}R%u{l?B>zq1S2AM9H8C%cjT#coy=cBjhNMpb1GsDeGJ>g-9?V9%;C z>?PI1URPt;TWTEpP>pAwsR`_7HBsfNPmNVmRj=AZ%~bv9MfOq;QhTd;Y9Dos+FvbD z_g9P61JrVLfI34Rs2-^X)M_LB%ab+CGhI#fMPJy1OxYhI|1P%l?=)oay} z>W%8b>dopQ>K*E6^*+S5MIEO;q~@!Ss^irs)d}izi2Y@?P<>6EsJ^34R^L|-Q$NAh zzEVrnZ`H%qpRv_8wSsfClI!XW9;eRYDe7#VrXDHH&!6CjA7LP?BKJ&D$o!FYR;EKX ztCne-(ZQ)flcXuvpgR&|3o!QrXhg0S14l}N<| zM`J8T&BRz8#ysp!IEO7ld>qC4R8~*zvIpRJ)_^gMJqZo05o0?05N6=m6@#J1!Vnh1 zSd3Z#V_6enR*TU@H&b1;9KDei>2IK^j2Kjm*@l{@u*K3)dw2p{f@x@?>6hg!BWr#N z^k=_8f0>NzSTeGCWPDD{6`8k??Yv!jDgfuBU7dq?_umK4Q`F0^YAJn?!~;ERM8H5?aO)?&OKIDUhf6xnH{hZJeK5rp9pt$O0an z$HQ&!k$LB6ck03-(XJem>Fu=^;_O;vEXW9-q~>a}+RQvohS$nnp`q9RWwzI&Zh(_> zb)UWxO_KLZ+idD&^CY&Y35;60F!(dQ{nvtt1gr$j`}o*ErmSeU@6(#4v5E~apN8)5 zBA;e?=BHc_CdGVOE1VMMGb8yV*Q1=6fI%5P3|FA#Z-o;Bem#OWhVZJl*_a~jdizl9*o|;n zSiP`Ap511qW9HR*J1x_@d@Ur|-S9p`mR~KG1;gqTcfGKBNPDERwLHy+G85s9wb0YW zIiv>}aGKpYTWA0I#%EoNnQfl5IE-eLXEk>OihRYq9&Gsg4fb+J&K{O-aglw-@Y8Fk+ zjm*Iny5h+4j<&CDoe|(Zy+&f4VtK%k!GAI`(=DYCkaexBC#dH6VH5%PjEOkMxGto< zxf3nLJHv61)jQxz46D#xmKs;9B_>KW)fp3AnV z=dlOXOVEM5ls%}B;z_L{m9oyS$|3w1U7TD^*Wr(Vr|Q`fM+(cRP3>r_)+ zr>3jdqsw>$x{5cdL)0+3gEyfYc&mCSx`Bo2UFhE3t(K|l(V5(Uj^swQPQ4!;$p_WN z>NfRQbPrEbA68FS|D#@}KBBHhS8=Vn9Wm`d43DYzs86Vy(RF-CeHwG0$Jh(_-;3(& z>Pzao=t_R9zM_7C?&Ob{@|*gG`nUQfI*)I0kNOTzR^R1*^?jb9e#HB!AM=3v2_K<; z$`9ti59JD<$Qdu;Dlg}p&)|a3;&Hr+$MXd|fiL1--oz96VxGj0V_viQX{rSUu0N=p_{289jU*S3YO+J{v!-w;a z`GNc^eh~kWkKn)aT%quhLgxnylaCTfJWurCqeTWEEBf(6#Xvqz4B`1=I4=~V_(U;| zPZE>(WKqnE#Nm93n8Az1zj&#r=4GOmPZjn2aB&QuCYJK);zT|}oX(FB=kb~1GCoVJ z;{Os?^SNRjuM#)%8nKZF#lw8Qc#JO)&+&!gWnL>@<41}2_|f8HUMIff4dNT#EOzo1 z@h4v_+W2x!zbF`~t0(U#KoI(@ z9?!SviF})$#vjtN_``aC{)j$+Kc)}ikL$zvQ~D_Wv_6SHqfg;4>lOS}eL8<#Ka#(p z&*g9G3;0`l9e-PI;_v9k^7r%;_{aLG{1g3b{;7T;|4hG(f3C0QU+6dRFZJ8`*ZN)j z2Yn;|QQyLU(jVkI^+)+{`g8nu{U!bm%h@ z>7Z#TNC90CF|=zS&8nf@j5J#{p21#OX`kA4bv@0_)$|G&fXj1=O~;;}C39EfV(V;5 zqh(5DfrBw?fkUx#q&l{g}12=uyUF8QM`lSMDs* zrXoPIwUY?6Jj}(XpZ(sSc1y_!l?J@u467f(X z5}-nOVU|dOc_JAWh!i+V_~01P1C|IsEEkz@lIRVmqr-lV=qDGxlR<|;xD;)XCls@g z?=;E+@^QRt<>Ige2C?%c?~p&v{_MHz0(;;040}1r=tsZpleUAf9__Mf+1@xbnqza2 zt-0LCiLu{VJF=3mC)s=r+k6e$JRXKmK0YtEx8*q&C&_pVGTvy5e=f7?aE(hfHI>SVf(c!9q|4f z$#;x!bR;i^{jl=~fG!3=oEQk>L^hO)9H*_4cuN$) z`(g@wBud~5Q3~ISGT14m!k^-BXcLu+5Hq9{tbjPE#JS!g$9@j@Y|CHMc@mpafwXB(RWUnxthy!Xg!0Aw-sEm)-_tV?fWqF&-9L43;t}c zDP6A%@PFEh-kQs!JB8j4t-W26hMet?5y-KI?1PAVg+qCCNx1D3+1Ti8Z>+?1A^uN| z?jWc3Q0ZP}+NYJ$0oRF+ivr&F$&sveWoj~0$joul!;6Z-=`;bvY@F0bf+7A5@nQ}n zin-tyRgi)2{Y5nl5j8MI1Yx|G4~1d@942aUf*%D(h@;_Oq7EndB3LNuVUcKnkZ6P! zaSR+QLU5L7g7ZZ)Tq;`N3b7d0iY0I}D(<_*a#$~pg$KlOuw5Jv&xjM{@Gl1wQc$U0 zA%`##mGqTzKu|5(v9*wBsb)9}2Yn^eu-pT78Y#|a9mVi$WT-J_4K<2~t%eVS6*fKt zcCb}!mQ=&5*;V#&(cxH{RBl4HCK-QmNe(h^Vf3bnywe~~g&48IbsCl6G@f8L9)ou8 zYS}oWKW$*6{{WjKEjABj>XI=TYz>Hv+i-|3rBm@G+i?v~@2zX)Y2lI`bik6e#nTE) ztRY>pRV>`%p<5kG)In+n9gh#f%s>X8+X|Obat15Q&e#B#Wke|+3kgW^SvbsRgGZbL zrZ^9W`F!XjEfTP%z3rwo@Huwco>E6@j z*Fi3IFnvgVmN)CzGjn;?nYm;mm-zVLT+OGkwf3f)bs%)*3PlOGJr+=rF;PYgrh`@S z2#V;VD4yFPP3%A|^ceIPk3+V25;f7&FcR~}h-Xn7J?9+eC&Kp4}PZ6o1!=NbJS5a&XZDyL>ol7g|B8S8AC(@7dKQ6{eJD5Wpq zlzIiV=Btn_UPG<Q`o&s=W}y; zX67YpAYl1BD|c9zU^c_5nHynsE3CBBeH_)xRjR!sGK37Ak7s&~HY$x`YRmBuc1JEi#q2!m?6GLee;9srdXBJohrLK6tkGf zQQzDnnb-rSuzTgOmp}?DX9ZHFuXh+*V&4=?Oy2}?tD>WNLPw7N00|Ctg z!?akJ*baB-8P4Q|ZZyihBu^RmQO&Ni#decJ;|*AkYK}=yx~6jy#oU~&*CUa_Cemvh zcTr^y(kaOm?aAFA4JY8jEmreFvW9+umIPT^GVHJUV6c`7BeWhcT1#`0JjNk;j7@Sf z1ZC_{1rbX!VdSy(^jnJ-HwCn9@mlp=L3|wSpLY&qM zd|Gcv*ZM#|tuGAH`oTzTKNzd^heBhbz8J`%)cUFB)T~XC6>)3C`%u z+d6b707A>gwR8?j&mio|V3e96FiIN=ra2v(CRgF) zBTSX<8g=IZXE@Hbr99AnI5c}Ww05%HL0o!~9nwZ2%kz-shak&GBg@C4$c%%5TE2_T z0f(A^t&k1q>##Y~Ve?i;U50Jnr6gT0#&MmBtMRtBHoERkE5pc&d?dXy65*ul&~~JI zbLp_;IXWzPR$g-=O%O=WAkUlTMu&-62>WT1AzLd#sh$G)+F{7nGMKDQg(9uo<@J;} z9K=m*a z617=4$g@#J9O-J=ZOI;VEE!!Vq?Z5Vuq)a!_VxJgv|NQP&%>6hvE>?UIfyMU*kj8R z?LI%k9<^J3*B+=KU2n~18(wCZp9_o1tGvzT2xAHIk~4IB0F_aQ1j# zjEqzm`er0m$+Q>jw0U8w^Slk69qq(;@M0&929H(;3ECp)q1B_@HKJxc2B&)nr+X8O z(VB5UTi`HlF&wTff$7>(n5iv;Iofil(T;OJ6ef-Rf1k-K*E_G^1DZu!6HJ~`%HL-%{- z+LiA6(ru$1(2LGJWv9I67Ehib)s)c+hlXL0-`MKY*Ft}M(;CRiq?^KiL-pwqokoTI zhEG@LrkBy1&&`l;F*j4bwYhY6-#SH=3Hn^0kP&09Pb&-fbgzaQW^9xnQy>ZXaS3SJ zr8vr$p_pC{nc5Yo39p14Z6%KKDj27&hN;?BII`D3m9_?IwY6}Jb}gKOBXf?n4ldPh zfU7lY5%Vvr_YRM)VUOFQeGPj;jyA=fv~Qwb!=92i{3%v%U)H?Fx|V_eT`9Gej_bP% z*wc)bJBq1waFbWB4t_M$x)!yK}Qv6pOdewn>u6IO3e zM>1a5jwZ^kB|Ca8f%eVx>#fW3l+p_0)1wAft|GMUs0DYRXg!83d>q;Lq-!cgj25nA z*sFHiuQ^Pqu-oooHCuzt(qiG-jwfxF|EWEPn(BF+&o8(d=;3s(huwgO{vw#&Kp~9+ zz7qrK2YQXA0bC^l&P<>u?s%Llw7=+eS~U^T&}a($MORM9~>_^OLJ{G`$R6^(qRevR4Tb%(9AxQO3p)n z?9CqJYkSmtQdLTIOwh-o)qiPVzc?Ud88SxvLyai?sc0H*vh!$7Jd zrr?&lG3D0n5J#^KP_hbQ`2%oUNf@&2l(E+PcB*+JXe-nCZhuGF)HCcV;XERro)5A40z0#2~Qid;6=mw*ryR7J-8%hkLw2W5FK%5oKQavtsn_!c4eQ(|d_u>EYg!h&_ zjSla0zqU2kP|<4R;^g}kdRummFJ=SWpX>2?t|I&Vw$Fot*gBUI2p!S>ZuJd~;B?FNR8N*#HmB@Og4${KBUX&x`fPZijPyw%(et!f5ly zA_McxL3Dusz>GmjTj}LD*F*p9&|AK-y_JwM$UArgJUC;JorFcb1Du3=WF^gK49<=7 z#jOVaAa9ZDN=@FK7aMMC3AcHP&<*gA#JB+-j*iqFWQ>hEP>n^9 zY}BKyH=?#V26BuL3^SS_*Jy@OMhlEJ7Nh1_0#l5osCky5<~bha{zRxTPJ%k)WLR#T z0>>kKs&N`zXq*n08fU_4<1Cct`aitPttW?sB)k<&UDrJA;YGt5tjgn)mQAQfqO3Aqr*GYAdsH!T* zS#mElNhvYmFVuFV<4~KyyQ-iI@vs`sm(mnV5@XK|jH#MjnXAeuRhJte$;v?0P-Ez% zMCq$~Fpb0hN~)YW0&*0uoG%&-Q)1OvsbzB&P0kzxMxk)tBb_EgHPtwK4jpEH+3!aQ z{15t-%3Tz}hrU%UMw#jGX}@tJ=mtubakI+_@<*H?`b)bu;^p>oFe{LqgDbm7P~Nls zoWAvWbUpORk+1EWU`K~#gK;98A$XkxfvmOr#HvpU4j6$Vu>2o|f$w znBmv%%G2$r{@`Y~ZKkpjo~G~6v7Cad*R27?kGAz0ETe3KXYWGF_Jffy4(OA>@$&6D zqA>12{i}CAYp-`cYp0FXcg|>p^qosA?wB}O%Aif~ z++BmVqH(+jp3mc9Fb1i^aridC3#er21ZD?lxIW(uFU|}g8(yND0%W9K&Q|=I?0oyq zK93^v0(uIsfX{dp=k9BeX}pe__ARtmZ==0>7wy#tICnpSLgQn{Q|Jk*+Ead!kL2Mj zN|&82aXMS#bhboxQN<;9wp}9|`qCdb$Igv~1T|CbMXo*lv39H5L#uG6WdNkVdJnu( zDtn2e{%T~WCRccCay5K(CC^~FF=Sr0qadRTK;DG&lNz^D3T1A9*K)Q)e9lAgqAg)c zo+o}(Y|eJ2z!$R`8c@n!UkL`P>oX7bE5lZiRJZ@ngvcS=S10()+De zcpG2uP!VJ9;JLZ+5lAN}fy%t=iyyuX-fM;TC6JI)p`a)8Sk5+hF)vOj@yD%)53+Bt z?*t?8;SN_E9TkpPWufih^;t1Yt;vm7a}$(2uPm0AsOBd5l6>)NV2nQzdtvv_pSTG= zS_v6`?+%Fb#ru+K&`H8NUSEPgv0_DnLWS?nOI(qJ2Iyg5!b7#bS5O47=GH>6_Bj@e&JWBq8zyvGud7jr|?2x=f zD{^375=P$6O{QPpxXGWGJrmhGi*`%a9hjTqOTo2SkMnV5_83Y~F+l7I0CBho_q~J9 zdVs_a@Ocg(DG$Jl?zR_KXg!+nIRYP4Mm>h(GY}t?^Bz5LCEtb*uC`KfwUfF7pNH_- zj87{*cj9w1;w{1lm+~n;AwKkj5^%Mbx)?ybhR-T|PQfMS_o!9pVVURg*@W?7NZUvF zprVYu5bJEi^mX{0gD}$IISwG^M8r26=^ceQrX!C2`1tWzEw{Zvn?QZFo}@|mgfQ(D zEQ|HTA=c+C=mvo9i$3Zb*2C)CKTa8>LC1a=yu(w6xY2&;&sk6W?U?ow(tQ=uiS=Se z?2A^K|!?S=t#S$M3dm42}8i|vupb7nwaR5HG5g3@EgUG zA?*O?ZZ#ZyDd;K8zUO@NchCGfD*^ z|Lv)4*=8&JnJt@ag}+?6cUa@=kVSEuFeUukh0$DI>)MH-yO2%gb$lr&c-;R*!ojo(~sq&@zd?)0lhG783PNG;Zik(8S z6pAgSn1^D^b7jwbsYFewMS{2Y2~mQ+8I>9(I}PVyo6mRr*;u%bo$ZUz>&;vXMw)L4 zrchB|d3fhva!wK$*rY&s=hu-sQS3e3-IaYzr3H@MEdcs89;t6fr}aqlEf_`fi(*Gp zEQMkX6!TE5X_Qp$X+5yr(+H_-;P=Svlap*`oj(p`1<66_d*5$tQgCYQoUsSph(4dC z*QEN3)MQvQbFa0kgJzSWR)l|fs|y6On9pxuF^?{QJw2cOT$znLQ+Ne=TBE8|83332+{;= zN=DIk(IaXt&7X#?C1K~%Wanb?Py*5-?fLzwX?~gR$&;ex?}070{PS^g*b?hz%g_BR z$xzG)2eHLCY$8;2+Noxg`k$(7Yk)&fBE3n$WrUT2%_m`jaeJ1{RCiTZcUMkf~k!^4tXl8Q_2W|TBC(QTp}rJR8d*aQ8;y1(}DqRQ+Fj4IWt7_Q?AsC{vr33mYF z_H@lEO8?MLRb7~nm1ma#bF`tFq%(G+>LqZq402HQLQ|q^Y=*ZiQ~o>)*X9;lncFfl zSPs3p0+fnvEVOb|z;>ZdB_S(W4tpIUmXnLh(IsinrGZwfZX;HTYFf!|=`$TvjkQXk zjk?pJYOR&4?sk|4UMh#deox^*8d8?&S`V4DOxJXj!ZFM2p2mMF9<|jOT(<3TB^R_Y>YnBCH+o2gprF9qvgCV*76ob9Ua`f5J8-Hog6 zN>hAsch5|_SZSTXkGqZ8f^xmGyJ!0T$EjA1@+3_o*L7CC^15mB@Bg)}v&pXY6vw z?$4=Dsxq{rmJHJ^sEH;A=Ty0phSR44!(n#4D;>oyV^S4I6%B>dYU#9$h9p)7R)%-h zQWYWT!{xG2UPehDDM?MMw-bo^BsyqXY4EAg3946VP(0J1xH4}S$@A1D7Y&k-ebFz< z(R-)A`@2JRKJ~K!tDU)AZNY;?a{cds-YARE2WKzv!>ZM98lcCUeYyQ21&2^)* za#ThwW z-95LGWYhltp^vf{ttE@*|7R8%Ou}B!U%ic8gX|KYQ(*2x&F;_Rgi`1j!0X%Zg&*=8oM(#LP|a} z9XhIzJYOoaBtEhNjH<-;&clQqyF0{JUWnAcY4sl`n?v78iS8SBwWaRSIN4XJv8aHW zE-!Z~c2+mfFSvsfpQ^<&TK(T5y)H%R6B{oOtvazXgX$_#k5)z9lR;fAQPbV~3@^w* z=~f}FaOO^;GNs*e3~9N$Yf!aKowWj-KGEK*ey{MU-vYn-Z5U9$IYISXTgH^GO`avS z=zQqhlMvt!?e#>}wHQ*%>wOLD7Gs5OBHOx`55=B*pdOJ6Lj-ATf^f~sW69vlj z?}h5Mkv}e{DtMF%qb}VpdVXUOla|AAR7lca*GNmv;&~MyL$OV$s0{Vliu%gd_mhhy z^`4&n*uq!9z3x+$aNbThDVyyp2&JKI-cEFFWul2p^sh|Rkz~VV!mARN#0-!LO(mGj zvY+sTRrhP<(+e9!>d{TeQL`L}T`gH~xOyrg70rrlK?5~V)KM$y zQX8QXs9}WEp;e9xisTxRa&%n*R!_0~>7$Kua`PN9Ntx_YuNWk(aK-tz)YG0Xa-TiF z(<8OZV|Zz4_YKGBL_J&-@X6@uJ`syc0?__*Lp|V z*Bb+8)irP~lv3AFwa^gzIxJjYUBh|F*6Nzvk=&Jh3x?a*186|33fF{jxHjC1>%t6N9~R&oScG%oVcY`-QjAx<0 z<2%r6csAOD=b!`lPIL(0jlRMQ(Fwd5{fZy;X5q)ZwQz~I30^7<)f3)!c$v2kUg5nK zOS^zqdPm|_-W&1r-kb1R?nESAN4(mzxFM`$9zliao-yJjc+6V*0&X( z^u2<=^XPR&cMAXN`w5@(Q~aA>;NSgO_)mXzeBOU4 z0e>Tc{7s3+--`JBJ&51mp9K8Z5$eC5F#jmR{o_d3e;bMTXOgJ@E)w(KOAP-bB<^2M z68@)&>0d=G|8peeUr)09r6k+Gl~nV;POAIgB{lp9$tC_zNlpJ@Qp^7ZspJ2a)b*bt z_5FX4+<+i?0h8nhQlw#^K4}zaLK+7ONI{?@X&&f7S_FELD*{7EtH6zJq_HgG#> z7nnvm1ZI*e1G7n|z3WpYhm2k9AjjT8m;lm3B^ z$bi5ha$VpU85B501_yp3Ljq?>ao`*o9`uqCK}>E4hRMiajEo5;$=F~vxhYtKj0@H$ zWZ!r<3rQSb!0KX{Tn82o`e z6#SVi3I0JI#u|A9bMhz-k!9ExITFbk08(Bv1BD4N1nx#NE%NetMMIV z4Zf4C#rKePcoErvmyk{PZ{$V%Bq_tI$xC=GDaV`17W{Yecf6Zy#cz}Cct6>J50ahu zbMh)aN?yk&$s71I*^Pf7Z{pv{TlhSAmjuXrgphqCLf$7P*-u)K1EdZ4fV3wckuKyQ z=|(;wMdVY`j~pU{$q_Pwd_hK$qhuyIMrM-}WHI@MJVH*AC&+hXEjdLtkke!fIYai4 zA0+pmC8vLqugO_S`HRf`l>#|OIr)u-$e%Pp&eOUSXj6)4bLyq7sgL%ce%gx$Xnz`{ zqba7hQ%a{%LFZ7NK14%w6^+mhG)gzoI4z|Kx{aFjRcg^aG>aaf+4K`yjUJ`d>2X?v zeorrS69t+d@EJ1TvEtnwFM78aNbeDY z=^`L2(~_NGzofi{eHO#deK&}HHPdeK4Wj2mLl}gHF)cKP zc|#MJFEo|;L$g^RbQhzc#f*nmF+KDgi-gv(XsDbeLfe@Ys$j{`UX}_SU|FHBSa#?P zs}?%Ps)wVjRyfIOhikA)!*y7laD7%cEVU@yl;wsyvb=Ct)*#%AH4G16jl#vOadVSOX@S-;3-?Al0c)<4pY4U81A z>mvQw;K(>OBr=5+N2ar3k%jDr$YM4!@&p?dd6tcitY$YxUSMM)JJ{IB9(GgYGd3>r zIlCothTR(Zk=+(K$0kL+Y;shv+oNGNC7R8qMjNr|(WY!xv^l#Y+Lq0ZUd84_yR$o^ zec0USKsGNrl+BNhU<;yS+1=3z?B3`+wkW!Y-4|WX?vFmr9*C}I4@O^MOQO5k!_l|d zW6{0r@#sHTN%Uj3H2N8PBKkR77X6w%89m9CM^Ce-qQ9`Gqrb70u>e~YBP<<@v*%(K zTNA6zo{!aK>tc=B`dBmeLaYtj7;Dd7jCEm~V*^-eY!EApjbSgvZf1XvO<`MO)7g&L zEVeVYfV~!5#$J!DW)-pZY*%a}+a24?-i*D%-j3~Kdt;xlcVmax{@79WkJ!)bK=$Dj`_TM<$ALpU%uzhX zeeo3c$8&igeg((zHk`*haS`vw_4oiDiWl>6{1zUG-^F9``8*MSfSd8ZaV!2LPsP(b zEB*q{j=#vO$KT{N<9m4R_{aRx_-DLs{3NdzKh1OFKk&Tx?>s-@;SCZ#-Y~&O zoT$#5B~1I!Q~ zWJdX5GtP_6Y(CV?=flhve7MVe4+UUUu5p)_nQa!1Lk4=p!o$~Y<|a=m}mLJ<~jbT<>QZ8I)B`X@THc?|7NB5 zGV2olq*a@*uyXiQRz82mYQk4q1^ij76Hi+``EyngUtmI(zdXT?pZR1<5oqU_Mi@##M&$nA2@}1UK{8j51f6e-pS6F}YT}eORoy7c|q|Wyy z4gPL2#otTT<$okM@IRBA1SCrZN^TY2KoTOyF$BZA3y1x~&%(+31eekgeIVTrFTo7xV{iZD zumR{^c2HRb{>YnUJgHt2X;zmw66!FasUV(3L{ITlU*b z-YL*sIt4k{QLx$RhkqQbbNb=`!);$8a7vDhEy>_AXsR`^p)HJ^Q;aCk(xuzB?bEhx z+s0|zwr$(CZQHhOyL-;$W|Fy+O!7bN?Dwiwl~mRG9HM9wjSu_z2r5{T7Fg;aA9c#m zq*t*h!Vj0_7pFI2AhkN|yYL&V!m&vJhG|ja6O`9L+<`LKtqHY`+K$~c1+u&Vf^Bv% z%l4aMNwvrFs`sJ5r9LM&aIXH1?+s!DOj>zmd%+D_*NZmuA|t7$%3{&LK1mj`ZNrO4F5DXuDOBu)oZ>U4~5qYbV5AmsefG)#BJdBBx$ zzz@3WVz1Q=Kc3F-fbNEH*F?^|VRv#O@F!TUA*RjXj~NuH3LMe=cUiecES8^cN}zsF zwKN1o!J;JA04mdb^7ovO0zFtJ!u&48JFA%RCQwEbnxn_Q9z}KikvM-gI7}vWZr5LT zPF|G4A>=G2K{8lbXC!*^)hrX1EzX2NZ5nRe@pg2&elaLAkTCA*K#Ip$x7PLTpQL z@C$>7XchF5%iA!kByG0xr@>@iwo7tGe*N;C^ktQ^zuOgRxij1gISTuqDD8C9)_)XP zLeHkC@`h9$YqRjA?ukh3&Ai^sSHPx~nwH0zF%MK$L^%QLS(4yr*MJsUWf*6i4v;{! znKZHs!4_-e!*B+ICL2ktaEgZMYwHdTd9_R0YjdJ`=$cnAx_VKA!9b=t!M`siT)^KJAy-T^1}mR)TRUI|dDAC>n(!Lf zV!mv*%Qg4fG}n)oCpgumQ;YL>ju9(TC&6=oj$Pf?v{7*B#LYXJh{AJfCiN>~4&kI+ z0t1hgNlbFGsXP}{kAmZ!OmoDTXXh|YguvGdq0JWG1PNaVbwM@3;uEGqIwYsLM`y2U zYs#=3k4rH-;ttFe`LObtrU`}$Ev)kINk{BSOEpToe>9*zb!L#|2UcF{JjQz+Uc-Wx z;2??!tmD4x1#B&PS=W952xPC9Yg*ahNff!72pd@OixfAT3_K?_pOxELmv-cpm{clY z6EiS^q?9t7_FqCWE)|)Y5F4odFO`&Of0tmq0Q2X4O21^GF9{I#tdJBl|{3el~Hb#0&#X$ zIdv-BTz+f*vtX0Cn^=?|1%sJylW%pBxNPoaB+$Stz-i8 zu97bUPXUzB4GH05zFw01G`I}|>YRwVXlc|B#Es}4zVT6(`p6kXm0yHdpQD=PAJ9T* z-XEyz$Rdv_D*mPp!y&SyKqHSLr_ElT{0{N`0|MhKFg2iBhr(JhNef|SPM|us z^C=I7jgkw?VQe-eNub~)#DUemJ)lW}leFZos4S!_PQgt>x39=fO&71oPDs~=(xbq> zo~p=hq%TAlEN2WxC9-W4ky2m5lEMKl6jzse1QH2e>}2shB;aABP|XL;!G z?%!fJpd94MJZWx7t|13Er7FK~MsNA50J-7DyJR;!*@))5LZ|3oluN|0Y4KEp$Vf(~ zayQ6j^vyZc1Jor^E3xb$xFww{VV>d2GV!huu!vQK`n6!u@NKh#wZM`H*SYTlohIcg zA-V8xavHe2=L2A6N?yUuA%UliH;nE-yaK-nxdn1VgipcjQLnLRTZH;7-f-^bfpwZ5LkM?MEo?7{m^aePBa2EY2Sxq7s2MF_O^|kXtn} z_N~Ruj=ck!aUu1awB|Nfqpr<^PXv`Df?a3_iukDX#y*RyP;DmXGn2HKz)t7Olp_N%BNxAEJX?o`dMq!1beZ<&| zI+^=6qBxYJ0@kfsapkmeN-;K08O~ZevP%UZS*MP=>s1W8;zDYl=D8ncKxJYHy|40g zI&N%({&?@1dx56;83Xj6@x^i)Y_%R`CrsYQch>Nki7B@Z5zlKu5d~&em>m?m?yBty ztV@33^yLrlXxi|Q>&xs2Jb(@yl*EJ7V+)P>Il8b8&scNfy&zCe8FPxYpw-VCa|*S< zYM0M>rMmbZ=N$C>v%v;D_@Wo7{leXt(hJ!AM%@fs`E0@O9*-s*9PuRyDX$k%YzEnGL1+pq^}5-b(v zJsO2@o7~jDe3LW@y<{lLwXK{P+WVE&aWM{LUb+VO$Hxi9+u3gul)uMkJl&{&yIF*v zS>vi(gFigP%*ym2gFVR1id{ooJk-vL^mIg|Y9?^x9gDo1ZL;0l>y$^vJk)06NYCi+N%E^*tE2^5BEDp5y6d@IjfLvGsF!!O+eP znZRvXLyS%)^InZbUwWp-c1*=G@XRw#);IZCI0$W9Z!z48*G|kIx958{c`s3}m@?o> zv0P^xPeU7U$rPhIN(j@`;7U7J=){m|*Wf>m*uA^5Hjs;Y^c}k%8kH4DI2K0%wbfH-N5fT2+V{PnUGemMKeVu(L|6$C^fd=sS6J zT1-N$rlrd@UA3Kfb&R*irMDGYZ3?yvw=XN;Q?!$CN=z+;r*lAaU8_MdB>A;2#YrcV zrN2L7#~~Ve+^7w8A1VFBGrZyIyPL_mX4f^IdKGSkk&CydHvLIc^0ih^k_$I!A=Y@C zWpl|one|-E{gu-?j}@Qs+QqxkEzY3xYkDAPS8o$Tj(p15;rU&^11FkZ zqDP6-{mZD(Gg8-qZZiFi*q98`a}X!3G3%+9&^Qd{GXgq{LCr!qdo-_2XDqbIO(SU{ zq#PQTHa~nOP02KDR`NtkeBExNcLM%mxpb_@Z&8aJ(ma_{dPW~7t{70rPg-h4+sUSU zEY!htkd3=H%j;*Rh<{#f0?I%aPt%GeLWdW{$LnEs=p;m`g5n|tCz3=w5G7EdqEq82dJ+}9Q}N%s+vb8n2OTr28X=l%=z`er1bz9 zd?>{&4Saa+E-U|`?a=mxcb_Gy#mZ2UCRMh;@ViKgmhPEB@a>{+=piAX+vR6TZd z9pLd2%>pCFzs9yn4kb8OXcPN43BEZCsf@yi3XNfNMCyWm)2(yEn5Wz-*q$^dS zP%ZM%`t53^+Q88-8F53za^wpmV_0P)psM7vnjL0Fg@ON@Ug02N<1lwRP3|`+W~W2y?he{?cbA##d8+ z%&8^aQYC6$zg9Dq5)n0<*0g?5H*74GOk-))jyTN8TF@4*b@kRBwaM5MXD>FAisXT_ z&C2X3(284VHC<^Axc~~8UEXlqmT^pLW};%7Jtoz={rNdBhxAg(WT7i#l3JRWnzFoP z#o3rOJtcio3Q-#3M~`LY@XnF!G=6Vo!cj_VA|6{0_C59WA1R$W>uorD8+U!2FV1=Y_zlpC@^;pU0k_sDz{s- z_vlM9$z)SY6j46pU zI!_uqry^{6hju)%Oi$Tg2bCw2G-WeU5Aw*#8eGgsth+O{5fEOn)MUn|m)F#swVbKr z-@-gk%(aM8UFour50@>{&kJ>yOdT}4k0(%#s0fme*c65&zEVl4MSfNAwhPx5bv`G) zuDuL_0q0_4>MogC4SB`UVRij{ST9g2iVCi3^=3DpFF1Cxm4JO%vs4xI+`PY zo(x!hQoee>pC8dH<&mM`>gOg;8^{V^21Cg*omA+m_?tw7PcH(73?+MjV!Wo!0m=YF zi806kTFZ2X7{WQ}VoFbbNCi6ira8g}MSEBiaEOs&XXSd>M3ePuC=7W=RhTt)9~)%9 zn7O%sS`iUcC|Cdb`yCerA6w2mpx-t+0&SfuFvd49PO(7hHqxE70krZ*7z ze6JI=+_)tR^^%h}?$Qq!m`avhAWO?wdx&xuCv8sH#2v!O9MggO8AP&Aq7($^i z5)waMD1W^|dUcEh0N`bjJ@;;0)k3>-kd%L$TMD7*>?LrLiz*RRC5hf=?$M^jX z{ZG^qLilUcckl~VffisV`zJMMrYQdLa26GwG<#~CkZzlFoKeThn~>AiYj)H9Bp2+S zDn9pZpd7RvnSZip++Zd|Xh!yywcWxwmquSGAPlFkHIOg**d7uu6o4y>*bgs4*IA$( zlpVHzXD)N0uNi;q``I5a>bXJ#N}~{7`h}^l(U6)6A2nmI0WsNuQh!hgw$67B`cUIu zP+}k){k_pM^O=KGFt4Fey^t2-H^V1Z@Ld>~o&$6{Wj{{}w_UzCq0B6?-5AXsTf3!8 zF3LO%`N^K_X0N*_&5Jf9d8zjG>B2rI$*qfv-~SeRAn6$=GN6Bybr1jm%KyL6OX|Dm z3mEC!IT<^UF#Jd6hm~b)7x@vqGwI06&7~xP1-y!?DZ&?*DD0>ND~MExpzOp|;Ide6 z5;`2N$6P7~{Ch#f!})RE0Kf2t5E%>wQIkc>hXAE=veUEOKV3|&Z25Yjv7TkxN%41cQ+I~F(-$QYY|OYt?b z-QsoBtd&GhqtS6I#_B;&*ts~J2GF;O{h76DK~+okui&`39K2%X8*r!sb;;|VDyA7y zsJe4R_$Ok>|NhAJ<@_?nc>~TPjd8nhlX(!`)i^-b{31AvJOSBMU-a--oa4)nqiw{L z=D^2vQmz^D`wMQi7I)GChhEn+4YMHm`TZs5TjyfDaRPm z-+|!Cbh|9R5;xqb=!t<(wSpp%tfJF>%_taF+YSY?WEzEWJxGzKq1^IcULT!{F0!tqXU2*S>HADy{>&A6 zZiP4gFmPmMb}v%c8%Xp4{X%I2Mn-Ek7%0e*R$t0uq7t}ej4;w8s}}KviC$@Vha9Mi zj-zK270-A^{AZ)eBDg_aA~xm~#bg^dMcIs{sHd>Z;D-|A2+Ml)`$tB z%GQ0|vHqq|bU)u=1#1M7y9EYor#&M?=skEj3cTDKX6{W;x0A<^{8{(vKlgr225O!Z z%?vUat!EDVXy6cSGF~K@N}clI%lkUIgx0RwF{PUkL^W{kc$aJr#}oA!j6MYJRZSAy zVKHKXoNSG9-MDtwA-QOA3;1$HHcZQq?et=21M8t6i%U(@vNpV+&u?TzjdWRN{jwS8 zVl)`#t<#8ndwcMzGDnAA^w>mk?qpT7^V$ylwKf2eE!euKfY5A!SNYdDh&kcN{FX46 zgDZ{02-Y;?hMm$2|WXg7AY z^RKL5E?*BKcMldAyyylVs0{D5*?a|I{!1yN>xB)EuM@R8lS}9R$Kq$$o5~YY_UaecBW;`(z8s}$^)MyTo$|la8gdksi*->8 znre2*;*UW+A(!U*Y>FY7B>kkVo-bPeFI|3D_3Sqv7yw`&3;=-Ve%v`or3pS!5rKuxJraX%PHHGFGb|0ZNUsP(l-@3A&`8Su^gkAhT_S zu?K1Dbr5cfXA}~@FYwV9MN>HAbhj+_3;GLx&&7ral~lhmv*Y=a<=Fd~eVb+D`+J$n zayDj28Uh0M)Hfuc0XOcz9uRAQF%SkpMvXtoNHkdw5i{u{=)j9;smw2Xv5Q{& zjnhv7Td(RlelLdYQdz98<=)?8fR5FoMn%3#kE~5+_f>mcF&H#d49h4ztDCg7skXxHIQK=%az%R zrZb0WSvSk^3)8bkK(1h`Y9m@>)AhLfk~yG5YGm9VC?~BoRb79$+TCUD1+!T)XLVWl z0?Pw6)VUO#O)$YA+jhexkf8fA@{fBd7ECFf#hfAikU`KY_e4=*HcJiNstO}=?r5fMb{bh+uvj#evSI*%Gk8D*t zvuUT9 zL)@-X8;J@}7US`0LgVpm&hE}TpHq`+(J6Yv$@Sg8J0azKW4s|8>F<#FIJuq&`;jx~ z-*|8l?W8XoxZ!8Sz!Q$>o5uKSxk{Cs&)GHGz7J&EBa{Q}GyljM5o4hCe1cAty%Bi4 z^_ydkp4SXj#9+~@@R{8uM^D(@CHC&9T1yh5Ejzvsq4#^`BxDuqvTg6 z2^njNa@JOoCBiXd^|}>$@2f`YCY(|5D;;Y*4I%I=ocS;VfYFI;5O0YjSA@P=S035^ zyGk%WS`>kk0{}p10s#Db0Bjvh>8x!%%&n~S=`8+rB94X*=5|hW|5v{MC(XOHApa^a zFY})EusxcP(rxks38@bd1yTF?DF6plVG#hr1^}Xl8UgtmkO!qI(Qh6@?V zC)*49!T3<~CvO?w1G@J&ZpNM-^7;_*>i|2|69@X#mGZ` z7h8BXH1|Qui~nkX@f{xJOFpdx^ojN*-Swfx{uOlb(8*w<_EB>ADvt7?>gzpdHSVjW z@e%9TMLpO_wC#nwvwe33`rbLl%+VspX*M+n6tG!7J4ML(!bxfw>GWgCeV~hl*SSY8*mz1a*W#hvBsbzsIa03rvHY2L`9cYsx_Q2I!$?N_OoAK$&F1x9 ziWl{{JS`R$KeNF))T^y;^bIZfwN36%P+8HF>qpz*D7yG>@Iwva4)rveIc>tpfnSHP z&V^Fyc$pl(=Q0^+hj!8-lz+`rW%Y$sZ--LaPHPYEHV9sOpE*CQ;(&>}yNn z`{Vs)Ys7WZ6%-pS#F*BJ&P{XD)mETHdnto^=fq7z^yZf4U@~aV@DevmF$V`QDE^70 z>@-=bOI!9kDN$B3)2G*N0Y0Nk%t{cA<)-xVC-q7OcO;p5xI8Ww0O&yCaPc;p1(=*_ zATgO>Vlam64@ox^Zt4ADAx8zPM%Y zWD^5co&z*esh}?9MnW7taC`U(M(mAclt^8SaI)Db63$J66XeN{n2ED_i!5&?+bx}d z%rvOaDSvO~Vd8zGq2;RNdpohvv$qPL_N?(N>L7Swsw%sQq^LG^z23%)!SNMn;(~Xc zl{VT0>2$}U>SKr=9YrH7s*WG!gB(c8Uc;tdRS6 zY$Qv?DaW$)JA3s*{^fB$Ac3lC`fUj5R&qmWEUEbpkG$-&EAhm0^Jr47JD8f80$BGq zjPTZ=Orl4FY=trzf^B~aABJt?eK)SZxqXgJaNumiT8mgmd!tTXy_B0+j=QNYq+Fbd zuo8E5-XU)Ul^hFb8tDG6`d`uG>Uk}&_yg9C8Gd3!iCqg(0?+j!GbPWOs_8;N*b5)T zyk*GOcZK>yJ#{pRsL%T^WAP;s_0{vv7+PT*(_(WzCwSsfhD|K~$68Tg#PhYrbKmt|@36XpnSLwdus!US$Cn1Yfkt z74S9|H()@bU+hK|fShe%9z4I2E&WoxgjX-tO!O>q5mG-g++r@DgEo<(ons1AXF-!? z_Di0{pszi`-5DV+-&RH91o}T&O0(rm8=9>j&i98tk_umiapSSVRo^NS!Q(cfCR1v{ z)1RS~WDQU+Q{&T#&ZuVn?^Vd|mHw+6%0Zr=$P4TD9-c#W8 zMSB)=lS4b1=*F3W$F>HmkEywA}A@T?B*V<{i zuc>$SQ%Kh^&6%66I2XE^$4^sMTEYg?gZ)$^I#WrQd&$___6KT-qZ>8ps|lpyCx^5$ zjTZx)Om!ke8&$yN^sE(m#ckAC0NP`uV9|M-h8K9(SQ;RWy+ztQY*;<-*q-SL^7h-c z5&|mJRHJcVvlkVc&YDxs_6_vu-;;dxIX{UrJSBI*_S)SV^P;NQ|9of0B>NQ!4*JHu zm%PpE9`u~PR9d9_={$KQu9<=0far188Z+tmH$CAGmj=q_}GI1++Ckqc8D^~ zSY_MmjD!LBZBhg^YWx#l8;5RM*}O!8Nhbq2FAr9$VEj4W$P#&LWU7Sqm7ZY^;WCO%MA+C*PSl56 zqOOi(Je##!>NbCi%f%;p%FM6Sl=VAdC%|(mEy{Yy)cTpjIl8!}dD;0Xr<#{;`nh6V zm8}fh8gD4j+BvafU9olTLe*nZv332zrNyc_nntR+dD(^4`We(&>^BX^{epON$Goz0 ziKS&DzsIb+)4Ey78FC3++w zqd&3fd}5-7Q|!7yMYws*qP1gI^|cb*>N#%%xH18=-fR<%IbMPjvSm4SSt!M0P1SRm zxMiahulZd$$FTByAbNByfIe25-fFoRZmmL#$EKXj%2}Sr+>!Q_0d~Tn&9Jg`iBJm{ zjU-1EUi|`7>pRwCMO9Bh@4C6A@UX>0);s=R`3a?zCXV$fN*Dlh_P$<#vC2`?Yg}5j zeh&BusV<-lx%f;wm$UV1$dRX4@d|o`G*TF4&pvA|R{9!BfYxv45fa|lZCYkqZvAL2 zk5Uv4@!eG2RoETA869J`e&%`h*6J?u`CE=3f%QA4%6GD8U2}q*F8jp>ZPdR}gNn zEB|Zxi2eqr^^M3mz53wX@_`(3$GQVY^9I3^pZ8>{^)2GH_$jynUXbXEdhtu@?W^`% zx5Q`tO!u5`9A{1M_LqFH4mNS80XBBO8D^5zi(Yil7Q~8pv@U%FmY>t^I%qpuJ3Y}9 z`(4!E7-d6r4ugaz5WHnVS)(AV{Kl~Al(eQU+F)!91IU;q1dEV=0ftF3jq?W|YLwUx z(*UM58nG|9_Ncmr0m(pcmt2ZvL$us&bO28!2RpJ^WPo0$5r(41I7)P-EcPg+g#apP zdNL#4$gS_aUe?O8(%GWBia~D$16a(}DI@=AT;1ccfEs)QSxq7UU+S3Pun~4VB%{^b zo1K@8qHRewt8~?l7UFZ=gml+OWz) zAtuJ~CVk3YBSz!{FJjG$Z1>NA`}~RA9a;K`5xJ?k61!%^o_fZacICHFxu>Q|M>$J- zPZJMXY!Xpqc#5hVU9jzqRjhDgxI_!X3_F|@)}i$ev+oEiX&73H1d~FBgE{3=D^1}7 zYsJ#EBAOHmuIVF90bb%B!5eE2?#*PH)#G;8B4dgA1@|VqE{Z87P6)$vnorR0M8*!g z7<@ROHu1z5b*e{NDaq5Zeb-_;Bradx;|=QfsT9wkB02(KyNgUW ziU5nj{ZW>1;MNvxWMMd2e2&LzDDvc>yjCu8--d~|eRS6HMU+j{2&)98d`da47-h~@ z?^EES#{7x6l%+CUsCPAI4V%cvt2Z3z&BGW6?$Wju_2_>6=gFp@w)WEe_;l(hXNoXw zR1*t(>q6AR#2c*;qS&-sip8C*?EXT4&0f`k}P9Br2>@rAlS@lj*?0X6q|PV_|&)Lk{x z3&rrcdlyO=x=;04J|>8d{7atlw|zI7YCf|Vtz-nD>*blF;l|&zJEu1a&?JkqGLx!o zrV95_66z*H3gG;C^J66&O@Zn1DaRyil{@HUtD}aQLlh=$IiQ)K(^31A#`3w9P1HVf zsfv8wNJ&ef{4z72b;`|4uQixwmz|GIl`|&IGy94StcOH+9vRm!x^Z^h{P}x}n6bof zC5`C}qe*xx5YHp5hcl|Vv%#54Z7(g!%zBXx?Qy6voJ9t5)!Ls~%mixL&!-FtEY)^5 z8Xg1dV$Z7@Syr<;o{E$a=1QOO5Q0VX^X0Jt4QcIpD|*M9j)5P!BNe)?^?$HE9vXL2 z6$@x0KYj#F_FBi&)yf6al|Em4&P8bVamE-_@Q7n@?RQu)Rw`dzX>k-K>?B(35^|L1 zDj>yH1Iny+tCG*n;@`|-_KtknD8rfH*-C-j*8Nh<=hgvCj6n#g@XpN^ag(p^r2Uja_ z_@dqx$So7+4Ro)t#>rmjffoJyPrHC~t`|Y~ zj{Ynb!j(h)E=HdE9=`gd!jkuVx84loBe0AbY~h&ts9uR!I231~oxlAQr!d%v{({$a zt1_{jE}T)ouu)}#omhJl8=?%)LK0WU==y&pkIJ8nB|ynR(idaD5T0a66t-m`P>wPSa>1PllR`$HlE{ z0oPstro93@<=U(BY0;$ay=grfb$8@iB{UGBJ%ec-haYIbbtz#ggkhx)9}g!HY{8y@ za^hIo@dvmT{-pk#(bh$KosngD z#YK$(8?E4z$Qds4K4b_?Rj5_w|7R-6@RKSm}gX`nthDedTXo#M+Dq7DHGYxRXk0_a5<(=C=wIi%Qg z5YC0JMX`{aQNTiaJj_ap?hk%?6e~OIr3_GWNN!&M|NrV1sAc0 z>C%}@=V3jJTQ>{kXMid@++PPy2sMgYk@?mYWrpCNU^xb@f1yN|-D5247H&{B-1P*m zD5Gg8S$YxfGBG=F!9vAQHguFTA6=HrZ!@3RjlD8QUlr7|{KWM}j#!r}5I%CiaLJ;$ zc0EO}4t}wm*i68>M|5d*<24}WNXf&J-VfBIoV@G={@64Iq6h?$(0C-Sh!-kbY=@9A($;gi3LpjYC$;+b4 z)YRXbxGpAj``u-EV0gJYJwv@O2I3dgT{?U69`p`O}m+vgmz> z@;canm-qgJu)H|f6!5ZO;Q{i|fba5#Fyp zoZk8nzsULv*qXCI()R@61T*i*8ZYEodhXGYc7H$47qWYT_-+{*hnO458?CNtRq_(J z#<5xV-TxK^FSr(Pk0(K@-T^Mjg*nzf2~AEZ^X+}_r>P@if;Iy#+;tw(ui~;2jz@%S zB~7%sbWF+Fj0`nc8bBnc9AmL=85q{BRPgC2Xkt%7$BA(TL-nv6!hP;hJld4a-GUq3 zoD}DnBD8*&T2s`NKlQjBNb`Ek2JN`;8`128f!rI@NSY<`yE1Xfen z)?kOOen4vpU_z~LF&CDP?u!pRDW)Lqq#2x;1}{-NzIYtt+?*fU|I&4ed-jdhD2#IpS?bPPa9Rvf#a3#DIBJ=(_Gbi*)d58^t&2( zS{r;Y_nSF;O{R1u4UQZ9xAs1WJ9J1K=Wu9JmJ-e#G$7cZ&QQsgi|J%V{g@uhb_}WT z-aVE+Lo}8Zw^uDwwsw^KNSz)QK<0bMG84z*I^@ffkcHz4Y%X za@kOGHm;`2sF35W{c$?57MdAlUMMp&EP|203U2B4^x`|n7`1rk*0c0lyLu*IR%_>r zvh1okrl;R;Y139Wgpy?*&#mDu1dAEf!+bHbkXAf?7R90}in!-#dJ}@}vRA=jw#GpU z{H`W~uSF_Okw`RZDBRour{PLigb|FTfcxR>wppPaDOu|jcp8|qe`EAxV zo!LcYwL@66kbE> zcoL}G5heB%Wf-ut^dT4SIA&Zis(nZ^gKH+Vt4Qp~X|us6zGGzmEgqD6iOnFC^qnE5 zeuj&6E7I0l!RqK zU4*_Oe_R*a=e&fYZ8&R1O?53>B-#?n7DY~LVctF1SyZmjIQN5Pj|CmU1e7G(GbjlM z4+Y+dY5+}T{qd#>ob&d9aw^*w0k_cSL2{sF-}Zea-SB2ZO+k4!JSTq>G#k~03gjex zzcXdyx=@ZmyAZUehC52{&-X?M?5fZ_-QwY?Per;gwrYwNb-EuXXLWIQ+#~Ld5yan) z1fbX=3i0r@J^eC-%>$!|D)bK-U7lbMQPD2aj3Vhf4Z)){D{5n3O0vA_7gIoRJ^OwB7$Cikequ&Q6`1ye-3Uexf zwP24^IdiIYY2(p5q&*#{?}8iPwZ-{Q5duj*`E1z?-2~mlwnXs165?g#0IT&_e`0IQ z#FZ2ZCjhQQyZgQWjkH#~2JQWi0fbC>GXn1B4{C-!sI@dmI+J(bh2zqcAiLjq&TJFZ zsv%MdkUM*-$dxOW-34a9@6{17=mg6)PqQWMde7MryShlcB`Nm+=8?j-0KFwj=g7sF zjnO@h`$Vh9?|T69vQzZS6Mirm7vc-FK1H@aOcxs3fz;BDs=72W>4saoXZeoP12=cd zF|q1Mw%ez6AN^(CgUZvI-<^HCPj?sS1%7+V^$yw-sds?;1-3hV`yl&6e0u=z);h6& zsZ4mQ^5-jz^3dCYlCQ$#!G|RiUkSQhYWW_pIiYhI>))DJTZG}3$XC%Dj66q*Y_RKm zJWS4fxJvL7wa)Z&7fQ|^=m!bi;41eK8;uv3mlQAMzvFPyE-}D@Q!5*OJwonRVO==# zFm@O4++a-BhE?1=hd*Bn+fQjb#C`Aqvol-Ycl|S4=w>lYsfA%f4YkwRPL(@sseE#& z{G7hU+&!ob^BDYspHFxk7MQ34A+}0A8Iq+BlwQrtf^U-HFzppFF^9`*G;-X?Z9H08 z1O)f-Rr&gywMb**l^~pIqX|IE{iph5@Yw|?{z?hcEtLW|BWlo^_q4Uc9=vBGms=oX zvCpIC9>5hK>mp38eh#@`lylYJ8+AP>wnCVI`x6}#4-up0l>*PnDzS?y5i!(1ZlW;P4MqXkJ9WU}R;SaI zCG`>P3{d*q_(`xsd;t+kEX0IJx_P3kc~0J6mB`W6cxCYpDj(9YezVz%*+(E~`GzLTViC12n9sR~EO;wEVqirK4iqn>=Nnd_ zd*YQovO;%c2d!`(`NS4=5NaMBEs!!+TKLw3x6hwc^4dSLVo{kVXuZsA%LX2!9*;X8 zqY~n~&Yxy$e_E=LD+-+)I(3J7lr5PuN92D-gir>GQY4a+!)FKeXi&z@Bo!UlQSt(( zCnr_{6*|eZlItweEHG1TlQCm=$eFRSkT6f`j|X>+7vCC1#izf6pM%-ou(>SCkVARI zJy|?X%(B-`gi37@fx|v{s|F-Y<8MuZYs&| zKk=y&o(rQ}%RQ@=e8y|xtmkT0bG-%c;r4SGbMQEoF*U{E#ozAGc2u6iSP_2VQy48; zz;sQhQz{&qH)R0erOq>}NRU-hW>k~T8#r@k=a@EN2Ngie;R{Fi+!}XV4u_YNM)O<%IH3 zGw=E+XG{}I&=v&}Tt*&)M&ATgEP;p}xPrT0tV?+)69(FLzbi4=Ip04StW#2gwINbR z1{gEcQNyMDG3%0CP;O4QSVH4e(GiwfDqbq9$z!>oj3|?v7jt)RD?< zfqq=R9TxjKPw&i^TmjC16-eL$?=|OrCjehO8xEe2hdfJ6G9{ZxuVo5Ql|Ol}5<^Y) zh}xkEJ!YGxv+XuW=r5Mmn77hN!i^Fn**tpfO`JFPGSHOzGAGkwM&lBQ_BHNCFcE7T@&-;PcwIuVKjEtivwfH7{HHEH+cmxSkZ4*U_%V+9fAA zVKneE;78Zuz40~!^4zoRs8B~C(A*#vmUmo^l{79hcQ6rb8=iwjGqBU!olV9382qlN z;lw^#?uru+@>lL&BM;s^Revofot)*UhPY?FQ*8LI_#r@#T*?Q)_@kbA-3M2+@^2p0 zGocJinh6$O1_(K=h5^Vqqanig8ipVrQ^i6k0juP?Y19eMzrj|ty|z)*sktbJ8a68TVA;{SDC#U5={@EMGw*C#Kh21=4Vy_Z z%OztHLV*U@PsxL6b8lctku&u~u44=( zVr1wy*~b&4FzVJV#3_j2mS+7dHI!A)#RIZ;$A)ir*V^ha zQFpo8n|VG$JVWl+2oRPLb&>vvIrB(aA!A`q3AU+X^gKUwbaK-Wd*%$Q>U{f%#l~Oe zc~DVkYgSFd7MG5#u!YkojBNv_Ik>)8EJ%;JHR0`%W2d#YgdC<83x*~FAS;oAS}G2G zlZ`^Y*ob9F$=ORN8FRB{B?Z6^-CWa;a|DYmY-jDYS+?^C3k+`!HGec6S?G5YqYPe% zn-nJ)a$+**?L%Qdeh#laR~h%oI;Dh2#!+QDB93{7AKt?ky?x$V*H5LpVa&UD-|<3k zWRf1!oA}XJo{#&4#~0w)9GegQ*~kzb?Crl+rI}G& z=Prk|8#Y_8Gq**Z(Vk|h_H^5(S2GYlo(o<(i4H}6Hp?+i2-c2MK-!(rwyy20Bh{}j zT)a2D_b|@MJXak&fm)ESw_vTm7O(D|o4Eo1i?DMF4lQaHbWUvBwr$(CZQHhO+qP{x zC${aJWHR@kmpfH==4n^$w_Vk%clGM-@1vXXkNc9szSi2@ijnT>7_j(375{AG$8%Gr zc?}=swZB!cx8t)sCd)4aJLf#4IJ+RQzp=2t#@MvrmU_jSTfjZ^@LYcLXJymyD(mT*bb4&sDN#wptIo37!(5wX>;MX-{IaU6G^8WNs99$)< z7yq8X;p6^&WmOe#`ZbNyttL@v$A+K|*(2Ok=LyLN@bt1Y4M)?3R>L^s^p(|I%)}Q! z=o=!2)mQQ`TFs*I9&={YDd3)yhH0ntc(l$U<{nlg+RdWp9(N>qcQD;Ajdc-%SrMy3 z`LEVuu$=_fd8+eCyGT}5K>;Y4Es$mn-90ek&@&-rb_vQ{;jweJX&(CdZ)b^ZjT?<> z98*a9W<{l+$F?%qO$S1V=QLc)>5%S-X{RjzUO=>mUO4YFJ~aDkJ}gn8J47(jo^1En z_SvR;DrWCsGO&@>)1*Yh_spBDgeHuilrSSl^RNPW?t3YPV2;=GS$8tw)T(Q|Yehe2 z`MbVRzi>LmC@!yddOZK>PvAX)hJKI@BT80eXclM;i%h1eX9cDYlMLSs6OgjiNwHrL zeRk+Qto=yPLj`5d9qnpxd}ys(+%{Sl@rJlh-x+DQ+vDuhadd^5s6idymgvAk;7TCb zj&HB=YgnH{v`1$W$UBs34q(#YRMkTxI9&+Oh7{Ys17wLWJ&lNA0X6=*YU;W(4$d%B zBB-2#F0bLH@IYbHKWB8s+)Uy@(*k<~`j`f&OYBbIGW21K_om^cSwm;SO~BpgvQX0r z&Fk1A&!!YPCb6aA9HE=j4i-Do{KMafyFoamWdt3S&e^Mg51l^wnvbE(%|ee;W3Lai zYInPiaC5S3rkG{WbYcKBlz2D8a<{4{HIRWmZN^>MmMPpAn= z;Q@sS@&)2$a7dGk@h5^aAfmJs>QO4Bwk`8fMHnn~<_!ZC|8()M%xzj))o5yMX>M)S zwXCj|sPz7H*fByF12*VQ#J%2hz5aEY<2m)4b4)tr^ZNieSFVhCTp-7_V%))udtEf8 zjTbB6j`Vg%p5l*amONHCA&DYO=Ux~qyCY5_^P-57dp!~_MNpj%GD6&{Wx}dEzCvIWv!qPI6(uEyEvtJ~ z?9@Tp^PtgPurqBOSJU|3r7-iEcc&lg*dfE4mf_tosqXGR#XBVqb!sx|U5fCDG^vjD z9n+vegEMW?D2l#obxiN14t(rV81M2pK;^-sYTToTyH#RWE#wFk!MHjM7v8|`=}rc> zS0hs|X^e)qH^nY#^?I>W$h?nMt4j&D=3)INNWm4n%r2bVO=6d=q-AN!?U9GkC{6uN z7jJj0tH=GXonuxv9{eJhjITJUpA;^f7r`5m;9GeZ9+J?t!J;6H^uN;@*jgxAb8yxb z8FD-D(L<$-=~4T`N_*o&t79D;Fh47Y!+cBhsQC&7{x~ry`kyDl~(h3GhtE(@~*;Fi}Ab;of9iF~UB; zi!tXmElvy4HwXtE2L&2;UbwArLTqYP7e5&R z8@c#T`X5`wV9Dv%%YMyp)^Q)M|1l~0cHWxYo|4f?w1*DX7*MBfcTff1 ziZ+s%jy56(^f_V`UJdyZLwc2;1$+pZ`YHnq_e3c=^zG;=8^BpvFKSaPxBNsrX`e@9; z39k)L<>uYQg_wp403P+4tW{?-&~$ZFB~;UI8RhOBpzK7Q8O{mY@0jYWiVXZ}uw=R@ z6z=e0?|2OU5?2c~hFLg}X|D!=xv{04?;e_OT=_sQIK#{y6C`=QY_1H=glz~;fv zDeO~aP#IF$>qCakVzmjqAHB}Tdvp||HTzaLl{bjaj zTksJvOCTNI^vD5Y28}AkdN5(IWWi6U*NtW1H>RdKdK!%Mn3N^`tm5`;;`X94%GKqZ zZO9%Z>?|r1Gl`H0iPQKcEa^z42G=-nKF*obgK`lFX)ab=#Dgls%c10yn3bbePi<4U z_~`w7?jE6X60XvSKxa50UzpW+g8D?@aK1(H!bw?Oy)oaS$c99HeGdF%CDoM`)Syqq z{5zyb2guOxtj+J3%{hAFH^AFX99EJV{FZfNw%pRUk^AjX8~2-q|?VVMJ`Mvh*|r|?onOo>J~VK(e^JUTeD zpgx#TM46e6V`C9mK~@?8yj?T{LL&n)Tx-OLf9lU!wyB0=6A?1lM3gva>b7N(aaVr^ z>x(_h9mDZ!=!&u}%%bTO!DX9|LG6+9t3Uhm-6~SIKu7JFh1={-*D~OiyDUh`XW_u* z#!uxV4o&kB>}z+=`w=@LcfW+%GxkaI4a*l~T!3a~aQ_DbH=dNP`3)bB@m(XTZ)&&c z?ehyL2~Nv9*w6eP95KkU^jLCDTFmIts{_-BY?Ty2C=K$@^&)ygF z&_#011c5lCp;TW;W2{gs4qwYU7#?=G zc5i^j23Wo27rJW%&gRc+$}hK-esbymKlfNQatwi9&cc$#^zq+(`q zlB+rYPPjsgl(-u|+OvEj!VM^vKu!mB#YMHoBjQ8d`CoK95{#m5q=lm!1{y>{Qb8X3 z;InIaSD?%(2!CrhyiG2eE}Ct*tF7_LONH>+Qi}{~J6!}wmKoUbnH@6s6K4a~_VSK{ zH#D0OPj5QyrOKWxz?YcDIz-euGCX(HVN{`GXDpRuA3PEfvbDK>=YC&fLQ>Kb$`Md@ za@8-uK%F`C;PQ(ZLya@EXIz0mjZgsn4!u8D-6e;6U*YTgf#=CwRTiy-vVVN6?fBw5)Bit?{LlZpwoHpuh@45^$PAY1?>g=c~u&2l`& zlh(tass3`)#JbL`sfryLTQmH9yEJEkO~0&3?)LRXhpLnh3K35!jrAQQgsj`7KA2q- zNkEeF6)b2eo>Xi_=VLHc1;#Orb~CIM^p)_y10jDDTEuFQNlQQ70E8?;-BaFH^y_>P z#JXJ1hn|-Y6N-$W#&zX07n@BXL$%`Y!x4-CdNg}JhSbe}34;%oraT0d^z!i0lVxvO zpZhOI6&(U%pARz$_TaqvpL zSs`0)4!(W5116m0K#I^2BxkjZ?$ThGmJF#9Zq$?*8$K0JX(81J_&mU$g$S_^ewJJn z)&$C;qkdXk_*7)g?RNMJy1he~ei4~ZuJ(K}5MC+k(-HT_C=wTK4)RsDaO>LBPT6w` z&uf5X8AXjwW6jMal zcJb&NoJPhrdHK_7;+1CNwdO)bvFmUH??+(}VJXL4M;7$l9Szk59_^aU#^R+Pb}^55 z=$(Egtg8G-!VwL{E&jdTa3k_mpIVj~26`57>6|%wwsgT67G)lKGd2MM)@V~;SAGg@ zQRhj9nu-QNL&%D3I|up5^v+>lhqXDyTf}Q(MU+%mRORJ2NQ$@_NvY(w;9DP%uBbmt9nRWvdW<7rs3e9-} zTl@*p&F}%hb0$8P=Pv~6sr!I67KvuRQHzK$f6dma6no7pn8A4UG;!Krc#x>rw;;fK zy5$|n__BUuHepHPe6=B#@kgn*N%LHJ%O|`Mkaw#s?ZYKevg-+A(zfjTPuz!PS+*-C z{9Wq;c}6@Hk}!P|ftv-_dq{20LolHb=<7m$(8%X_u36SK^EzvkP29Cj8G%>*Gf8u5 zZhxuKQ@SVDg*MD1VvZb#^B>I>=1|(;#?*P^PViD)(c@-pNnHu3Geddp$OO#J;6df6 zJkm;_HqT9A1awc9JC8vLJ&uSfE)2+A^ve}Tf$FR zO=4<|(dIZ5j!pDo{>~RqiJ}{N0Z><$YEPd08^}rt{`R7@u!#K@mKgL$Pd3A*c`4X6 z6CAOuAx@U#jU9Rc@|cewXhT2hQ=z~Uu3(Y)%=XW8IBie@ZJ0-G|C$QGHmU!OC1+A? zfZm4mqdC-`JI-EPit56%{~9a*xoIb&tsND6^We-is5-8HlNWfbEgbZ#%@Z!bv@f9l z7c%at48V~b!0;~rJHz%IC{I5s4{QYP(f1QPv1j_@IRY;V6G(QLIlwB51s)HGId^if z9_T6-96Xe`ri1;;`TjY&!pL2MP zH=yUj70YDi!leU4Gn0X7e;~K*=JY|CvwYcZJtOB#D))@c*of^m#qdz9aY1SkXD3*b zkHewB1pFdHAVlPckh{wa9t%f1)Lo%v?+rK$1;;ijn!H*OaTrob$ro7eC<^fcWx?7Q zp0L?5_Bf(*%h2jY;{J-0=`>+657xAn=g4l!;&zkXER@+8h+0j0RKA{tEpqXlK2;Ko zZXeP7p`2R};>qOzu3@^Q%Q3tv>sNGGR7!&N*+eua^Mb-_(J6UYaeV^XT9Gw#x&F}Z zPu8bJ0I$9O8R={?Q?nHU?AEfVic_%)~TWMsZac9%{E)L%Dm$nQY%54!hJ zr6lKkeMAF1h7S-=2&68Jeh8!&&0rPb$`yG=5>THyc5uo(!mLWgH!?p-t$%^xo;O+? zAWO?xe>492Xf~r)jCEbWY>sY%*1XIq^=#=e?5cR*UZgki3h|tRVluBe&UD|NlZSMy)|C8$M*8;G#b(h)~kmD;g@&s%B&1(HkYdDOzJR6BW1+RWv z-&nS{XSU8%pd-Mi#x*s7y-^dIw|0gmF@-yLGctxpi<)63JNEqg%=Q$SAg)5V*Y_{{f7y1 zK|vD;58kNscfhU6|Fgz=vF57a`l`goULS1!)u$bO;T_dJ)*xi<9Hu>K!@j@{kdE{X zrQ&HcsJb3~+ykZNy8bU6!$n9IjhZUrt3A65CtTTL$l!g;J_O)$Fcg*mo zntdnj)gf&D0dGoHZ;oUE@e=aY)met1L%)tPVc8s&!5zH~zkX$KtU;!emc^AXr(H#i zuygLZ$ibZVR+RrGC4!0?f%6Q?BnY~TMBHRoG7FictMVTyT>6`$h0h8=Ye`P?f?{D< zyt_LHI4u%09n#7`G%{RpJm_>k#RYC;1S|HOK_YX^xI)Lb4G!*5)Ccv-6Nl#L zF{N-Q3m~*5RN4|7ZPB)S;7%k5^e?;3Aq=&5-TRY}Jh;*S;9QrA^$y6G2 zxQ^-Oj+uo6mC5FgP&50URgvJiMqpBB9Ia+!9_kPYjmoP3c4|e1gcEp_$t2v0AorTA zXU(NI)_I~mggX7cQggP!z-MuYxl6bz|LhULYvqWR1-W8DievEezh=jZ@z&xX+FIKp z4+##DaH&$`Hzw^aY>9sumZ7{O4_e>RIn0>vtt+x=hNk#SFK;v>dgWxy?N@>RzB_ht-=E2KFZQ|Us_8PBX zX6lXfARll#)&AdaLvh{Yb-}!_&Uygu9CP_Kidj8)I+vC6@H*-$b~#H@J1 zNAUxgA*heCks${ep~iAygTB(5+`yev!u0f^NIOiG}j-TMFNyC3enznd_ z3S>#Y@}k4_u0v6nsOtJW-5^p3t4Va6n2v?&JUxR|lETbZoxL0kJnN4b8oR5$a zdi-irCfyf8J&?CBdAhF47fFuVs#~!~~?_TDl`^Rrd7wx+T`2N~ty^ zj*qOv9lrt!mt+Ah(aMKKyk+qV0Gf;jE-b^e6_pl&2jOeWS&^mLic3*f@kJZ|ber$wZ_V)u{@}pjs0;!EVvo;SI+`y`um2ah6(T!@G~V=> zJY%-uVfYx}`eJ}-YDNY%Ch&sqg?~jy=H;W$kM%6&V+#%~Z*!ks%0nODmDiZMx$y$P z)fU7WNC({ZnEZ!tmwK!+3qwAJ)6^ekT9&!f;Ewo256#HWmMguFS|531^iOsbS%tO+ zmL8Wyd9Y2NR1VqDZRWB-nwp)11ZQHW`~2v@3PN5;um`8fAZZdfRQ_C%&CU* zD2g-eT&Pnn&?$Es?U7_>@LY)scbw{@x8{^e@*YTY1RXzgO=*?~g5jBAC)n4fI|$Dt z)j36Py6&FTnMrT*&Jq5<0HG(g+5$OtX|ayfPY0Y+d!8-qeT44JD0i5=K^X27EDu<= z`w(-w)0X^b1LoP8zk_M_oV|%^cc#s)_s8B`dIMbZO;L3RVQ*4j;CeG&@0h&Mk!T)J zeUobsSYIZ-VSR(Qk1k&bb}QW7GFa1W=0oqIHSugOrTSIsjrGm9-Cus#e1-a=_5H#b?9SsJ>YmEp+di1SxcdM7d>_Op&Yo{Ls`FK5s(G72?CM>D52>NsJw zWL`2~v3vDsEeT)vzFrMrIpfbKmu>5BXdVe<%=0nS9VoH8CFUX14`uU+5O*uf;~v< zdZG;PYTjK5NZJP-Nb3(`WZpIZGA7$%x%Q!(# zujKqc{=h)bYy<(*<3Ns*@nbiI(tD(M8&|ZGfSzCEE_}tlAFT2|fz8BPeJ~&oW$4#+ zyCEt+A*!+8(2etcM$Z1e;Kx5^d)ZZdVl+=2qW?xK=3|goJov41h$!s67^ofa-u-u= z63Di}Y`ps)<0*E*Y`CYgl2^G$9Wnbe&o;{cpe?k|rAHM@#T*ECUm?%4qlIMyVwM#J zxeNrj0{uu>{H3=QS7oG?DBw(DZq6p2F=}oI_|iVK`9OCi5?YIqVGiIKUx0b~U?TD6ORCv2tcu+;lnRNOE{JGm21Ky1ay)2-3b*jK$T&O$>T?8!4VF?4V6qna~ z1*GOxl7tO7qBfrv`ij5y=5#MoOO~XFOk`?l%FfW#$f>BDC-q@TPQC+(9(^$9=dm<{ zV@w_u79>?lDgfiG%Mu+!{xQ_skn|{-*b9W=7Erq`jb7x@VrIWVdvDJIw4px21)D-% zw66hXOj{JLi6$-hfwpnH7;FV#MGVFe&l>x4*cYaaDYNf8-!qOG-$$jy1wrg~ki-`x zsfy)MDM=uSK8|}^LYiWLEc6u>r4mSjQbbG`@7>xh;vDY7mqP%FM^SO~NBE=An;X9E zSwiGhsrP!5sG?j_TRBhCQa<8J!D5<+vaG9R%hybiHIvCdFJoDcDlErz!Mr9=cEQxB z&gsnBhIVF=(jwQDmS+BBNkkJRq!~mR>H~B-%0fz!jm!+c_BdbHsmN11|A}Dbp7PY# zu*VcPzPj$$MDeFNIad9dBPHvse5sM^jwYR*$6_PGaDz4qmg2fJmDj9+T-ME`x~L{e ziTcJdByx+S#Z-$y(VQAuxID`})Y*ZRna!l@jF524(m~BF{r1t3&Ft2h`4yT_GYhK= zjy6CbEiuiiUD1e}$Ci&R>x0E^H@&ZSPOnofljnEWK|GNW9+ok*Z=2Y5tn3?VaX$Iy9S`Qft84BZ}Nokk=f- zSyhs7Q8KSfCnb#CBd%`qEh;w5Jo>5FrP+zDACR$<68$reTjtr*owAI*M9E|}7+!&` zpxoqaHjnu+n_bsuwhG_R&iV8;OxZuo*q=N@~vXzb~f(#aG{S&sL`JJhaEp_wo z*PP`}R58Nqx#ipZNiA3bIa=q~*Q}Ilwq=mlu$fgpIAX`Ln#C=PkTzh;Uoe#mH-((n zwwguz#a3MwIj(#@5>`roI)jL9~QW}qUSITeflr8%(S$e-r zEy0t0kfI6IqSBmr;erU69I`{J__Je@1$~1+$f*5}vbklMP)Z{j9a}jlZiJD2^sWKp zv{dJDRTYmpk|~DF?#W$72DvrQJf{Ee261PRwSU_$02Y~_ zifLuCkR=OrM%(>Xdbix=@c9T&^q^Ea$g zownjvyqsMQyK}&xW;$5(<%8G`JIvN|<(S2jSe2JY=n9P+d%xHMJ+6Q3Z3FSyZdA$M zz2i7mCB0o19+xMjIP)DQ7lXyRh{E(x^IhmRFs(?KWAVdo?LMy{A}HN3|d~ z2V0FTr%M3K!QJ}T9;zEpHIPB5OX5otnYRvQnRMYhN10l$ldF*(Ta3EEgu&b9S<003 z#Z;-kT~^PlB}WI0j7k*B^+0ic~doe!x~e_SA@s+O)g1jMXm{rfP8)=nP{LkM zGs#*NwP)^S3b*d@6LHyyb=l0I=xnxS%gviM`KDe&>vZRJSYlll0mxAF>WyyBcw*dc zI%NrVvbb3|Rd?D`5o zgYXLn%NJk|Ik3tTeUpMnOeHv7l$8J+rA`Lc6GI_X*nYWb#5V|Km0!RUQU%-@>JD6S zYyvO*4Fe-s%)@pvY zudta_BSzAf+&n|{nEZI2Cixo%vZnvcKal^9Tw)y1wlHyKB5(5@bk((;fB^gN}a) zM$7ajdl97*Wro^<29`>oi=3@CzO?J=Fwg?DaQkNWf=*J;)8g9|p`A~{6GXH4xXz0Z zUyoq<>I>^t&2m~t7tVG{u;Lip@$-H@)!|klmUu|CC!soOL)}BQd5I4n0sFOiJ??mz zlw;5yZD>LCR)9F-gxQKLavdw!LMa|_VMV$G-OJk2Nn+mY^;3hN><(U}zt*H*LropM zXt2U&8bcbmYbyN1#h{T*lj^AzS6iXM-y}7kl613K50+UG1Qs+9cG{PL1_iR|pR}wf zBKC{H5nr@1hd_J%wp`N3wW=>KT+J`CM}Qw2Aqjh9a=4yHb00ug>VQAk+xwlB$=!4K zbqs;~G|~FL^Dtl@IY$BcWA$eckWa`Wo}(=Krhh|)(gB@|?Td*(nAuODOwwndmn^-* zT0$V4y6$0CS#F7}Kz=M0vhUfd^e>%Q;I|Gk*+r@xRN zFjHzP;eK&2#btf9I%b=y+CnMimYuhjHM|rdI9?coX(=C`!x-%r3f?j=;>3-|gUVh! zBTsfyHIJMPm45;L_mEN-ESd}aHHS-O0YwgF~M8 z-&>JCwoZqC*lh0(9@Fm*&|{~@(Ehs5L-FB07$TA#Z6?`rUyTUn_7Aqzp- zz;4#bgUc5B^j5koZ@Mg=-k}JYf~xaTPI$E1c9mN0y+q)hQ+2cx~IE9%8M7G`AHX2P{&L1lNRH#$%_naPtm6JuuB zMM;u!5e$^Dq1l4C7)n>mj{__%j{Q?3xMCO^=dei+FB6w?LnPPzrTie7A@i?|bPkQ7 zFq3h*5|I?nd@~pBO(Y4Z@#dX4Sf{QW9F+5B7LzIU4t|)lN#c(dA6thUMxr!BcFQaD z{<4p-i5UbDX_G0p&}ljPiWqc9WJMQE3ifv4Sb5H92~|yL!Um5Cy)`ry5_N0CSR%~o zJhQk4*6DK#yiB0q4Mk2z$jxFN26pm8w?>*w*L|}O`Uv{RnX(+BXPpKv z0UqO;8fWc6dyQ2SXO#%vQjzpfA{}b-2{cbZ>$eEd(r+81{du8XCoZz--id;$*hmOs zd%D;d@WyGJXD8Q~6oqBeu#wqA-Ai?xg|~W?h1VM-x#O&)GQ$5y#4@6v`&4qU`hAgQ zIHvC7jyluZ9d=G`=pZ|)jLu-h1!=CxBGbqR&j6nwGhK6(cy=x?vA0u zQ)-LJ5uDm;V;R?MtJ_>rR_1cq`f@{y_Z`^RdC!LT9qYILw>lnC)woA)QF4tUW1o}v z3+cyjd0Mugq|&6^`P9EWmj@i3HfSQ*Wvtw}It3cYL#|$^ko;5-pT2E}!H6ao#4yg% z8XR~lQ97NP#l|xk#h}h7Fe_tykV(gr^_@EX+IFHFN$N^A*8UPR4ERRgBfN~s6&cIDYqiOo8O^sR=H~T9U?5JzhjbyWwIKU-@0MT$}{ ztPN__o-2QOkdNBUg)^hxIWh0(aw*}IK?M@+WSkJ0esDjUWiXn!33Zxv|8%SQ zyU4vc&#>Nhpx9g;kF6AjThV=vyvfvhVNupg_}Ls%wm@^nR8Y^jO|T$15(C(hfWA0*sOOSGFP+%}TYHj}-|3h<7;;2UD@Y|@>Gv@wc6iL^b4SiG1C+a&DIn;)of|qCo|ISfv-C2GPYqbkH%6nmtoXVH*L?-Th z$;*-H1?@{D_lA1AfRMF!0z>VU^`Zt^mYj3Fd!w1{40XIZz4Vk1fT2XC4R+W%FDL4}F>^-yQqLpVX*GLIJupP01NUed8D)eerE#L4Duv-eA z(vvA8K`UD(m7j6MlTotRs4cyX+=k8$;pJDH;tDQMAV1~uA7^BWG0-vk-tW%~r*^Pf z0{oqA;|jl%J>U~|4x8A~Nsl91-X~9;ce`MSJ$_@Z9W}F9`^1=so4@3hlf@&Bf-||+ z5u|aQk0Obxc{<2R*5;QGs zXLCp_?wWcuf0*v~xomaE&0P@d;0(;+3y(s3tT2$POS3$*uQD)3pVv2gcV6m$c~jx@ z#|BNUc4hEgMbmeW7**LKKwd6o6(O5ZH%S_}5P)|-R1ev(;O+oYAvpeSUy}jsQkX$g z7-CZx!&8{!Ll^{fSbJEQhLuN5s6d24@2tUn-DSi-G2fs4Q{F}I$;g;)hv!ZY}vcxI6BsEt~g-ttqk>=T=_cC zYLz5YK%4%?6C$bF?cof` zl3WNA4IY@Nlc?@vHehCru$ZH*8AhoG*%;EehP#}hT^fXwLPy1*BV@&+&a9JZ+E=Yd zZwXVuMza2;s2$rTOqALGlrL*{UI<$~fT848O%RKEv>Ja4$H5hAlE#~1%n{r)?M$sI z;c@+hBa|La|C`h+@LuUy%ve+47KQKh~Z-&YuqIA ztAv46x>)#Ea`d~pcTkemsoBFDtJ#Coyh&2)YSytiv)reY(gppgYK?nUG8NPjxAT3RjmWDG+l1pD3X5Wzn zrBt`DZHUOdu6GWRckmrsoe#0Ev$BN9k%upwa%yCm{OHr>}Ur?v1VUXGO*cs9SRlfD11g|~% zcdj~nk}zZ2b#ub_;_Kc260ABa9#_pCQqpt$Ojch_X+KH z=0!2t*{+TFEs%L8v>_M#FHJl1gpL+2Z}J~GW^*&o|o`KcTmr0HJajBTatLD-1Wawg1ec)T{PC>F$P=~3F>I+Y4F77c( z*f;BrDUO)6@T2d)*Kgt@?3tdwcVaTo001=qbNwc5@C#=4khU{0HZc}*wsZVH#hmJ; z5|SG756y-#0W~?e<(-1JJi(uemjakbIN%aNLOGC%PV3bA_NxO^f%+VaF$_NE(xtfB zb-(_)Rn^HSAsZ9U*{9p{Q(3>)P{Uw&3$i3HU$5DY)7&+lF2C=8Q+414FnXd5cswZU zVN-@3gsHj>-lV{4MQ1{O9J1hFo&47 zmg)0%9q_xA{WgCQ#^>oP29)6^GzIkEAu&Hpqd|(c8U9*#*~xIEVl=;M4K$~n=d0Sv zRQ-kK=KBTwLRvzxLWA^Pn^veBaEj8VsqK*tH84UZJAf!~v6;_sgi@deix4N!= zW02NUSSh6Ks8SX(+>Y~gRaqF>ty;BmkM@4Yx-2MYw)&EV-&$d85_1-0soAkZummV% zq;=Y37d930*bC~2`b&q%%H^|{S}4VC#uG|)GX;9oniJ9z@~KOBN|E76X0{%%V-T|V zM=dC|Qo?+|ey5lFvhXaP?KVp_js~;I*GLQpjmx<^E;@FIy|_q$TFhQ~><{*`fq|ru z>KL;%4pV#8ArJQQ-dTD`RS|?3i#z9uy<8aFi{k-bvW}R)2W$kJ7U-$Qw1$)d>*;z`@&uRJn8pVMdo<#I+Q)0~!LfK9KkhG!f99EHSueXyyDHK!ukuB16H)6M-g zGtynL+C1eQeihQo6Duj-C<*0Vw9-U{?JpUK*N$cKU;*}odMrvfg8a0?CfAd!*c+j2 zNtoShv6y1odhr9!yjC^9Eo{X&{1Ak%^A#ApfbukMVL3W$v56t2gr|FqBfrEZu?09J z**Zh*jQ2+nDq->VeO|%vmTo@v&Ie$Dd(Q{pg;TIz5kqhEIApUiJ8CVBp1?>PJUOL; zNg<2uFC_q)PUuGfcWIDC*3CaI{{TsO54q9-(?z`S503LGG+*0nq8DzOeL^QcSq{5k z46r5w>W%y%JH7%JZ+;VCME@i)VnGNo;y^`mUjKx*_@rKPveFAX!|D&^H&SKqm|=NR zzBR~-1WReJXvgL|GEhXiWNl|4j)SPyGxDi$^i;WosA0mc!Y43F!?<0!4@Gkv@lfE^ zT+#=3#VnFcJdm7xQhv`o;|s4?wac@{<%N=PlIEqQv=;?Qgb6dZ5icgjl7uf2Wac2P zgcy2HK2mww^02LhS$){OPl#CbnH6{P6GCqSbKd1`I#2=x3Qzg4iSj<=>q{h^TI;Ba z=DAs{(&C9ku||qj^&mhey?Bj*WqNXKJeOpwgmX?G7CKSxo+s2{yO8w(>8^cS0!b#p z*Z{G%qqnp}wAuMKbT5h8vQuoXGyNc(hi32(&s%!VFOJDXxGcO@$~p5aRX7h(1Cb;G zJAyO3GTx{U+eF4~>084!lG3tk2QSV+_9bl4wzGb9nbs|ewo)p(M0euXy;Z|2RcTYj z@JwPt>AVT@!;*ONs7^&Q=g>2T`Tk&xAXRkL-1&@jxhji%M%bh->Mfyp{tfoullb=1 zD^vjNuR;SC0D$y=PU8RBd=s>D|4;T#QTOszTJ!nA)mltBvNE!U28UiB2GMF{*gw{% zhuh+YZY2m8%l6I`9bXg0mx^^p!M9p$A=uhdb$8HERr|WzZwyF-?$!=fyQ{?Wi{?vMv0~I_x%1$o%>LAi-;Z*9mTG+M zgw{))TQhzxbNnzHys5;)X>7yLOW2?L_eR-EO8mR^Wj7wvM}L*F%iJW&{$7al8+0>y=F#xk?T71r zE5N(FpL_U6=lD=3_|J~|3h%RFhTtc{`db;97zFR+4nlmDm6;c9<#kvy~>Q@6coG85<8vW<=D`^$M4&M&3p2_I{ivVbz_O z;qN9&T=7yC@-%|gQF+Ry+fzGA3koVqd~tOFJDb)gGl)e`!t&j~Qqka46Gv+Jh8A)v zGir|ko)oODC1>^Cg(R#dq?4x+L=_)VG^}XsXou2DR~Nb^CQe!5YWdla6$^-P$R}S>afAk>E-iGUrUBsUpLt^FBv_4IBcl z2!4^_*X8LhI1b}t8g?|yNO~ypU&pW}LSdew;3aTAZ=xjN?_?B=X_E93jS!=WY8Ow$ zB8)8i20|iER4K#Zg9D9l=OZah{L}6$3!#|;FIhzbs@LVlbGhrOb){WO8B^kDGomSm z>nYw22h~z0GdT}gEW)vJ8&#p{)KHXyvUDQvpbqsiBy;zMPi&ei-}^ultIJ*Ps(ulA zQGpc)K>>D3l#0p~ZlRU*@$z@ln*j-=GW$#i zP42P`aRM8{(BcZzz2*wkN`L4mV|8moWVftJRT_pB#g=J#m(ohLDVc7)H(vla^5t!E zos2h^uh0TpMwKAXv7iCYA7mD$`BjmU0#0FBnDuAgk0j zHWeyaEX$S(ThuAOh&go2n2OcOG4x#e70#C2idRn+#i0xYDg!ibByr+v&eQu&DrFU&%54R% z>6T=?mgPF3n>OXRLe~t-xgQ>TX50CXu!sPt0^=e(JBz4PH5@<+hoV|0KN1 zz?JihmfyX_O|ckTfkzDM%#+z6#);DcnP#w9K3GA49 ziHeF;10B}1i%0c#%a68#M`CoEvSkfYZG=q;=#pSd$QaCXHrbBEC2hRVrx%=2C0YJb zu5ME24R|c#ag-unjzYi}vJ0dPHtY)rZz?^a#5Ap)eGyHWx*yr=nNhN`TTA4n*->4X zUHCdJ1Nw5geCRjQISy{>&SR}0I|1;tI)jETkGIMqL_J;`RUA!RpV#m3#Y?O=AXtGp zbhXAG3J@SB%PKI+@ob3JTWsfXV5XI-^e+ynDGDW&?=6#+Po13Gh-iQPSbGNhurpbf z6v}pCr8lrLScBFSfI}?=1iBh8Ot&QbGk6(H7_1#!Mrmcrh}J?l|6hciQ*%I~~XFpQNf1Y}LZE z6MljouA=I_bn(;uYjs`VxC`1BlZF>)C)&5e?h0~P9H~+>3f3JTZ?cqkwEp>(Gzs07 zLo&CG(*ik>sU0I{@Tn?oBj14-IW5=gL!lr%{KdB58cgg%Od!>=OY|7ErIaM)Xw>Fd zG=ziT^fs29*ahXxujJ4}L*VbNgGR*!w08dkdnUHDTf`m?J=4k-HooP%|jZw=`MPPShT@#50%7H_=AHosxwr<98cLhZ;z*ypU=PEWpoB zH`2!)ptjw*u{z-1)OX(0_4Ux(D9m@PkvE%C-CYOk?4Ww$x_`J+4m&~{F5H7=`X7-y z_dR0qyZkDSjJa4mWG~tyx1VKt{8~?Zo}7oSdSI`W7Ou7x9=drKe6}Cn-O##n#$dSWDD0*gn8XF zbqWKu9u`TJVz&BocJ)CiXN!WCwE5&6K`G1RzWph!w*|S69d(-mJ0idmW`;t4xb@lv z1No#)sUWL052_e`{5AO(``>vr6wMVv(=VIwdJnpM)f)0zW5s^j)Pk(NB7@^ux_gQx zWXlzSPfdz_%MXy{{jQTOkVNcZpPWowwn%rO5@U#K#iU-d}UT=Em^ z*F~<}?!E+e9gVzrFz#5>*GA)r=Ux1EQIxrW#yJ-b~pZ&>P^b@Tp_I&`x-q@05(@wo^&3trcO z-!{aT?wQZjrJq4Bq?%<(Ts+}=%TIu;6-Rd8kT>eCH$>l*>yEjiDmtiOew%u>7trj{ zsT6p=lN+@CPvr)Uic=e;ruq(A542C^YT21bWtrti543*^i@hZtZzOVj!mRugu#c$d z_alFJce`=rtX!58`bnZiA{4LMn~;e%#ygRzn@&D1r<@?kd|%Oy!>hN*n)H-&PpG*q z>GN-C@b{Hn;p6Np%5tiq9iMUeCTFm@TtV_&-A*CodVM^C6!yy)@kJ?is&6YTo*_En zZ#9%5JApA+ZSn1%WBN9)xc3!|Rh^}>u{_)Q&eu6uGAm83`#k`pC1lH`h z-LQ5)sPIg`LUjtRbe3h^I&cX=KL)+X{Ox-_SrXQES+F4>6zghDgZD~RI3*0#idcS+ z7-pt9BiPr%zpEj0G`YT|!9aNB*5*lm0mfUW8}}jDZcpN(C0S|spkBg6)fTFmzE#Hk z0z2%|!x)g8r6R?ycy>g8gGl#wIU%yWvNEO2YYLj8vA94RmM4?iPDbuYRs^=YeXLO` zu**f>J~-dbH??Cv>aKdMae6rlSP_uomE`m;d_#?rf~q3ZC<;b;#T*&A_0mZ5tOxJN zWU5M7922Q^_3Zk>C-~-@`w9y569P-)W*X>2=!5T=KUcqd|u zl_(L6s+-waDcrbB#(iNte1(d+QIdRM7CJbVR=#GSs>w@9GbvC!Q6yb0kaYOdW}o3m zTpkUA2iasgOU<~ijF)5VYVZ6(_e_FBV3^sQ6QmV0VaOaNLvP@e!|e9JeAL|7fu19( zA?4IdiUc59SiW_ACbh;HRUIt9tkec(pZFcM0`9E4OAI$?jYDkBI!E15a6m;yQOe1n zOzLe(N2QE*RAEV@azC4URG>iHYl$Y1p($-*b^mBZY_((-;ZQaZ#-cbl*RguVBf50N zyblAA3h!hi(q!1`eR&loT4x0p_kI12HUc5lP=CpS4yBXJt!OM@bADwU6mGJ53zBBv zd?=MZ4!56fi8in+OTNBe6|6U*&9u_CBCEZpnbe1iskefaG1HdTwu54EEMAjYxbbvR zLBIg;*r-h>$Di#=tejKTEDsa_%oDWai`WbkEXBJ3!DyDu>5J%X)A8`wQZitea-fKTn<@_b!qSsW_LE2*sxY|!9_95 z3j@IU6rgwxSjwc7Eh>(o54XIC^rg#9M*aNJ)V!W@HbvqxNbOR*s2vSv5ts_CxB>xb z=Dln&!JFxZI2ogn_S}$O@IhO5HWQ@_wi0H|(6fWCNWiQpE)YIBTinjwpYIF?p>?K! zpJ#_N&Sw{RpXVtIvh&!%$~`wx3zEZuelj8ha$rV3tW{X1nW-FpzAln%=9~V%H?fAz zjhaYwKtM^l|4)RAtbwzItBIhaqrrbElZL$i6XEjs-S*s-=E3YCK?cgqKmy#4T@M5y zP4a6Tnc){OR0k347#Ku-8o0cIb}khi#a=(rZ|Jf}Yz3kC$kM8}^DVuKB}+A06|Hr^ zkfzqewb#{8!3q|+Ki~fP+P&Y>+0vQjedoM}+x}Q-ApcX~{n{wbvr9~v{V<1;pJFHH zIp-Z|7sk71L0^S5gSi(jSmLcr32+}&=x(~dOqJuIj&-`U>Kt{_<~9gFhI5!lq{lQ2 zAk<|UlnQ-mC+s!|{|9#)NvO*@=!dnJ5&H6%u-hj58gs8B^d+0H+b)~{bFYVYFRXJR z&O4b_*N8#)SjF!G#V(w^?Fps2>k!2*D(5bn|2`roO3(iCpZ7c3_SWuthxa?{w(RXC zySG=I-Szz?X!qw|yPo~^Fuq%_TgdLugt!N!?XLr(kF4RGxT7fk4%u}-*g-w_c|DJh z5$|`LZNA<0ZJ#}*TZFimlDMPrnNIa1J=h(K4HA#SUPVR2+{N0!Mc(<4s={^gsG^a0 z2!#7PlreS!eknzL#Mg-Dj}Gy4AOSKXpR|77oSRYQxQBNNvIQQd-Xzc4DmUctXDC}H zjjFnY0CB%~JHqVc5#sl^QVs9W3|O4{9KwYzAi@D+W*=wPXFb~YdmErQ%u%QMPRDrM zNh#Rfb@^_%{dN0HRa5dYB&M*8w$RCaiPunEsK9Xr@8-Eso-iEnr@TK|PO#gExX)&o3J{s9LpahcOG zQ4GC-Rg2VSqfxJHNzdtr#BuKP#1mkzI0bNZe;xzPg^en!U42iL1r0-U4=7!JI^G08 zF?hn+Q7N_OULfcFHlS8B-fe!PEeV}IgWaM%w|88klI(Fd+%{D2b`0xsIxXWz+lH&f>8C%=~h^SY@?Z8B{kocTpn=otB!GI)}Z? zT5^mjlmvW$3Nt?RD6+U6LQvwwyqwz3GJL7}KtoYJ{VZKW4XG^Fm1j1y&SeS?P2p-D z++((>olbQ^=HG9Ebhx=Dj&|&wW(byLRu+c^Bi8c_95sgp#DgPK9p0ACKv?_^D%B#0 z_sXSotE_C2^W>PvB}Oa1g|l7{Dk4jf`YthVfygGY%4Vi^Ustr}LQRU&SQfSv*N3+% z57?KK4cP|t>PQuKQJhv{eOhIe6?x<``QGPx|C$Jj9j_4t&4MSmKp4zNr=#g?cCW2H zPV}oyhqqR$f~FV+`Mde*QM}TK%D5$#73o7k<|WihPF#kwI)Hjo?(Q1%IkswSdD+kL zbnvi-q*zp02G26YQYwh*^SQWu$HKu=8H%cr-wUUsm&7L0tyD#Dj&6mIn2WChe_^88 zbSx~XE2zae+9UiOvA{0aiIcQnM;6rFgtotnzasl9nr>)Skc5p*q;@xX|B8#kNUa6D z)=0G+PUHpAA_ChQx5PHp=zunU1tP&Si?)0C8;`m`MoD01xc(2E|8*8GkwNEB_v%8N zLIcscRLU<^5h?1WtD;^JwAO-xj>hJ4S$T%{3s(19a~>s;tiy#`?-3$&lD><1I>7`+ zYkUr)Kt(9Csgs@XVLFJgdZ`YyM@Wn^QT_dyM^E~NNG6hjJLb1fl&3gRq!yqV>D%FuBubX5Q#jZ_mrkWp3 z+$;bmv^Q1CLM~CXN~6O<7Zb1b7J4*)oLV&&!zl0+s-#=9){fJ^^sMe+(!{d?iEGz@ zrNVgyB5qd>)l`z2iXD8#H^_{b?_%J9@~>IYNy6Kn|*5W^XL<%v=URrm|iQU%L6o9eclN zNDsPIXMvRTs!|8F3c?l4=7ovvCnB`2P|6BIw>*wT1oaz7#^rIzKEGUpdcY}gsYVCt zsmv0h#MA|b>>}<`$(_M5`w&h9jVz|MqpbX|6m+^^BjIS^TQ>OI!BIKYA%a(~{Mv-D zjZ1-}!nfVQf?zZRu;DS;IP|0v9)^gGsFMo$%uL!|P+6=py;ZbMi17F@+6nMQGe7Og z**E43@9i^KWlofwQ>+ept!=cjng*sRf!=KPH?iqQi`;HmX$5c(6N<{>qMWIwyP*TX zeR+wsQh~;55Sx5Nwc7X<@K%I-N@MRezpzAU@Gc65kt%GZ-$knb1@2s^+82Ff87k~A zj8&1J;2A}R^DS(>5c0m3RiR6ur8SZ`Dlk+IbkY0`tJo1(f2{9mSy#to|8oP>Sz_`F zr<6-YE$0){#x9#+M&dUY>%j+oXhGy<1ijeskOQ@S^A8U30(BhQH{kCc08NIGCXOGv zI@#fQ1yq`HVCkQVax(+b8lQT&hEOr2h?k)TV-5` zB2OfnmFQZDWDp(cWtG)bmPQSyN9vLBc0?ccJO3`MRq4ctb6*UwsWyC2f@!7-e#lR= za{Jnw$Yu3StJP;wMQ~$SeF?W4Nvw3MS2`3E6|F4K-=A?rH}OO?&1uXPtGMhOa(5$^ z;){~~;9TH}2T9N{$@+xLbdk!`nIj|)j)WPqRDjCb5v!NQF8j(dy*P-4Frw@OB4X~T z%P&bHW`44WhgR=z$&D4om`DO4d>p2S3gb@giZf}CQy*|VX9|@TBb&H#29y8IBHaYC zichB;7H5(lX9z)0q1x`=j)E6!Q(&a^Q+pSu{w7N&l1TMF8)O&_?j+?3jA|fmcJElqtgHlC~^O2(V2$QiS zdbBi}o`;qEQ`|41g;fS&lWrx@l=z4?=ZXGXi4GlqN1l%H6pPDnTq z448DA^shK=+wt)5^gV5blLTsM4MJ)eMyceqJw=DK2zlHY)hO2Dmq-ehp(*c<5Ie0G z*N)Z!)aRRpES@Xix)D@_$WQzTG5!SG$S*^G%8CO?rRqdRr61Ib45J7v>ySW#$vA6$ zdd7e>qjq6BkyiB0D7MnF(dM~=CC9g6U9!tX&XAejm-Xd0u`xQ*;N8HQA)8k`AUXiCWYx}4UZ9c6d@2@EmaNj zPJWa~S#Dp>#MG_CKITRxJ*vKvE-icN9kxdmCHwffv`1HGAF2`uA@UiQJ;Py)BZ~KR zXF&V_kCHYKyBobhe7c8A?@8q!-qC?h1`*#7wbn6I=0TRY&b8zgh92vLmh?L|j}FS~ zcr6)^lFo_b^%LH>&h_N=v@7yMUj2#A04ar{g}^swF;gX-%~3SQSzpFcy6co@D57x2 zf=ffj1yuHM92t%PHIIYO;tfK#bVCAT)vLq~nL0sjqexGO5K6X)sbUJG1?gA+4Wscc z#~ez6WVLj|f2%g*pLc{xd^8BDce&P#hiZq!WKDAlf}q{Ky{UH!uc?#>V~%m&8_9B` zE`^Ew(ye5 z!+)Dp|9SAZi*-$p9uC9phST}e@p=KLJm75!g8`F=XC8}k{3=&?uhlt|r6Cu`F1URi zw_Z0DkpG@xpX-HfPD77jVRd2{PCF&t1odDm=^b{~Z-U8`Q4u~GvCJ5@&x9VF*-2n- zhh0LtOj)OAZnO?1R*=(KTOCaMRf9Yd+3s0dmr38-f#S)qmqf#1Vd6H? zg4br|tHgj(!6vRMcIg(mSxYUOs;sdBOS48Piwog?vV>@oSFcfDn3q>=(3lI;-mmF4 zo6Hd87&}rIvELC8aEo6NbF7{O-0>Lfng-C3O|<**Km3^YyP4jAI+GhI1YGPed7pvp~siL@!<`fJXuA zql}s+qmtY7A6)F%s3n*w1D&#x>YJ4iUmo#UQk^d9bC3BtshG8zj6RHeEgv~i9TR6q zW{U0aXth;`R^;VV&`4@HFZ8ivH_%@Gk7)3+c&%c>xU12nZWJfU6)GpX%zr7W%DamPe zrNML9uUJyvyI-kZrjVR+m> z!GH9{eJZWbishWi5q)TZ_ky~-F8B-ze)22$90-1joAss5`{V-f%bNEDJY_&# z=Hz~=3ccGj`lZi)VFCE%%)db{^~f6iLY}yxF5Tw79I4OB@5CXAR8ex8&2XL z65cWy1pM;(jbwtnA28miO(kV>);f~)8+Wcp9b*%-iDTobN4$bJ@U*~yAm+3;CdQ=h zYY)AfVk~3|mE5ACo@?h-+5vs2qVdY`gb$ea*j#-(wt{8D*Z*-!HiAHq06r~QpcNZ0;oNaJgQw9*wZ=!m5?CWp=+ zx_3uU3v(tAv4p5nU^+2yWe7b`&Q6x3S_)4zDM>2xumpSsl%#X@@n5272R0wf9HA;Y zVo|n{v$+NQrMOZNn2@|%plUK1O+T?t7Rw1(2KoLHExA0rSIPJTBO} z6;AiEAZ}%u&8u=2#x-Rvn@X9LrfB{&*%o;N#K8UoeJI2`xbJv$WkNVSz%M$8U84Eh z4jtBx9o9~^D^GYVPnZXTvAo0?VOhgJrOQvMvn_t*U&BiNNm1mSIa89o1;p0LXfTCp zHic?HVKB>yVO7I9qT9e;V-YC0p#`8+sk*Sc1iPKuY15MLVKsQ%nm+5wT1pDGsPV-* zqEy&j>f-ber@So7bVd!BHtt5T+6MpXz&Y6P4UHdKL0CO^qQ#O_Gb}+(u)HMc4tZ4< zhn4k9hKwR1WfT$AMr&Q(u^e<^t;TWKj6Ap1?y%<#K4;XH+vkcsC)M8We-zfX+x3K8 zv2*yuTH&v)ES7_PNM90?vqS;yQfSV_6KTV^L>zygy$W)q2KXp!1-oJ%iY0%_R|}`b z*29}XjHmo`4s^n61cyS&pz_mVoQQ|c$r=>&0-V20kjDEc#Pe_i9XZDHC?IojL+cU7 zcPW(Ol%Dn;T(KRJ9kXXRrQ1$D(rl7f0^X>?+2>@-!LZ9M*jeX58v~wZ$pBI_az*DsjPfnHhX->ELI@Ub*wco$l`jJXc+k z#hUZ2l=HYxOv|Hop+xiotWc_LT3z?K!p|kNFI#mRp+1PU`G;JfR|p(@B2QsWsH%Ol zYHGirJs!~Kn}pTkVqeX?h4NRpVlpy&xy}Ni3_9 zgw$D;=z;qBrKPWtmg|QbTGU50u*@GMN+yu7+T4SwZ?|r2$2|{lWw2Z4@3xr*poc#D zPYH#gf+caSftkPkj%CqyNBNC;D!?!wpkD|V5Vw7>is(J`1SNLdxNr~^iqK<64u`cR zt3+mIv+KECxy9o04*$c|UueWN$=240doDhW<7RkJ1G`OCpD5w8(il28{w-8IfpI=+G z-WHYMB;3T{9JqVlmoWV8Vb6gQ1u=+d&6yk;ZVf)DPJ<&r585|uR2r0@2aTI&i5}TH zd?cjg57z+f)z5^%5=4j%?5y3H1ffwVWi}tOS16@gI6-d*d|h~tWqJooR?6*j{{#u- z^L8XVi=g;M6<0rKK8}72#0akZdss1nqEI3}MA5-FOf1+8E6gWUcnb^uf*E%;Y(xf+ zb+vlo56lH2`f3`i>o&(~8MO7&gXXBd5nlypH)2CXDuH#qKd;HY|I!ZD>yhI^vT$ zHKy7>tFwXlG^lKmn{C)LFzv0USMism9H?f9EY5&xaf}sa0oP@&j$rQhqG_bFy`cc^6E-_laJ5 zFMx66Gs=h{&&Kq@*36yfK8e)YO1nJ`9~^$Q`Mk(lLb?k_TcKMjju)Yk;YbE3ms3EUa+_doQo*ow$XHWrtu;$(v*a}%hd zwVYaj9>0@4K}ewg2G{Il-j(p>rZw2zPV`GeZ<#B4zWi;sQ}3$z#)AOWXQ;CU+zS0? zQ04dLQZh|-&{8Wt^r=|94GQXvDK@!nKFr`0i`0hDpaP)T-=QXk-&plP>lZ6_-PThsWjX&wgo0x(#%5;c|=+F7zXz&+9i2}*@=w1!HrrXT>)g- zMLv5Rcp|Tb?%A>7Nzf&aJISK@`!HbV#U_Z(&2W5R8fB6}9%adN!4|wAeKcb3pJm9^ zL>C@;$gN($=Ow9qlbc830vV~nSRjp_l345!I`}9_Xl7U+3jR}!I5sgnWY6G{m;Pq% ziH0_fp7;CaQFzJ0&HAnaPH?FC&kkVWwew5yA=Asx8S(RWeRsYYZ{gSeYdtWWANa}- z2*``~m|+Pcy@y|a#>^v9O+lR){f!0^qh%l*8N#wGxxoAOV!$AY*EHy`RC^PnjL|w9 zf*cYkTzIIhc7bL42|3B{F_$DoK*u;icT{l;xFoWOxNoWF2f1fCuZ1Z5vT84Zny|_= zL&s6g?RofBfc@k6L+vNC4p$xsRx{4}4lO|IlVcl-FtS)bbJA0pNk60l&cZD4wODPVP>hIGYmNR)pf+VMjte*^x$c# zl^eg2aUAaeWo4r-ndulMP+XE$QM_r~6o^kR^fm=9FrepAG3a+-)ii94LNzVnT{{)J zd9}LcmLX%DBd2FWU%=uP14!-VKSCtJ65#4UgSKJ@&eYDNEk&8CnCeHWqTRrY9^^ZZ zfT+S+a_h#q;Sf#_LOpIBwM=AL53DZAu+z7ogCSd5=N8=)aF(wA?92^&N$$B4yYyklr9n{mOKJEc;!ryIK^0dMVw@Kz>`WV2KWrBBKQtR~8CP&|hX~ z@+u?h(?BG`;M?GBoUwgO)PG{YYkTrun2&-+Z{jpRw=L++K?r^X9<{__L4L{}a1UfA zKiiQMxGc!XZy(jfxpPC`lxtl;E1gA}|Et{JkA*cxD&wnWp)FH{D9%}lK25}@Py*DL z3GOc?i*&JKEUbL@g=m3Ec%(4_)n6ZrK-dM?wK&r;=X7FbbEy7p6Gw)sMB!2e_#&JG zhISSBl6Mof%S2-HxXB_&6F$6n;?r7OnVB)Clk<9i-4vsfcSo8o(wQPRW5TRN(FZRL zX@ap^p(Kn*V@{2SM5RG}PMPRrVUdJR^-OxRND0TksgZ9(r85a8`P$P+Fo)U-gcG7w zne@x!A(3u!iu9?fGLsP3^+K26dS^2Xnkcz#bb_>4god%u=SqDogu&K_rH}m!9y`|j zdx2qt-ZxIrPIj5sL!qr2VtRTLz+yJQ%L~djgqFP}=BndkAv#8e2|L;*@UFG`W8!UK z`b#afW7gjQ(^A~0Jx!pNSg zEL%T(x~U-J{F_UCyI&NhZp8vO3s zIFF?gOm<$_gtj&gO7q|(fcg2I5b*_+=YYgvMkhl{4OmRBR?Xx{l8XCa{nXVB!0=BB z{mH(IIG7LjD8|!~Rv_{N8Y+26lKNL?=iYEghPV2O3){68*TcT%xQGk*OMRfUhJ+wi zQ2>)z!GR@Jyw!=ehRpGVW;)5ad3k3b-CsCmG8~Hp>wL6&EGl2xs+1quVq3PY(D#oI z^JWi%i=rk^)q@r<0q4}}&eKz33y5z6jIT3P_a8fDcUz8PS?>`JTzp|fQ7P#hwE56P z9|B){@U$9RuM~YBu7(^zK-{DcUvWYK>9#5lk@A$|-gKCi{tshtWsu3FSmuqdH6#fP zV?oETEqq4((OEqtTOG`EjSVm}Q0xij_pX>wm3W_`r`A%TnT~oFvb6qeHmoKt2X~PkRbfTlI zW&<91LzwuW>vx|Ii|!V};x-&>?E(}d1kqbne?lhrk zy5O8Oq-cW;YTK?2T3IbIR=1jTL_%B-LzB-;M=eN+?6W2rc>a!X{Q0=m6n|aVTY$}d zQy^$^s8`+kkYH*_NN4^kZ6q&Y*5y83Ye<_1A@2n|D63n`EXZH7V0WHXQynAvkp8V) zdUE;`qdE#T?>9cwW{mn=GTUp+GO=6x@HI9oV_irp4EuUHJ}_H80pC}O$A4kD1_Y2) zIk`M*(AB=s6ucnG&2!EksDMYzslR#!;CGywbaL`=<6^HMt*_^eqP{^_!ms|`DtSIA z@hq4l6%dh|0zdz^r@X(-8Lc~p;@G*G*21x@(Bx=yPs3}rlnC#1!%)4l;*IRITk?iQ z3~amfELia7guA-5fVK6l*a`f?Et1SYM~Biaamb0427bN2H!bioNOrYe!F0&BJ|%{A z2$UPTt!DWl_C4j*aw8P^hMU2S8Wru29d{U{U3)zbHYghW`>TfUdir`ep4C>fT2NV* zXWfG2sxhn#jyN&$`u3)HQwOc0S z?l^apKF`P(yu4Ew=Fskh=@nn};2kxIKw#t}wmOAi-t@IjI6|V97%tuxK_(2(LK(mp zdXi-m6?TTGT5H32qWO|8)0_8?O*p7_ecIC~LpZ_)p0v3y5mzC3m24RxxW`r}`>LT` zp+JqL!uJhLxQ4E-S1vpk&ZIQUHVP-eA=1Yk(-)uBuKj;xwN(I z_?9J&pMPDHH;uVrAUM7xPkZ7T+P$C$lS*dgqftPrU`SKIpc=Yl#{aSloBXDC3tsu-tQaOhrs5ix+pUl93K>#L3YUgf zp=PD9JWFwlGcL-=A|i&Az>nE_pA5sQ4mkqCWrfOzQ_64l@pqe+xvcLj1x0A``9x6l zCksW675ETeCcf(=@+V%cMFuR=6PlL>@xfXbw?{WWe`#3PpG0uCV zNWZ$ORfb1%Jq!zw&$?Muv`bQrCxsU2wP zwtmLRHiK{j*^`xU8kH_+Y8u0ke@9^SjDJN-G>(FrX{F)8@Ds|R3n7W@ard!k@GOSq z9XsPkO3LEnP?}^i%)m&YwTbz zp@xoBtp8byLhKqh?;9}B_~vrdU=*K@*N1tF>UUpmgi>uTr+xoC(42a`{>jTzLp~iT zG_&Olo5T3Gg|J9zfn;}}rfNx6G)|OhYKgf395qWsaldecKT*H?B#O{>_+1U&2RgM& zXn1AMc5J$WS{~uQtJE+T7Z>C%KVCdNHjNBJ-CvNAU zbp+M6B0d+%$=Rt-0Jvi??a4^4eZPACrMMY788c-!E>s(;@jzl8Oy*)NL;4Ehe;ken zF4tBJXd@Uw&8sG9X$Adhz<$vX7H;GkpF1lP(30A3dhAVjl+2_&FLEXomHy=XvCMJ! zPT`K!q#4{x0SCThp!U4HJTpCw!LJH>ckk~xDX-vM$u#~6tARlH=Hj@=2hufVb)%iU z2GS~eXp%XYV^fNJLOZM41cCGBhMT?0?E|ox?_I)=V%?yiuPu{o19Sf8g1~Ye!#@Vr zq>#4+*u{$ zO-v@X6L=$E#cBdp-uZ2u78Gv+FZ6fqS6YsLyePa-GsmypU}&q6CN`lvS=9FXoxjz! z3=EQaq88&iEEHGi)C715+QFh88AYgCvfs*wf9@A6+BR~{oOEXkFf;Bm2?VP9)*PBw zm$2uT$dR&c9%ycyGZPz+dq-wK<;eR+=;gbgi0qw_>%X91UQ|+d)qbCE7yno-ejjf; z-6SKd95@ysFM@_vI&FgI$b+cj-?x$%uud!=eUp<`uem)y&pyyrq}5)x}3 zSmpJ5XXV5(zo%0^Uz5q=HOYT>7h~6gck7MF7u2*hjfRm5iT%nnbp#kgP6df=b|<|J zHwjZs#`hTq%y3W}qZS1#3Xu)R{5mJMkf|exQ+jdGlwFMz7h}mBR+j3Eq@*p;v&!r4 zypolSqBpP2sSsul5m2ujj+XD0);mCWt$Uyw?@#yDW$sOpmn6a6A^qe5i=GuS@>sSV zM@X}TUk|rE7Fo>vKoL|k$n-s@DSjePuI>^IYRs9VxIC5*y`J>|bT|h*S*2HIo#C^iIeQ{yY!B=^WI`6^$TT-dkzWSu(fm4X4RxGBay@6RYCKb(PP2LbS_7r!3SLd8i z7kBfR+^_m;8J6{bC=69`g0P%_6(5`^h3WHw-(FdSas&zyJ_=zCLu9D-)-PXCsfV&O&+u+XJmD4?~d|SN@t=&>xx}xpVd; zwAhy|?}{g~_DU)FlcrRt&w+dr&fI$#RvT314)r2-9B21%Bch%I5gpsL9>gKtlvgOv zLF`N?Ry&Dty*QvJsjGP$LU%QmHj*{{Z_=l50&ljDSADAG)!JGK{pS*<_3av1N11tQ zDToLNNpf~%asDaXB~cs2yNe9iVJ1`@_^ zoTs2lJ6obPcNX{B!>P3zkUIz6Cr*xUL#sp?xd+7j!;^`kmL+jg;9i{hqup(SmG&|0$K)+P z*oS@P*Z>|>uWqYs>)JSeNfT?#^r`tF8`ia4tzv$wrV)pi53@(;lDq6UJNfAIDT(?M ziy1DWBwL1ueL=(i9^Te)ZgaER=a(>M@c3ew134hU-XDZOlk{503;Y&>0_Lj;b5}Dt zxmz)v9;xuo3>&b%Q-#}tzCP5CbJvALpSBFku2gf^d1-H5ELuG|N5I7U6{varn9YrsroErB%_`W!ssPr_djQ=>rd~P7 zA-==Q=e#a9EwnkY1dFJfAj6)l13x&Mr%1L?o!_DK7mlU7@Ex3HSH1!8S0qWqdl~Cx zhp)BoBzQDW_ICzubpaZ=Dmk@M^zH%6KxW!OKM9&@s}xT{#0;W7`KyyRkWUHx?AyzT zWSPgXe%C(n)5oI?>Q44Lx|x$f{bQEN8TSRVzbSPOLuw_>p~$V&)jWs}ca3$X9_}aY z>!~aMh4E%44Shrf#MU3YB6rsTi>b7H~R1Sj3OGmZjB!t_Bq&QIltWV z8GY}72a@z7GH<6!CIq?BiHfY zy=W{)c>2G;k%Ey~K8@P2xihmrX=9$^jTEI%^YqE2(u6wRtY4pP-UJ=Q@_)M;q4H^3 zVw$N!f8R1DAY;oWX@{SqYx4{9kCK}1d5&TiRI8z!^~@{*P7uG{d-WRPn4EOXU(cT- zAe~&QMV}(xKf1^p!^0SXHnlQ=S2RG+o+6rj=^-{svv0_kBjGechLbJHR;`6br%&M}S?-+oNe~g`c!2?t_@D+~`azAkaG4G|cvpth` z`Jb)n#jyenm(0q$<4rS6%X|Z1d)rXGVvwPKU%d;H01hOfvZ) zQ$=Z+3s!T(%WU#VLI;oAOZ)a*+5yD(LAoZi&9j{#MkNAtO}IQ4s)C;2VX5xl=VYP5 zCfq$}zfGVIj`4F3yl({NWrML$n7HQewbZFk{77`Z!|CR~!8Sk5!dLW8=su0O%D&+O z`pJKxe#!FB@fW#0_{~y&<~-zmVfhq)OOc$Hh!#tQ6Vg!*x3e%V6-9Z_wX7c8g|F*` zwyqqadFk-os;DKpPntvyR2$z0Qj2 zwNb)3M&pfA1&Gq1k0#(n8=-L1B{C5D5L+;|V(zQM|FUGjO#DkTPb7j~)v0N4!6q}$ zW}~}V=#VjJgZ)AHC|yGE2M}12Z2_RalrHHh_{7M{KAs~QTn~;lb<270+~EDm2E9JZ z`To4uLlhwATV}us4V1==Bcird<(=ZhYxA5WCOEPojKoEewh2ATsGvYMZt*j~_4HfR<5t}lv%Bp+|HkR)eq|x-ZN}7sWAJ81w#Ostiu1kTz zgx_?s53nKzKhv1-s#!5MBGAg-lo+kXrF4Quejk>#WtxBnbW=cpr~kPRmyfh;=XCV2 z#}FZLDodOn)$WepOpH?ZCV!1U1vYcnF>#b)ZdMufxW~;NTkReNaY*R3FZ!T6D0*t4 zxO3Q5?lXEI)-cONh^q)9{wUG4fqQ6Yi-kZgTp zhppyVlC-S#0eTQG#42Uh(Ws3x0ZkQ`RCbcjJAaE=tUd1GqX?0< zHF(Oh;EkUFFjuaC)%4@3`PQ^`2-5pyY^4rq5y>1=IWF(Q=Yyaw79#d zihYC3UJ1>(h&UG6-SAT4*tp*T#xC7KPp8-&Nl*K%u0MHTmKXF3U*qT?``9;2xN2c{1yyJS^H8?lYU{>@joU(axjC*jB`B1G7bnKIp zHGkBTYHr?iMnh5pQHWAdf5ELFg76UMyB>ye{sIfIn~VP-4t&n5A>&?F=xK-3fX1dH z3^cQhA1WU;bjQXxRXyyM>VAj(H4j0irG`;MzSM2*{(=tx^_hd< zi@UeD@kpH!<0D3}*DrtMBRV&K<9WqO*OKF}4?Q7sAy1XuVM<~Y8;e!~Qsdwk1duZZ zQ^ppPo*0A6qCJoVADcxhkZwZpDIkY#3 z+CWwB=Pkvu4z>%|#kU7G|JC2&gLko_J>#FHXhdD0C|*h>bGK3WhB$cX++2qC+H5-Z!~E##6=RTxK@rwfqA`9rsNDG+cGOn zJx;68XrEx>h{~Hvxc8X91-Vx+Uan?z{)g)Ep)*3=8lmNm)N-3xc)@AOICcTOX%QGm z<>5w|Gr^SOCh^`1=Bu_WC=gq1UpPJo76FgkSCM#ycxk3?*Pkbl1#aE&`M(5JNJ_cpF!S~UOM zFi$%UuA7Yu<0#f0U}q#b%MPA7CCPgm7GB_w1BpVZq?{DhKa_^=iQc%NPdg^1NRN^d zS#x)RW96y}E)mSXl+njb;i4S+5Eh4lNzr`O(?Q{6;G0E1Jb-FN4_Gyf|_SI+gC9sTAR$Kvwz5heAiyt4R3GT ze(%WmgAOu7#)#0e5OWYZu;ifHvfv5*&Oi{RgG_jXG(X5x0bgHvA_^|OU~MR#hzD5x1U!ZDnP9!gx%UZ`!5@efl2s zZ9;$M6zkSU`ePy{IMSZ<8=}kuTBSmiSx#`ZQB#u#v9w5 zaI@d;&9^tZ7u~13PoKJ|u2a?ZKhN`fYIbMZzWs0wEmdYyMvUJn9ULZ;$2KE!2j6>%_8r!zzRbd2?DQz^us9MokR<2v|7fnLjs8yGohkO|Y$tClY zr!?kVf1=hk3>!KXIu4j-s-}I2^yLf*P6%}>;U{YNcgsDCp?^l-ItjJj(Ur9h$g$N- zN7M%IrsE#SR^nX|9|`@gIV$NYl5kD8kz*;-R88@( z&5|;Vnh6GPYt4O2jRKNf)?uXS#h$qtp1`51%>W|r;F5gJ*=)?zpC7+=q8R<2)So)r zuiA|fgkF&S4?JSbZwW4r7G}QqJfad}on6uO!WD*7HWVrC3he48@T?gIoFACxC(-aT zi~7)1HzttweenaUDJW{5WUv@KP`lYqB|sGB;3vcE|uXTLCRAM1TsVUTx8R&)kNWTzjKkN^V$P zp|r*giyUBuSQjQHQOu%D;&$b#5{uMFf-sqRlP3G)Ofmh)ze=HleF}U~v!&pm)j#Ad z`^elky6RTn&^2Wvm_qD+*qYKZ(|V5DJ?wM0ER84F?Fpv4J)elybw@o@71U;Y+%k6o z#Jt?>pVDv8Yj}RkzF0Y?oG)d~_3ux--N{ekrWnW84KnDz(1xlK8;@662*qFc_oGf(BHarlX{Er$#n{@D>qFhKls60ir)nwy&A{f~bXBDj~^=;W`V8H09jHLe_Y4zsyUw2}9dMnG_fn5Anh z(Ie2XcW7|ijJ4};K@Sxg-{h>9R;^=?8U=&uJkR(SmI+IY(Vt6AD)Rz0UMIIK*4nIy zlJe44UsUAyiwIh9n^Z5szqU5Ugd1Oxas@xe8?>*FUJ7LQiogB`pno`apz|LK2uQ;3 z|HG;+YUpD6U#oVrkGp~D(9>7?w`;+kL&m9bOqe!1PI}1zCYTnR7!a$cs+m9mTa+#b zQcuUPihiN2iY)VufQ0D>3#UG7Ea0DLz3B!IKx)IGm56ajPxxTNt+fB6KL{d1Sxr?WrV+$&ssKFuJ z&VG(#;6rH9dAc&a*@n6%tMo`IX`k}FX^7^51eCqnc zuzkw<6_{TlpqQ9nn1ganZiIu7I6dO~C9r*p`T+?1&GDTxm42=8WHu2^4;VCfEKrGqr2Od>AoRrxFU zxZzQ+J zryykL{sI&vF%Fnqi`4@Tjgx(T@9p{@R_YcmT-LlR`=wi7{QKKT^vlAvdvj{VS_G15~e?_Mkdv?-a1r`^1v}FVNlNCA({F>N>Lc*b|AfSI4bgf@7P` zdc)+BU#nApxdqQBte*&33@?`?=$h??u|0O{?l!OgdGzth^&S(cd&JkSCpI1jkzEzC z(mVurK+Uz8Rc4sgC=uHgM?(Y84t|+q`iDAa$OGMzM`TWDd9O zU7DqeITZQ%5v+Avr^{p(%L1jmgi3^s6RWf$y{!eUb(J+WjlQBz>+hzPmd|PG`VYXX zfe075{)gjaS~~0S7*=&2d{xzDHhF&?cN535mTZa~{+*&+!h-D-={zr?u$A?)paQ!> zIUSrjkKRetd(8LF*16e#jib1EbeNmIqq-GEmwZ(VGeM3eiq}G$62tb)Xl<`vn^rhF zA;~5px@8gpa>=fH`N1N6R#lh4^3uo_v^ww12gQ7D2r%EVJ}kY4PLvJmTUc$Dl&~3L zBNgx|`X+|!s|b*6Z8Q-fC95q=wUUWMRf}ZEe3vhnTdq+;ZGoB?wwrxvd2DW`lHl1G zr^8dp$|krhuj?J1Tv}4wZQ-;`*(6hIbL^Qr|}FT z8JgT=Mq1m$;}vx#U%cT^4Gq6-RE*Ug`y}bIs`6!>hPznub}Tp*%B;&^IXFUr6CK)x zxFU48(Bs+Kwahg-u8T>BHZdd-w)Qc$m$Mp)5+H(VwrXUBpIRzsxU^8qi`BuH5YW=& zyA7cgufu^07%+?#h!|57IU%6?XX7l4e$r~T)U&FM)Qij_JxS0Jrj*-`3y~dQMzT=LR4d#Ok_I?NRU(G|4K#>G z7gBdKKmOhIfSfn6$MfWW|=FM#NoQf!QU)Wd@-NhNh6gsAV?; z7!p!Z#x$mj5!qjaawyHOrwzt9CeVPOI7G{^n!rT?Sv^?dKlBh^^Y=n_qr-trh<0_l zr2sajsF5D;sg{e4#v~{ml;Z3lDb*JvzU|&I_Rpklkq>CM>gr30XkpA-z~xNlS}Y3Z2@& zY1TKBj;LUfX}>vU&Y?!q0kg!>;s~Y_S>IJyfDFe2$G!+vxtk}XmxE+`VC>ky#f&d) zn^sD>8H!!pUrbVYHjNwWf6&t`jluQDIot^{Mxd@n+)muB_%*eVQx@6`_0_U1xWud8IXG@H!oQyyEV2EKC zt6snoLvO>Y5yx0fe(NT>_=DB5R8_R_LS!0gvfxqi2!Ex~H_vO;R5en~p5qBm%u3YO zRK!Coq&iTm>gaEwhk|7EJ!>}451nNtWa8`3m+vo&C|lQ!-XWWhfe(>bASs zkBz_+Y&3Z|mI=w{A&SlFqq@Bqdm?{oU6T?F5OXa_T6E|ARMlltSWX+VEw#bFV~~hq zSmWp*F;%6XHv4;C_`Y#Wt5U}V@lwut;p6@tC{4s zX&%v8p#9q-Kk%@xKzr;$lZ+^VWwO!4uHFd0RThD(?6mwM|5D5wsieCyYmy$&N!d2w zl#5F$9xeyRDc!7!re%iQi~VEq%H~W}Xcv1GA0A&x-8T1?kWMXKvAAUe69+yn20&My8rV;_6yWd&-Mki=b;Hq>H_F^01Hs9+~ zvnQtS=SLnQQU&^RlU^C3;nhLYz1N0pFjPAx%MHZI!IKON$nI4vIv=WhOTs|TSK(*o zPVjLz!`X}>VCR=Nr|6A>lk0J9_@0*45 z0YS9g-Wg9t^qzW_b9l&fuOTS(biB6K;1-j5X^huxL)SSqrT=)>+o;oZ!S9xt%12Dp zd9ZKz&qI`-FgfE-4szCOfpG2e^BTws5WIq;y=fc`7WfBM9ruB5D|1V$dKrn#)120g{W zv#e{mf?Zu$!o<{3BpG7Yz*r@yf~_1y=1;R+|2KqE>KFxZl@```u6;XR4tMT}x~jC7{SE{? z*Oay1(q&91&S7I2Q-{i~iwrJAy}3ZrlvU ztryeRd?r@>3~ju7LGd`LqiwqN6M7C`U+wEK=I`OD>nY~P3tZ+U@9A*S@}#N8#)uf0 z{~EbtMR*XDX9enYD|9PJmBV?@XH<9z;kd`aj%`etdC68;ieiInB>(YF;Qe`A)}3Mj zEnAApHgUy#Av9l5Yc_Rde+~_jJ;dQpr_ZtF#D7#GV#BlwWbSe}asSyr8K8cBLlC(H>W&F)G(F zPPE*6zbiFO#BGc$MCSkd=3l4Od z@S;fH*exCNj!cV@iUbmhGrWu_fXbm$toshGJ#>uimP*5?xBc4e@`er(eXOXS;VA^S zT7&#`@^4A!pd~|G(Wq^z0#xY||2gQsPljHixv(T!XQY1=f&9fY1(&5@Us*ljd+y+0 z^MUqYpUL38I4>&%H(y*gQ+>UTz#Xu!?Z7XPcPi*l)*F2S544*d{1-1^FVBrM&|lFS z!u)Om#+Ww}4wwPH64;5~hS#>+XB^;-??LZS3w{m8I~_Oz&Pm__=8y}n0FiUh_tDqs zrm4>fodeH16j%zT;0!$NW5xGy2lC;2C;+?hJ?w$L_#XPe4}1^Gn@>buIFAifQ>>60Pw0C`b`Mtn2$cLXj3D7XVz17=)+ zjR7-mK<9uNSKxiXj61LtRA4JG7t|*ZTpxz_qz?;}={z8{b%8Ust45K?oX$W4m2_0y zAp#-w8+|3j$ixi-9oKKAMZiMouc|DLTYjC4gqGQv>S4JpkBXF#Vt#a7bV=g-1a5Vb zeuqXkmKzsE927~DBi_#vZH92yn9mLh*C*+h{}*ELNMaaef>a!OT*%9a#N~m=jgTC3FXPjJf>dhWm^B!~-kPeW%z_4A0VogR5dj+s482ZuyZvW(NMO zOE$XIC{H#GZv35s$_7{sfD2FP_0DByx5Sq2zXeCXFpD=9Ebb`B2!F@=C5Y~ zVVynBn-R(l;)nL#mY{p0NakqdR=T(cR|j!}{0*{-;J{(<6R6sU-WL&29#9Cf01^gT z0*(kV337q7N>B%FfYfIfzz4by>J8cf>Yd7=LT5nKM+Eu?<_EcobVJrB+vg7Y2Hpde z2KfSJzyU<*!|wwRXb_?-L3*ubb%)s00lI$wA^mcWBqU z-~p{e{H{v>(5SBkaR3D}_pMzS?MMZvfWm=N8ErcBDFuiH{AIR-01EcS2Yj&9VAnwd zsr&3sIB}Uj4RKjHt3!srLvx{>@-i$val9>jGL`wIf^Mry{;G=1C^K{myFOr|e}HqN z8OnnDN*D$sMavda9u=F?N2Kh-=mr|!(BqrZIpSwWlO5vY!yOMa=R!aG@c+Jmtjc0E zS#m+)of~q1t~3x%t)n}sz2MfKvMZ2TyL7?X5KnE~Y6|5O)~NgILgAgV+@N7W;0>rT zBAQ*gaPA28l~`%mIpMCEd)$=aydm$1FJ183PUX1aT_05_$b8ZK)+#E+m=dCp319v^ zEXx(2IAn&FR~YzPC6pN;rQ2WA1V1rkxa`PWM^toqm7mC|>?3cd=NFmsZG3>`aeAH| z1WVm1uChycH%+kh=vHb_3Y~B}CDb`d!lYe`F92X>ux)1V+2xO^i@?b#VO&Z@iZKC; zE7$`{M#62$$y!572qotbQ4_&;vwk3C7NwDK8soi!O8h#bzGHsv=Wx(c#y^zp{B57= z>*l#Z`}0VpI9FHtLOI9@XT18W@PbF)lV(kl!){Zuerz>zv;KOK;4<@b&mvNaL)#+5 z#v`p{A0lfvvpvjgYb*X zVMCBF@#Mk8_+x63Y)!HN^4z|lroqWeEPsw3%SdfwD)SG{UTae(XIn=iKkVfj{aKZQ z(Hp;M_Tz2qwaT_uuHEHZF!y=le9z3@^lMS`waQ$*f^fsYu^PFOsqR6x@+k#FQ`4-Z zBNbk_45_iQ3(e@+e$$GJMe7mG1NpvwF;os_#g<@wxN8xcyoU9vAd4d^fN=rMeVtMlWl`*^&}$l>SZ*EGiOLhM z?=XM<434tkOHVEEt>-Yy?||?%f@)!=i|S*XwLBTgU{Hcs0dEE(cW~1Om-R&$^Dmti zeXZ%O4-V@;+LXRpgNS$B20kR z$5+JRoxm!{?!a8eAQV8=?a#@GJi2F)?`g9LI>#vep`&oTHJ`ajd9;l+oIPY6>Kt>STUwoO-6_c}Q;Vk0 zp8&1b>tvYj5@mQDIQ>h^Fl38bk-Q5GnX*9LkPL~}lW=#5ODhc0v2}JB*|v(YRgJQB z*D}irH@;5Le3cFlm27Cn4%Nj5JQhIaa>S1oLRLJOY0f@49m8$KsPDjQO4f*sGi?jc zFfNoZNu4b0Ldv+gkCGDzR^~wXxx@pA-GnNxm#j4U#R=(#^&@3NUQ#-&q=5-W5~8&x2!>%z?3ZAm5U1Z+u5d#vw?3IqU_kVC%AM#_F=+ob@{7xduxO zX7{g-lYedwJX{g#23vG=DSMuXU45Pjkfwr+AWre3v;kFMcN&i+WbQSt$hea&tDEi3 zXiqJ(#RlW^F=#dxBio}8Iw&sMXg(3JzXJ}Xza`V@zlYZ$o~J{|E>ke(Qud-As?js` z^30Hs2CKabW$$RrEk5<(_yQ5~(QcLy}tbA&8u}y6YDp)Z| z)w;-Hdi8<7E4gI!w<5o(ZfqN$pKUI+){%6{`U;RpHw#8dg6)BwelJk9N}6H?#IwL(FOF58%IevW4b zM97geY$*9G6s$99nb^QK?1MY33fhS`tS>CRl5i|eXLZOj;pk0}Jz;MN69iGQT{EmT zN`jjaQ=qLxd{!@*wSRKL+D^Wvy&|J`A`~eAH%jmY;)xK!{F)5-iS_3a30d_Eum3&_ zCPAP8Z*{~44iUh!R_Y?qP|XLE_T0#H!tzAH*Z+y8##OhV4nYt$rxtk%3lnm!G0u+P zfA3Ztd_4ENMTDkA!tbP6%xM-C_8wn?{8XA8SvEGr>{S>+Cwfc~Lx*3Nm?$+J1tku3 z`U7zezEw=6;JsurmLZ-#aZgYS(13C{4KEA3YmpLAF?Cf&O9H7@iMmL?R1wUs)v^wT zXS$R;8#>O|0({lEl=iT!*g`e%fucRkGnc9F!p39&`Hs68p%N*R_c`bnfbJiR?jMTo zABgTBa`2g#s7V(cFdZvw!I#o`0(MoRwwdS33uOriyAtH@0;icG>w@DO+CRY{RJe9b zPgA%M6~;*GVGP^R>n!g zvk-Yt$uGMyGxfVQ)sA{g>Z*$`_+~C!^t^SX`B(Wi7cc^;luJ)k_aDso0huK+kz9xm ze6+|b7mA@OdEkXK4TlD+=o5VCn$ z_mA+VOdw-AkJ_40Uq`bLv*icbR#sO(PMN%Dfg!aRb)n)gMH`ZxjDrB+4rW}1nt?h@ z$<5xngyu=rCDOQtH%UlZB3!;fciSTA7WOKP`AR5>kJ?*_P;4!vLE+RrNyc1}Q#Dm^ zS*E|->W&2T;htOi_|fHuKw`-a6nAo%C6s;9udWFB{Rs;aefh(8`U)Ujd{J)n;5$C~ z!SOt%AK}*YOlju}WK*<0j9l+vK5OUY4O!@wS{Mj8=d&2bt|$+G_|&FU&d+d9;}PT_ z{VT3Rqe3uGYHqQ7f{DQi8rnth1yz?UvuxvxmlHN5iRweP4ej~-sB=@vc+pJ!mWJ}~ z>N1ZQeFfbYgrrgXBJ`f^`ePUGPsTj-`a}utVpU6}jy0jvqiO0bFzHMoOE~JSR{?6i zb(-QS{{&@L>MclV_n>*cub}x)>f&?`ir%6F;`(-0RG!fxB4VZ;*yfEx;@#NLep_-x zpkjk$R$zVT1sp0T(-dvuj0u9l{k+Kvi*{q}WeQCFxUrR<7EjSpa`T8%<2IrA6r{ES zaZSC&7KNjyrl}E9YsIL0LDereH)}1}Mc3$TcJz*hWwRRF{EfJvj)dr+^z_^Lf41WN zkp%?n-&v%AVP$y!SwCOUlK$ov<-gO6-0D^}5Ggm4J!u1$Bp?tvrGy75R=CkqZknjKy)p`XpK!}JB0~IB5c#nb2`I`jg>x~?>xqx-mRgQ^)Nm-MtEtZ{2hvtNPcd%i@ zeRqnvEr&Hb^7{?eeZ_l|;pDLgsX*@yNuAPhrL!UZLO*;IB>%+Fn^yc~&C#pY>RZpE zp=B^PBWtPoOmi~|>z^C3i8gXi{G$)Ux^7dz4)&hueSv%ZN9js4mREgfh|Hj{E1 z_E))~Fh4o@>~IUNkCscFhYUQ)<}qeFP;ZYS7oa9&;w{@>fgToxJQ}gNp)2j{22BSY zP{$q6$GAbxaw|a0b$(d%6!~#G;{}Ld@RqgFUXQly5hT?GJ!9G0n1`EQk6im7fHQII5xe!d$3e$2LPA|`rr+i0_r7o6b7WOs8AMl z_{^FJ58U26%V%5lUN*k}B;mRmP!HqpyIte)WfDkSD^7gd#^jDLxN7UN#-&}Tm96hQ z{sE_*H6M_3a$rMS=l$vr<5V>gPeR zIK3^4^TeIT4(6703ggk>>b$if{I(G31x_WYVM=Zs(22ArIX8u&4ikWDLJ;_&bls;8 zjTq{tv|cY&zixDZ{~v`ZtYg^bPiZ``qllpI)US3wHwy#q+~CwXR8FA zM2zRJf^+QN(zbL)MFRB1d4_R6YXV1Q>CDUIA^W_~1W287swWuRSeaqfO1e5$TJ@!$ zS_Ee+97{MNOr5XHoPGaZAZIkna zP?DKP1c4RDT^lrG@Y3`stK%E6MMg=Y`hD1qUBvyldG^f~uWm@s5r0IL;*$1Q0q;`Y zC;ec(JN}7}97Co55}n>l1PqZb*NBfJp2^^7B(;;n*YqB!j50|4rXIGT(ygC}{rALw zn(kwI2}z>xGQ>~0SR^0WmPn{meC{eF)j&7e>LO}{d?+g$|Dj-t$(LS5@5Mi+up%n61S{miF+Sv&@UgJesLDr0Ij09JK{3Y<8%8nr z7ZtH-4fq-?ZI8O>i1V+;`` ztVaLml7lUX6-nY!jxB9H2 z?Ljs^#bSx^!@5ICme$Hj8%G^vOQA1m+%}@bBQ>iRX34|={Gum5YOpjS%w#xf6t54c zMuuDaMLN0+5WDbGns$ps-k`#4{3!UtM?$;CS`gVyp3v{eIKJ`R`|TIX6&p7AuS@xNUuqm2J!QYJwx}H{#$yEl`@5DSq`%PbvDnDwcZB+wUb>pS zFI3K(*g?5>6-U-D;mrYm)Xaa^MgW67^?2fzNOH$aNsLwiykpo2%@un3o*s*+4I1Pg zzY+u z2Sp*Wa4+0Lg_mL*O97xTcNhJV`69+!>3ExUgfe68xL1}!thfAgkWQQFwjzb*v&Iy# z(geEaYFp`K)k(d25@g$81g=oe8)~-!o{839?Unt%Pk{%gSPS;BokTF zDWka6(d6^i>GloE9^DpV2=pI(ZFE0ng&53j=(*r)q8JxZ@*NLuup)V*m0K8J1)OoY zS_(ZSbU=sCO&i3PdxO++xk`Ps~J@tsOvXj7f$D_ot%8GwCK7U{!#XOC88 zjK7u#IIu@Fo4EEo3h#cHE;IgXv=#uNbeQgT z*Q}nvBB7djn2fs2MDOsnCE0rCt8kUC)wr8_=PO|{b!|uQaQwDq$3CJWaq#?9di!qk7)V}Ah$%^NJrD-UoCD82LPdq~=p+NWTmJ(cX@8rE6M)_+>8?AEJ2PwFsb6s+~Ul+J~jtQ{Xp zFcq$?U?1{RBy+8$9uiX~e{26>ZB|{@kumnvhQh0GH6PMO;?O!DE3xb@40NY?RI4~Q zqEsH8QDW7!FN=XMG`8T}8t759@=9B7U{Z2!G&1>h2R0mcW?~-P@RaNu^n2XSNMGbq zjzh`sSJ1lm!OqBPBsQHhDZE9qzcxFC`ImU`B!kO%P|@Ml=vu99{_Za$Ny}~H2VUj$ zuAm3r4GAWP1O_H;2BwzT1F0#KgE1~X4X9bGx~M}LF~?9|MG5m!O+Q8X(5OSWW|Q~I z9!D$MoaZBLfs^sA_|*K4vOIn!aG~x#LqFyj#IySXAzwZ6vYE!9S6+xmkL*$eaeykm zMvk>Zj<-V&3zve}(?*r*!oPp48opnuE`>iDQ(pTLP2%$pm9Q9c6PiF5)$oK**A-Xa zVZV79@u3!f%M|H~Sk@hIYoqf}tJ6LUq6<#fxiSjnibB?Dnl$P1wQYZ9m&)bKG$~V0 zt9D59B-bo`3Ue0BOs&(e*G!dQ+VT@D$_Jrl3rRFXJ_NSJ_00Zx$ZiSuTNy8mWP$Qj ziI#@;8esL4$Q5j(KrUWVhwJt1&CYCImkJRQsK{+$$q<>M?FO>NUMZf2CXI`I zQ((rYOq||*2Sw&OmzgTcXtz2PGYjX@6C!>U$Ghfo_)&Gc1RJr#+@3Ic!D{BE8zeFj zksz(>t%-eimCm@l*OJxS8>1Hn%(@HaXl%w$*)}RNRZEb`@3-fu9>Od&# z=uys$GEE&Jv$ekTM@zku!$0>vwNl5VN{5d3^qjPgr}4I`+k@kP8%EER=P3*N=?RC{ zYdt#zBEo(V0*6D}@3-lkF0(WRv+Ys?1FaqSb%kiwlMN=dvwoiUB~_k~Us~ao>w^1s zVZyf)c6fk4+=&0MIxkn=5Hz>KvxEfughK(-tJu0Qm`#4VX5e$FcS6e&pD!N=m4f=1 z^sC27`tc-rx&no}*LlpK%>sos<#?kI-MNuhQR$WdEW4U4${Oe2MMh zj9joMVI9FIZ;j-fs@^fN$fQAFu*6w{tBs$s#CarRmS7+Dq28!oZXq%*$J3Oxvydcj z+Az#?S1fR&@^Hj@oV_Zcza$)Ax(X?<0as{QfL%wVo?xV%cN5Vf3~so{S83{2{Xvmc zd0Dv79A**!#2nHjQ6}%rmXY(E=kZkev0I<>F=ukRoR@$oZEmnwBaP#tZRT@l{s&j)UjHPCG$klK=Zo${laY9azd8Y04ey|2yA( z8PW{sMGm{Zt)!Ff>Jam}HLK^DuRh=3d8;EO$u?ZQK*zf>>03}K87FU(r3;@GjLB9L z(RNf7749Wqn1pudsPih5#jgXqaIU5&MTKk4?PmT8VJ1Rb_Nvh~5^E4n=fe7>s?I9W z*a7`gc>yJ3uLh5Of#{{Qw(hd1&6(RdE#r`Gm-pvfwW@Vy9Eo&|vx66&Z*U#2?9bJU z2oN216e=-7&;83YWwPhyGJaD_Qb@5|WKA84en^)^VJlbl9y^Rg6)M zH6IE42NB1K(HfL*2l=VwSXWZ=2~_$C5HeI|En7}}A|k}EDq3V`e@#Rb} z%4yfUohb9g*DQ3-`+9MD2`c1&SnyPpE-ZLK5iEJnR(gH=D6i%0Pkm3(x`{sWo=XKD zY%nX2>rD7!9~YtPe0+)VYLLu~AMH!ZZ7e9T;bxLEE zD_-F#=HSTNWJ0!g_HL4}QlRb&DVgZ`Y_P5F2IeP@3fxq6RfNTC!>FzAun#Mqk{^Gi zO&!@C;zH;EG%GN!j3^o>`^66FbMd%LwjQ8$tyRvY%-0u(=T$Sce*e-zfgg3kTp>iiG8}S7qea9IkgI~giSS+BG+kRl)NZ-KkI;LM6 zBZ@=FlK&76OCc^xZS;%L^4C`{y||W%(Y9ZzZ!H?tBYXK&%w7_~ke1s4Ks(|Zn}z4 zGWZvnitQgKPBlJ$n4M_+?Cps$J<({y|G?#t?Tv|^w>L<9z+0pD1<$OtHvv3kY8Lwe z8UTC;fBES126hbi7h|Zi`9Rqp=~&C{l{z(1n*kIpy6}cnVwVL2EdXLb z{iPB2x!J~0t*ZILXr6NBF!gw|C4TYavi2(d29&H

nhVkSuz{srDoDfGdH9$8yPt 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%0D~H9;enTVN=GBl0X-Zf2LqNGO=m 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 z zJ37wc{}d#uX1T3@)Bgr&;hG4QHf{&0b%zpit1qLYj4`T6SCP*frbaGK`sDobB5HC? z5Shxb_x3htT`v=XK8?FOA~oinWThJos4v*-kZAI!C>kV~S~6!r&aOQl=f!Tw63h*Z z4Xa=yP!v;u@yL!^JW~w&(^BISLPc#c8xys1#z8okmAltO4ed!?UL7U}t-kwWil{lQE6}N6|9Y%(;mKt|HEFjh8lCpa?Vxm#T6%bYS8k;a!u~OjQcS6D;>Ky z8ei3FFmwlL*Jos~l!Pq=#Y^7PRe~Z|K79PumJ_;w#_@Z`qn#yI)d=ZM1VD}Kdr__z zs6^jjOC@w%oxlx4J@7}(c~=HUaW^oZHQh^z_w9peMX#4&L6dVHy3hmDCQegXJ|00T zn#-&ggZvl`jn$c23Vm0Z)F!GN2ah@<;y`TE(Zku8l+ad`b36`F4_iNHsS(| z+*uZiQTOEZ;42jGjLG#if=_YgW2w-eutA2Jn2zQdr~UEcd(Oq4Ex{BYgsB-VO)ZgX zC5T!srvVsEO*MGH^rVI311z=yex|cPp{91g3qYWhm5m6i0w?C^t18^S@U89yWthGN ze^~?c6%>y%LPM9>^S+^=(oZ$lAFmjIKwf~GhPptIC`4fSFw~o*xpy8d2afQrQV^RS@qij>q`P87OLF4oZp~ zfj$n!CFNOk><@|Wl|>q0bhVlfP*6lkr~zJ%!jst<|95-aF@{ododijA-$>cew~A~1 z{9`ECyB;$@TFA|0RX|G0J60@LU$H+~xLvoK(eMu>n*arXkXqTv@m z|7AE}&J#`&YDCLDc(2+--1QiB+DonM@xI5DDy3r7pv1t{Gi$z@~`m*oP1 zlCVtKkRd#RGCssTdhZmXo&Q#%04_UFT4V{V=qL5QfW_|LQ(6r1FB=cZyz4|#1VARt zQYd!GFupWJO?6hK%ZHP-kQ~f1eo6ts?U?#9UQqI8Qy2`9k3|Q(!XGZi+fYW7$Rcj- zeMrkquC{V93Cw>bwNJB#83|WU#vf3)Y4L75m%-g9b=&=SSQoUQCWL z0uqN36SEe{pVP#dnB`n;RdVzNYIB=m;n)deq~*Ph<)Jz}a^haOSZuKiB&2LUVdz6! z8z)E~ivj;{{v;8}`e`=OCTC94Cscs8R0(`0LInxv``mLJcoW@iMEyKvBCsuCsIr2#u47{P9F5DH=x*8nke{v?deJH}YSbLou-j-pP_jv5ti zgaoLdvGcVVt05JFqZSLhq9SyvM(DZHR0 zY|_6^QNf|wunWbGhgV=Gor9AA@JX;DhF>%f3_h>_D6O?3Ih_;lrT`UpW_kEke+X7h zLOsk(tgR#7lpRz}R~~Lqd(olL)Z%7RRG&|y#NEhKVuo_HuSdckQz;5iI|)^n*O5O7 zTeUltnc5?;TD0Z1R5!>>DaEg+#r(?v?{C<*v@e*_b3k}2IhhAfGmaLm$dsR*2+B|S zv3?9Bq<$g*Z~#>rofrwJ4$p_;2E+hD$0NSs#3lkY!xJau-_=mtjBANP& zzF6s3(R64w)J-zODUqjBjEz&zWcpI^PkP0>3He)=BsXXItXdO6ucGpiiWa6GP8oDI zjxI*E*!>T@DWxTJcxQ2M!z5IL!lhkSWm!HM)~=j&O_t-F#sA+v#=f+aiC?+2>L+k^ z`_D~!64?w%RG#!L5Bb5O!6zK#^5%N9tO%BLj^GK4Y)8w306 zZ14E*G5z|NH3H7+a~nFqQil~89p@n8RH^zYf-aDG$rIeFQpEWa_N3LTgg!x|sJZ|W z=+1-LjZk&#cp4?^cq*kh1caNDa>d+f%o7QYYP)QJ>ZwU8n_l^JLW{(pCh}R!>4cB@ zeZDYx%Tw7+E2XQo9>57@n>!~;ZO&$17|eQp@nz^YCQ+hbYsT9$xO2V9b->Nr&sNvA zu=3}jzh%bB_TIp&ZQ959-Npw_Pi7ng@POQHGcRtuUQl~FnkVn+_ajL3f06+Grelwc z;vJD>xKmw%ck{F4PT{nEh4M|hhhCKP!ZZ-jl5)8!ru>Uv%g;lLVcDTE+{RU z+(l5=453^oLLz`mFia!&x>8)cCY5LKEZm9S)i%6n^+JJYT|qcG(vV(AV{f>slJP+k zfw85YF!n7>${GZAo&>z3nuaM9%_HVpIK&8~B8KY0+`&QO`IEFPoNO`TrYs`sz0mj1 zeqG?OvA3Jt>qR=SeFqEdT&?y)hLwXmIXbzN&HP5;!2O=89~QAGp^X?O0V6~dXV!eN zVHA}irI9V%a>`t_zcdErUp_{^owTV|i_DwKt4DH#!6E`jptJtR{7)I;>_Ke5@)2!f zERCGXFemkF;TrDH+6VrxbtE$5B5I?xO(F&9dN{o5a!v6CCd^o8eKUR&zKsv`cX9Qn z`1{Clr+Xx=X(Uso-e@iRFb-hqXm!&Nk4%GUin{wSU^0i>=xb+5LQ!lV-ej(Xm z6A|2^LGrs0y2~*5u2;RyOiH~<04JQZMT073-LRcw=JzNz|Jpv-J|m}_)*7t#4~_b81RBdHNMa}woGIexn^VTw${{&n%Uqx; zW7PI>k{ej*nd@zQz<-rYe^2(-HD5Pf+kBCJR~Qj4b|~1Fam}dt$G8!;DEd(xVgs%V zv#laMYBme}&DOO7SIUBZpQmnsm}R&6U6m3};P@y2r`bbtjvI>n;bonv!=7G>0~Npb zo2D1gMYS4s15_FPMTV{>cVJ&wQDV)dW&3q81l^NhxdEfBBj-9kM62#R)b9XrwsEN7 zm}b*OFWuaSQ|!wV7hH1BWagm8vNew?sGA^yAl088dPZ*xbl%I+;ft z92w-8M~ktuvAVXn-rT22I?##RR+VB2l`B3q;5dwm#!#*qq$ReL14@A&I zCg51mIsqYKoo#6o&@St-1@y1v9HF(eNn}|>Mh=sA1H5YaMwG7t|+sQa2)7Bhwf!gruSdyM6r?IG0osE5u_BJ-}bdu(z%2F$q`5%uyt3ctjU=uOlcWHz_pL2m&!$)&f9usTYseHh66K0(T&FJcb># zscRaWk!?x_Os%OkjFVAqrIsQuhT++Ku{Cw9(KfkS>apxmAHg532FfV1bkthf6t{v( z9H~(x8fQ)Q3KS_@A~R(jB57^WWXmMAE`}Jz#an)3**iX4UUu;=bcc}4Ujx}jDyn1^ zJ7l(Pqq?qXWxGVsULA7FIHb~Ek*T^N-qA75AplqkcXl(I7P)f{)6<-b#IzTmiMWR4 zgv`WIuf!It9q=6-#X+rmIcy`}he6Fv6j~i#_Cz&H)=aEwl>mX<-EMNOEXeUIAz6O$ zlrEcEd>d?9_(Pz*VoiBbVJ(_R=A#FXB57H&#kJV@te7a23y>~ zs$Fl(){G)Y$F@AOE|rAu_`@SJZEl0y61pg?YnABcI6725fjPL`DsUl7Kh3RUwA2s+DNPUz z(H*sh)H<4Q9j?FJ*@yqMyrA51NNpoRyHdpQ!WshW0NzF3msWI_zO1c$m%mmpktF=*VHBicF?61tvHfo-@VDdIL)Hhb8@YI&2SJZyjC?zvK{<8alVp$e$+3>0- zT&3g#{h97AzBfxsnjY8E(B<*AT-o1$H6b-wjBJ3KElW(68KO?=vb@k4=BIF<{#{#0O1QH- z_RG!@CufW>niT^w8$}tfEbcE+JN0%yNWm<~GelofTLV1D;-y|u&>}#3ds4;b39nl! z+Vf~^|G9i^RjW!{;YqOb{H{VZ(_3QLA#dnI^9iXtEHJc2uX%m+pH{3pn1g72UVrI7 zuB7LNjmt(C+BWonF{1r5kdBgNQ$2;@{|8V&ufN_M2n{u#3Qp#kX-D@Y7Jx)u1&&D-t8C2;Rh&%1kU?$--#H)5loVa3 zs-rPSHSqh@VfPYTs#07Ts*_8I{W@r^O(mP2Vp_T55x3XdXbPb(gcgvD%g|mnPu%4^ z#yonk#oOW?n*#+HJQU;U$g^r=#4{MwDO-OS4!5d4ZePEaL%X5l%n_G^5LFA7&Yg-}mctGn zw2YkyIP%4)_V_w@e=z~p5gj|VToHfp#$xjH;2!l9NlXW?Gdo1C-623%G3<^U3s=h0 z0fcGjdNh>j2A9JnRzV3BY4ZURK{unt;8ERw- zI~d>U3+6AJ+II6+>lt@rT5)OlRObTWMb6D@MD)t@Q_yteH7u-k?KLZA#Yjn2g3_x} z>TA^kmQ8UswzyN#uVYSXz3Vxps(z7UlTDpGyLgy$97J80rkWm@;0o-7N5v{oU=}wx zL!C_P9gQnvo^H3ClElj@rgUKG2-2ah^>XhWx2x(GuR-fpDGNPkGD*N>RE{``*|bZS zbYYL2L|aMZ4ahw^z{)HVjwV@zlNu4`-Z_U@Y7ykBk;$Bqli(&>_x9PmPF<1fR`;MB zEmeC1yXGWBn!l=Es$KUwTXiC@Yy0xKvbZBrxgc_KxE31?hid4uwE9`$4eKJ&N=GEe ztxNfH63<<_bLKRL8MPZ`UME+v4rj-AMhBIrEQl17b6mcnvLQlu*UEe4kk}GmgzIrC z%1XTt1XE2xNr`09By}Z%b4|?uPwtU*nXSX^4si+wWwWh5dSm&{8J;*m|V`h=VCv)R(a`KeTS+HUn{V5N+pQoZG zG~E#co!gj_0G+atxs45-va>tmI+1KfM6@D#%n@EAM=c%UWdeyC^U_eKsQbhYYsYz< zE0^Ldw6zYeQ|_8HY&tbd35=0tYL;e@vPeRe(b{=OwvyawrPYV!#r&rO&h6wCQ^Vvm>)2c+iD5^G(Gh^` z&Z)^|j`uv3E?t@}!?&>=%cfe`liSz+ZzZ~eqx3eWX6y*NxjJ@5TEgpn7fA<#Ot#h_ z0~XL?VO&9Ncpa6vbKdc_k3V&U3B*s5x@5~aRS~~&W%Zo?{NbSJ{!J7nv zqeM#M1m^Eh1``fze|aKfH`!@-aVT0VeW#u{0*6fIM(V5N0bF_Qa;V~DvUQgyHqOZ= zYIETW?RM)JkakzY5ev9byztD_43byI45x1x~HuyhZ>~BjaGCn5V%a5wKcR2g>DQ< zC~YX{AysChZtg%+JMrBdy$)J|cGHK~wT?SG(b>Gj zcMwrPHRf3iK4jFU)m0hTsfu(QhW1-l#w_TLK5Kgh69t@O8-{9%YmvfYS15FemClJ` zp`#p5{F(1gSVR|Fgc5lSR_xY5CsURyCLCkbjsDV= zN2Tg`p)04`9x(K^FLOkZ((w#>w7ze9^w4QNmY>)m$;EdU55WNk8L7FLhIgQn+b5iT z6LbNL%FI5RrwSLf3(aK3 zj8alG{&ngO4GIQ`0 z=*!-Kg#eHV0XhbPxd3e~k-zV$-}lw;2kQ4j_4|?f{aF2eqJBSBzn`h!&(-f2>i0|a z`<43rTK)c8{eB~Vd$RwqZ-KG@VxGeQeEuK%PL_YqevtKkWc%rtb_~d0#yP#`8rNgr zaRZ-4TswDRJ(F9qzDKrq7wB{@1{k;TX#_C(OYvX?cLTduHjym6&hNh@Qa<$|Iw{*4F34V@FG+G>L(5_ zvit@PK47H{xD`Ybba@B{F3k;?0V{Ji3|hQV@TUF0r`ED_n_Y~Y3t5<6iZgK;V&V$$ z!Ny!S5wt-JHtUAt5RWYYmiL zd-x!pt(sh}h;(qzwBVVW!O-sN>GN)d?md0UTcJzOE?GHS!HYkGw{<{~&*GS$Lkv70 zN0Ebh4vw2Baxf37j*e06l+trEcy>Z=6Cg3G*Ec zE+}-_8;eJ8hF(}adKVlsBRhK&vO#vrruYhDHpAc+DB1Dzi=F-w6NaG`L_=JcH_(&;x2@#{(k!P2T;G;Kz9n2Ws z0u$TPjGQE9#gS(hUMPhyQmL3QfQ17dOGGpx@jDQwqJlp?>dnNcVet zZHHt(K2{bcH9?^-M8)0xUcY`5_^>=w>GPgQuQGha^lBi!GH!z2_^Q}>)x*lX;ADT& z1r=kgjV5c_zd6HiZgb|cht(CPZn~CTiok6{os&VGPj7)4yP#x8k(a7u8e5@frnwdT znLcYPq-OejTfvj*%i6}4=!IUbFi9)4^}=MMFhvxmnuR{Cu#0b0VOq+Vbgj^@6?XG` z^=&Xk_KEuD*OnSZvdgAa@*{QPZcATA!Nq@*J^kOro zVw&Xlo*84=!tVYqcgT5J56*ui#QNjEk@#;Z{#!$Y;P1W}$~UI%PaR|Fgf;pt(e5@OQ!`_r~Sp1*sc-=IqUFxL&MjY${um`-(tS=gmVy8Jf1X@5|4zA&!u ze)um({maFFlW}UBU}zKM`@8x5XS&_>uzIAQOt1X@ZtV+uSUZryo`650+MDUnBwGfH zFdYXP8;|TU0g~86=)#JjJDUW3*c2GZrXp)hgE6cG#|jgaK5YGAwj7>dE8%%o0WY#j_#0aVU$T1mH*0`z*;@FH zt%D!gddAoWrn6I-$xdfpb_PpfXRSDLa8(&MMgzte*XvUBj+o*R!kHHnxdv$ERD_W_CNfj@^r;yVwov zVYZd+!MDF-H?pVLP3#%0^&HlEku|Zuv)kA!So<}0CwrUS#olGjXbs^b6d=7S7a2^t@V+?|AGNi0_e z3sJ$2N7Zx_anCpUg9m8j0E)B6;$Y-G@NJkux;HB6b zibOV)&&FIgk~+K$O(2lDIZ`%JZZ76Hj$%5WhtO+aB24o!r{gFl@N&!qQ}`n6&5~ksu_NL5{bU>=mTF0?jn&3wW^9u>Arskne6JRmy@fd2vyr24 z`ByLB&}~qVX`GmG6RZnn>L(Jf>wew09?cv4S+Wg{DtztpwLsa9CMfUa%SD0G%a^|m zre_NJY@+&%S{g}p4{V}W5Ua{2#u)NbPY+{V6Bs>=9T|FMp&s<>_|eir1EE6(+o>-JkgILDl3?oHb?VWyI?NrGpEt6Fb@S#S18{hHD9J*C%~o` zi2z#Kh1d~F?Q3CXKsZ9%LXl=|M;I;Nn46L3EnmS_7=%CJt@CP(Z$oeP z4*Hh=gaPbd5M=McF!nwau@7Jd`v~ThxDG#79yW5#j+K=2V27f z>?Ab3No#I|WVCpC@Fhr7IvVz=sEYR^4V?iwd?}T&zHp4>D+|?qsk9wUb`tW{GUO|h zC{0nd!Kx&UqFc>YOZw(G+GTvXr0P51cam;(bR8bz#}QRCFI4j5@mqAt_z8T4QvBPn z4$0?{Qt=zX=8Q*RVHr{~J*MVo1~Z43OY;39GeZ`jx#JXkncr%x29dvk4+Oynp#?A) z?foG5c`jt&Z(m*jgV6TP!{6b2xWq%y>C?3yM)DKoSW;o295Y8eW%Cfe)ezd1yh1@c zOqpV4(ATd87PT|Hc~P8|V=6?^=aq_G_Ys>T5--W{_1g-`8NTeTV79>G#cZ}VURox4 zFTcK(g@V0^XboSM-`I|1YWU9Fj$~?NY=r%N7XE7l^6~&q_pK~M<{0K%ML$7bE&cTOMd>Hg*FZmh-&*=f@nzAE={t_R-fO|1 z=R1zT&GQQfY^cW}ZG-e!d4^MZyx-`;kfnTiX~)wjj6$;slJn9|pa+u}Tdy?N6k2}k zS_C82Z}_cK&n)!#J<6!_droWu%eNSR3%z-Muk382^?lR+=QnDs>Bp^zEHj9J)hLN0d`Z>TB(qad$_zzK5|%u= z0D4R9=0R??_$tzPXnBm_t1)MxeR8Z*4^8!X(lIq4!aRJ9)G}SMeWH2|da_DhCHWSK zG^W2WcM@_iL!GyQpUkU~2Q0cULGi?mq|fkog4977TcoF_A^o<%iSj{5wX_wwNu|^R zAz3Cl_#<>QR&F`Kr*@e695DE~$UVP6#kdi=@$*n@oezEZ1rX#HA~T@}?rZPJz2qdCyDGeG+LE&5r*h(kh!B_sJsnso8P0e9G1Gd0Qad z+{SUz;~l5nF~?~atZF5wLgF9(8x)>bp)}ZpzWg<)+P5I2*FrCTJq+O6U>Ls%1@3m3 z%5O$-dkd8F+v8-&66Gmb{1hHl@Xt^ps5i0uZdjeR2H7I`AXG8Hj1M_xNgJ|uB-4(# zR(sQ_ekqwEyg{`(P5EDGasJmysI?I-?OM7&&izVr1!$VEmUTLZqGCJP6hOCbVeM=1_K?%vLuKN|BkG=1k*8a(@Qg z49RJ=nJo}$fx11J6v^>q4r+l@nia;%@-+>gqxo&{G#-UN@I9zP9z!r5$C-Kpy7DI> zlm8B>?)Rt|_M(z}3R&t8FpfV9llgN{!ka@yQ!;fD{+oljl%ko=b^&k`hPfNk_iEjNnFK3k?$O6qxk&Bas%+^GPDMKGJyd zB;oeWa|n0lU_wqx>flJqHP>O&4b6jFpphyKM@rAbIi@^P^(g#cOj&-~+7?(xJvBXX7+p|eo`J}| z2=XQAYj6cl=b6Y_L|=Q{u;d;YC1f&p7QUtFIvWL%qr6+NHhFwwgZIN}`yikfqMvI7 zAA-}D`ugmKGai7`ngD%lo!%p2&MY)&;<~`uG;6}IZ-%6RNIOf;ned%Pb4C&07FGZ3 z#d#0HISh(SjdWYUL`J;MZ`~ljI#+&W`mNzbo`C0Z$lnb81D?kKDc~1{NqPPx{C1-T zMP4*`lXk&*s79yK`%y(nc>#KPzI>U~0vBwClz<2%QG-p8g^*-R>cJvkHrg}_JXPo` za(;uk0p#He>E%WXMfXY?PR}5dgH9{5>Cuvp0ecUAc7`0CGi2Xjrwz$&C^MPC(h!en z=r^Ugw6hcP0F@b-ng(7CF|8TUQxnijGa*Z}AgColp=QIeS~5)5Qel?X73OMwSgLh{ zkk%clwH|Pa7Jv;}PdHo4gbTG^aHZB8uGjj&Em{`bruBs#T0i)$)*qhG2EfzWKzLRg z1b@}C;caa&e5mEYms&pT*Sa%98^*laaF(i#U}=~SV7|9DlJ(UJ*jR zp_zi}DxIIpbx9vS{tFqhz7oqeN^kReRA59+Uf6+J_&lW3Bs9d%;^$+T2Y!p9-+5aJ zH%b*|K?rW9OID=4JvK(2m{Zh=xeGDJWv)=#s97viK@enV3W7o=q#z=D`yzg^lB)BR zQ1<6azPECb@0(koD45#<7qyH2Y7=leCW5U^ij(<%6-uWZX(y8Tm+)Vz=2xrc`^Pt* zyBE6VqHwzf{Y%u77t5|#YiHdMTF|CrXEU&~66mhYguYs7T&MkA9_`QTRi_v6U*Y#o z{9cpdwo_wTh}|s0ZkD(bJJFaZcPV=pzr0MAQ+Jmuxt)RFBEWEgBRVY-oy{o2J!zM; zz%TbWV%(GVEBWBq6ls^DaqNg@EA28A6G{T7U5=&?E6d*t89MqsOSQc6A|0W=q7)@= zKyQI7o6)BDbuc%N?SkJpf*HH?kYFCuoOV?nSsiUvn6?rJSb+l!qcB%V6k=z9H&JgtgVHpwhm6!)+5hskO&!%^s*QwH_;VI#|vD{U*JkdC+^Lm z1SNTQDR-lYt}CQGB}84R=4B4Pp*Bo}zs*cY13)`B&J{D=ZcMiuQ*}c*nhVXHi(jKv z<#h1?&IGavjK-;7zXg&IcPF*L)q8TK;tFE7nP)93{q+F(4#_~fy zzDeqzO!P;IbA>yQYxrixIA?+`i7HFYK0>~wNYCF#QHTv?0Uhb#LAX|rgE);4r_plN z7L=CgUTN1!C`UT&xKL)f2+iVKaJIP2IZ!5}l)4sSqj|f|U2qt#OiT-zb#e<_*DeCD z-5h7RS#B`@Iy7mW@1tscX{fZ^jFcUNXfY>Uns2BPlXCscQJJX8vY$adSimsBJJrzLVBZW@_s}< zk?D*Qz4&i&4p#1>Twf%AGVYWMjnG#$M6VwoN z33yXtzG=F$xIQ8J*EzMqkO>G)n3&|0YIb>&@hQ8YbU4L#ePz-&46 zY-i~BbHj|Z+Y0q;zkUG@9UHi^-Sp{6VCczU=_!z^r$U;Z203~+2b?{%lO{D9g`9 zb#`Zwo|kqP+N5`Du!W*LccBX-THu~0NTC-2^sRU3Xc3NV7vR&g5%?VN=z}3e&x3S5 zAJyhi$kvC$Fntt^)C*yPJ|<2GPUd$@;3-GqkYVX~DGoWLqv*JY@4#VXpkLRll-Ip{ zry9o7N_kB|^ZfSG+z~x`jf> zR(@&I{y)X7@FVTxIL6~RCg3=z+k-;M(DGlNH2qN`dl2- zJeZ`nMmu} z?VivVA$W`91WuA`9wnjG`mJ1L-HrZ`)8H?#4k0R=bk@4EeCaw``KW-K^CfD$X*=`C z6;HcQ{BreyF2ce$;$@&T;#t`CRCE_6*M}XO`BFlCaS+-JS0{Zd?afIkH&}Ed$ zKHGxdk$imG=cR2&h2t`BfJe0P*ZL% zvmGwVlwOT5sR<09cROtG8x4g*D>OH1%r7>>@Lri)AzzcRTHnyhrG@xuZ|BqQeo<)p zyneC9Z&Vfv3OnxqORvmrFv@SH-M<|&=w};b`wgcHi@GqkLpKyvvc!+XBmAP_ytD4^ z3J0a4;(?mT5F zO?7r`p7hM^5X~f1SIe0izfpU>7fOgseH)k_x!m)>-FmO>FuNBad3vw&M(aAomT4Y> ze&Ni+cnxcKu*S_`(g$5(cQ?JN*Lk7Q`bL5C@aJy2FY64?Z&0vy)7xTqCK^?s-+|b@ z3$c4QN|<|)B6mQhj^>BH6ES)}9HT#gqH-5Z)px@jR4~g>TAiRj1XWlT(I15k`W`r4 zf6_IkC!m~hc0i4ViTq4dA3Dxqg~S%|?b$B2&Tz4{USZ4PkMk!Kn=Mv5Y`P=gJ~*+D z=Qr0vGHn3rb0O^j3bwNg^*KZ(FF*~#xzCreZ(JzV3# zram&Mi$N4QYS+ulh^kk>tG|kb zX)W=B9PBnJ=ttcC7KJK>nsS|uEm&{V>?WyCPMVFf7-3JKXho~z)g1-94&|m))mEIRHME??X##b;}{~BlX8z|QQ1Jm_yVYdEXoZ0VO zlRp&#ayXh9hMC=hYSO}h5(;o#fir5(iaAq`-AdCy33A9G%$@f=8S45Q07AVxnq8C>|>`f_|d~9xrPGZ;*UZliP2H~i4k=mvd^?l92k0eMCMh8R7e(C7u@jNVXe^mXNn zjlSI<`LhVtK+KJn5+o0C885^IjKc#Adq4%5+&EQ^lt#7ekw0p^e~p$u(jf zS8A+-EZPhBh}_wno3{)0<~8TX@qB)a=Ml<%4$oumsW_opKnujiT7+{QBpd5-x;H>~ z<8yB%zJFc;6T)m;U z%i1sVS2~a1KeWg1uMqA_5xg1)YcggTJO=dR&>m69T$K zju9~SK{7G;)A@uSk%lm&li&*i9hjoT39+i}Y8f(+ws zobr31z-We%#=Y)Tk3<)tOzr`vb=VkUC%9ZbL4q!qizVm;>S&2r1O2c8%GRXeysn1x zD-~_cc2Jz*qBzF!F-&I=-5!AH7R2;}2=;Fw(|8C~(!;2d9*x6vs*CAt7t`4;muI_} z&UP{V27j}iHXYY)_DRzJaeNaD>OiGFJ3gjTpBvw+)j@aI>-PxoUIcg_lEza=8h=2b zpGNWj3`*2L!Z71m#P@S>tnq@o{MAY>e$t$rOt_%SXv5sHK1j?CDL{Hlk$z3C(Var@Eck(KjuJHQ0A8Es59nEVqZ z)>=pVscR{3$J)gGBU~GKJzaASa>?UZf-tJ`kb{ zctsinL^=!y}22dA;fPnD6#^U zu<~i^04f_9`|<{?BGCkA zHo*jJ{q4=rKR4eAj=5C^QJ~{^M8y?Ub3tyK?>)IxI3cezPoi;l-oE|E1*ytws>-d9 z88G*PMU8mq1tQc`pviAFdeb9dJPz+{L2$^B{pX$_ZRC76V6@xyC5C_|h9P~7fMhWe z{9+XJ5`~EH(NG}9z;ICn$BJWNych?Q#dw%5Cc;cn4D-b#SSF^x31TXQ#0)rD%z{Qy z3TKGfaITmO7mE3CiC6+xilwkcEQ9OCa@ZzLfSbe$xLuqGcZ(1_AXdU7q5}4bN_bYB z1b-7X@Up0de~2i&CF#5{R+KUKxm?ks+KLAtIw;FuotY6{(U-54_ z9eeW9-$7Bdf1KJ0)-8BH{A)8xll$R46a?>=%E(~5g;;SG68YKS6X(W>g>Eiv-CWqZ zDN^>(pNUYRqtm2C25=)QbNGyyYcFhYD0zXRWP@fODYnxFi2d7!svP!EpC7!u?-3BMkp5BVT!mJW{X>3uDA`##qDsMxC068 zPN)=j!)mbuBBB{i5j&wl+=oPWKN8&oaGv-r{8BswSBXcE;2wpo;tAI}%ZIK~c?yJO znj{h;h#Os`-{>O!Mj7ZOO|umzTFMXDBqa%nyYKlAYRW%Q4#v{p-k7`VmzDwIJ`XK% zX`78h^^b^ostLt7?c(mY8IsaIAdy|SC!eCwc@6^c=RFkW@6QU-dZ%0j$ZZ!o7f*pM z{(z$KY3L%Jfu7=z$f?gFr~V1D#h+oQ_zN5({tn~BONhLe5qYn|V)2?Q<+~v8ga8`$ zQvRc|3YNMGcd3%{l*?3s^`#OOH0=HO=nVU8<>3!_2tHiOcEd-svVjWf0r)uoe)xDV z*!h_cz$ZAkPxIUBq3^&WzK1mN0|bzSdz%{cGmW@-!vF~l$eg3IF-L!chj;)o_)v|w z%%f?VuDGF5>74rz^B>MeEPjkCQXAU@+c5tb{`>sVZO}cBUP#73D3L-xZQB2LdY88p zD=pJcd;mThUWNr8egi5m)tTlVX2D1;GWoE&-W?#6(><8DI{b8Fq0B$!2 z!JTF{++z-Q`5;A^i3}Flpc>)RFm;B3%O!x79eVd zAWB9+hB*?l%uz7NEQCUHG>kEiffDmrcX)%qr|jXvxKP?GH5AObi(%8$P)f)Omi01V zsIr^A^e3Mbh53}9dnzjpO8Ooclz^VYpfvYUq7q0C2IJ_fY5yxu#fkXy`Cb@9KeO{5 z9gn|X?1NOfZLXKxHTQ)^23xPKC^+yPlE`q{3%6018-#NofX{;(l4k4Sa~Y&JCjvK% z!DCK>baOKFFsC3^ra_K59dgYXh>;Q)Z_b2ba~8}nOOas8;COQmRN-&LoDU6VITFkQ z*PL3cwh!wlC5CApZpm9hl@08 zhM~W?3I>~NV5nIQBg`5caxF|Sqpqk+hdgB=jzH7)LM7{GNo5*O1e9}DL`_umj;-j? zY%N($eK|d2t@EURM_ZM=!F&`S-!w}nPtS`FGD!Y*cG*z&aniZ5wa`4NjpczPrI5`4 zZNdK!S)5YSlF?{1?cW;^%4ie05=#z>L>sg$qcc|K*&xhwz-yk1e6bO_o9ClEy#P^j zA>^BvB5z!VRB$;`!Ij7#zlKutDkwLvhUMlaIMKWYD$Fgg+PoG{GOvTEc|B6ZHWVQ@ zy1r()QkNzy2U|;#HWebm^$yN+y~*=j@8B%SJsNa}TD4Tr8&)gy7s4DV+XW&xRr4tX z+YHK-$$6#HMfByn1lEp+ zb|Che5qtN7&)kjJYk@xIgQ$%jLc)3&^2|qJxVZ<4%*T+h9!J6ZBuq7bhy1h`=Az}l z*nAp}GoNv#&TvRqy0r+BB({hrR=U_)>Bg^Cy4X5SVur9aOJWAKtky+~T^{kST3KEZ zlmns#_^bDzfPH7Sv-8eJJMSEpYl7~%Xg$b_9==_=8~(e89?SCO+r1FTmxdwYC^cWY zBjl}IQAU2lyX{x!&A%hBy@WdGRV1p{P_(>`D0u@0ns35L^DX4FcMui-M1pz`iRlAa zVt$OGX z0*>~7Dxmlve5ZrMXai}GYBxJ=`~H3x{ICm_r~Qb@E?BV}_9Fu}r!yeexP`GIJ)Lp1 zx0u$t`Yxk-=Jz<(A0XNM5si`k&>M>;S{x=@2F$U{xBzaU)=ld!WAZ^6QXpBfgm1!; zfXrQ}?8YT>ZxWX|Ctx-Q$Jav{P}gVyHO|wNLg^Kh`}W+aT~C8WIhbg#o0SHpl@7M$ zhcv5OTm-k5+=mA;7ZYl|lu)Cbv)3&RlH@)-qOqP@h63azbxFu1ztFcqkK7i9Zet#8 z5j65?zjX^Un*GAq23_$Ln(STDnVHTkGF@9>@t$0YlIK6jJn?%8C2FlcAgnA%w$OpM z20&kHAmmtsV7L{8LMz{uG1#+feox|8AwrqVsU5zUi|r?zr1leHPRmr{e3I5nU9K@n z>#f4Ble9i^7qLgn()y}V-mK7F=+|+S>CPwzq}`X!ye%wgk6*_Dc5w!nLeibt&Ccj3 zpWJ?ABXMM-aAbwh%{m4$tufHwDuSRj4hpP^ar08>j;zq#DOuFvJ`m$hjfUNcBb_31E#FQicG(;8Ip4Y zx;C5?lu5w~5A8%MGJB$n=r{E3khBvv6j@CaKGNmJ`n`}8@W}nUu~#_(&*Ln03za|4 zd^rEPw5@*3F4l$Kded1NZS!rStsHR;2Jor!5m<<-P1ggKMvpBl9Ti$0UFgz|Ue1I* zh}BXstTLqTIY`}e!EeojENec}OgRj(79!0ofic!n7;i0u8P;(y+d2Wtt(CCYs)XaM zFs!szLD*UiCtGV^y;TKgSSP{dRt;Qh)xr%{1a7gSaGTWt_gIZ^pS2ctS?gerwI2Rx zIj70)LeZ3lqKjBspf}!4iY}ARUTXtz#w!qn`g0q;p@WNe zpvCJ0MtH=tHK{Dzg)_du0)+b;EOr7mwSwuvS zvA*}Se)k{a0{Ss&XSCDO8hBJRT zjI^$R(blhFto0ixwywh2zZz$M6VCoMu*ljB%dP8h=C?tubu*lA-3nJC{cW~xbIQ^WkWIa)N-{vDJAZ3dGij}>A%C>#e9b=b?%UIMVGlga%NKDT0T@-F=3dh<;#|9 zVXRi5VNY;A`l>^X7jK6AE#8gM;oDyRAXsSQGm=AD4I<% zZ#J0BHyVqx#h``7?aPs;9IQVeEKfs{^$f!DM}+0sIL|-R-Dj7n_Sxy^mpHak5@K_t zG8ab0!sG0Cb$a?qb%&0#p{AQUwy5^iRJ5?%W(TX?DK?X*=k8*8a((<3F!E`44ZX^x zS6Z;mD`!el=*S~;4m>(XEK+jalG31Lvtx4Q&#*%S(gKrF3{Q?doJ6~McCk2jw+ww3 zuwI80>kU+!Z=(o&2S!-`gd*!*WPJ$Pt#4h0Gy+jqD4pCgH;1UxMl0jtN$nV=q@IkeL}+8Q*rxLPRFGv{ zkYYVfC_BzJ?~^ZGU!4E_?*ygQIV-qt|KG@xe;qA(G!sy4#NE^+H?(@t_x9*uqfF@P z5zyUZL2r)-`gy!C*pmeL9ven@QsOk~IPF+>CF^`;O^?&Y${ki5j+N_N8dB^q*P0%u zjaLKsP#u+6lGnOst~SI3bh0aRDX>YyigVif1q?Tqx^MsMXq(ZHho}v@Lz?AR0nw|? z*yM&Fj~~qcuefWEkE*!-XEJwpGk5OhwOPm}*+2r}vAY2RB*+R9-UvwqLV)lR44@!r zc$GK!Km`F`&?*Rs_z3u*$RmkG@Cm3td|+#}RV(77RohyvZEY3lnYpu*n+w+dKA+#` z^ZO&&*}eD9nfcC{^O!kvE^CE-YYiDJ8(OhE>{lCzu(sH*0w`te;9}MuhOt5@XB{2q zE5>V&VZ83+c)cz+UiMb3{*FqzOxi=O&@%c!+Cx~Y@~=$s=3q5Pq-B9m)}ocuoS;US z6v&~e_JY+#y|J&EXh00??G<(d%km<7R-(1EYAaY--qc!g1OA$NWpA&%h6(_6d9nmT zJb{xXlW5tlddO(o%#9=Lgd{zn_SucpO-q4-(f!?ey^kbL60M-v-=nt2%0Z_vR z!W1?Lrm`X0M9f2l+Mk@0W?rq{%Bo7(1Bfx+*OBw&4*rW5d!uT1Z*)3VM`FOWl+VI!$h_MxoahY zwpvHwwNqdT5i>(?8PCur+YBXQyvn1cD4|D7hzy89Z}n^yWJrj7IQ=fA!rEs%rSsxzv=?kbF* z$5bx6M5embgjQ=JJycFROC$}z?>!&0jggTm=~~~Y{F<2?wZH2Gf-X`@ zEkOe@ddF713nEe3*oa*N66zeiKx2QTFOg>nHoGt?Kk_2akdh}!DS>FB@NlA`vZ>gG zi++q=%Pe!3c8Z9W+h#zj(*KE{1YjbTHzEL|;tW+k(J6P(!ON&ffc*?OyBkOT9>`)_ zp$)qiIp1?tTy^v4^0RJq%Z~dYI34!;S0_xRpH$o7iKp zl|2r-*gn|Do`6R5@{Y0t@H{&R$Iw4G$r|BJ)&%deC*dRZ6nxH(z}M_3e9N9Dls!k% z+4CgEj*%|xI4NN#NFVkh8O&ZHht;S|LSRGOeVS zDX~i-mnj;W^_Q4bzqBMaooclVl79u#SO@h-D8q5 z+I0}}4Dan+gxsMmBTFa@$sj2CdsWn*s}pGh9D^)ZBH8;m$fv>2K0rI@42rQ2(MI?P z`mm2te0>6w+3#UG`vVT@r%=Z}gJtY(EaeDWP2k z=@L9)BX3b@E3qUYOF}U4vo3|7*XCb=|h`J%PCrMj%?ZSB3 z^EdJ%GZSZguk!kH%cCuEvPJ&C5T|bur|%G_vnckzN2B5#l%grw*Ca5(OoC}9g{w>h z=9wN?VtU~^lfg}<32RLYHkf`bHs@(p!#*Q2_NKsXikTR#N{CG|Qu!E1#T*rZj=i?3 z6r6U@ey8Rhy0d*ETm?32H?;Hw9FItZ(`=w8A<*O^B}3C}Oo!>;dW(fQDX@Cla;xY+ z$Ss#paUdyuZZiNLGZQQ`2q|V3v@%0bVCF!PnG0RbFd~|Vh_-=hGan|I1yF0YgIQ)F z)R`S%vDpz;nw?>d8G*aZC_HXWJr5+2T zQaz#~>@5_bQkGQ6)!ss3K1t#tU2_X(((D61voCgFAOy`p(Apg0(29k0tRh>O6jeq~ zp)z_bI*yKaH6TAC4gCrf8LeXia+zo~X8%}!?sEr%av$5g42h2dZjMIcRgi0rfi~t? zM+5R{jWSj9=>(~keUMEjN>i25Ng9DEDrzjNB?7YJC^Rm1ovk%zA>G;7>A4PCS-P`X zy0cl@iJPo>IZZ9Eud$gk&t}fn30_v**&BIgyv=YT15k6CRC@-eMIFDD+YFp%GjMBZ z2Z;Q(q|Y`7D-OI=xV*iMPFco1+s;#TGEtDZ0Qkk&QJf3(3wWB zP<;BTLZ>W1`j+Eg6S+i8mZ))r^sAx!Nm*5840T`sxM8Pqh*Y7|Y=k@wWB`i#eU*pF zpqfY{8N3ffp1BezB?F!N`{s5q%pEwN?t@hGe#ka=LB9C_M9l}Wmk&WNbC33svmuw( z(&@bFX7L%&#hD^cs4ts-#LqrUpbMoATaX~q??T` z^7$qXv8Je1Nk;4FJjI_eY>4o-mc>NfWJpaT87lYrjyp(+fWkxY`)D)`y{Cdh@CnMY zVKVkB8Y>DJ4dl|eCrZQ}(9V1wwaE+6!#oaU=8G`cd>Og)B#bg&gBtuk6~E8G?{o0`Lh}@I>>G|X zkY#kf+FDztov>wk-F%r|H(#dK&C4LJV)S~z(4-Y~fk28bq={5qi}C7Y=re@8c9fmB{@fQqkI4F0BeHr5PbBDT zAm#DoqEK=ZoZ1TQgT_`!4|zk$XnOeMIdb_;tYY<)3pDlTUTBUVk(QMC6?W{eIMe=y zo%%b@wr?P8ehY=>chJQ=3&rL+=*Izuatb540oB|KQ#pfLZo)k7hlM;@bNID@-~pk+d?kShkRb(XhDJAU?`wB$`)keq~1i=$QIm0Z@z%k*i#;f z9we1WP0YZ`W|EYhV~i+4xTeRpZQHhO+qP}nwr$(CbV_y^xYFfJ0rvT=!rA`Y@WmxK1AMD$l3}V*kaSGYD?lKV726=Bz6bMs%`mt zsHcQ+FLz)}WO+1vRflJnbA#Mtc7fj>;~OX3W21{%SordCAy64yDg**nxBTA%WE+gY zMM-fQzYLay=v0|sqF{m~TjJzFmxOARQ$wH(qPqNsx3SKrgJ&gbi<>~8x>X-Sbrqvf zPt_Rl+!;u%*qIXQ%ewHu@`2M%{5?i_Wq+VdY%a%*@pP2}ZEOgF4^HgiPGQ(ufkq}k(}!s0 zIQbV(8dmB9b+xB#$lee1e6O`JUoK3X4=Da7KWWb6Z%bL6~_(huf0d%4HUhd*}< zddsUX0iiFl^oE3VBK>=OIA`P)%85~5H0&080>Y0tb6`CI(+4+mls)O~)2%6ISF-NV zJ<-*tStf%QbxRPSLg)T5AaZQ}oy4%CML4r3&`#uET#>VpK5o>E2X-%RY!KoZ#jfDZ zNOkcdZJ%^hGZsran_=W24GR|Aa{hs@b76UxJ*A7%%k{#`btp^Cjk(9Jp9}r<2bQa^ z_>=Fh@ka>FeR8y-(w|scNm67aQVuZqDs$0EKed!A^TQJA-f+9Yyxfp$mui{vXFQvN zm#C1xB)XynuaX#3=WHq5K*_K!+|zbj$ycN!})Yc+}4(&k;O`|CMSKv4qaqwD-v}s z(K)qy$1gVM%APlImUCRCNL#l02~eIxj2Y8$<}v{%_>Csh-X&Ld#<37bVA<`bdz z`R3d*eLfv?47~>rJ`{@h_7jR~U1L$_f(I;>QvEqLrn&6dttNIS7N=YM1qdSkFX%_%$ zv05{qkKdy=%o$hA#&KWB7V?*Wm_%n^?~+>(kdx2_t*b;N!@?ms z`3B^RAk`B{_eLpQyRI0N3&2xV*QPpoUkr`OodweP)Go-4 z7b-+7Ezu&Nt*J|~97S%HrQ=5vX~<^iF0fzyf#l7`zbL?)YKFIZy&lFsemd=Q;v;>E znKn4IH`MGw^-3#s@=}n{51;#Lc{ax{GWm&^au;71N#6j%(B5_!RD?+dZ(5Y!dAbGrmVa4$0ZaegUd@I6li@B>|+7lwuA~4 zt`pE26}W}dNrenl)c0RBo@n+OgjZRbS1H`+VjYyufpli5}1Ts7~WDun;{j7vi<~0 z21HCRjboZ^nfxNg$bV+GAoglv4S?tllY zqP9RI=gmadta0PckDjb}1#|7Oh;VN~9W%>bDkXyGXHU@}ynhxKk$;j!A2T#Q(8@-b z6^O3k8=KFSD^)coAeinhBU$l&nb`^ZQ8R5#gXYHq3sa#u)G-_MAZ0T z8lVh7_3=$mq-xBKy1)UG3kGDt*Y;_KYHw#E5S$q?>)}$L3mKt-Op$#VzQ$+JQ2mUL z888ClNn`dgL-XLM9M#8|xL!K_+2=^dJLY00B-spP%YJ(i<*1IYubEP#3|>KGbH;wP zY&_*Gf;~8{c$ypiwq%+up5o2If8A;$PIsx0(f>h1iN$T-@FL%go+ChdiRyI7=kUP4 zU1fN^gH6sCr9(6dBv%*Gt?SQGqIUuI{+VY>y=yHg*5OdMDs6Q*jgMQ2H*O?736odr+~}JWVy2eL?YpiSRW_rj3Wc|plV6)iJ)(Y@1=&&6O<@zt znp94+wuo_stxD^+%KuwhKfC0juIc?qw3^PfPz}}a(!Ed$R%2zD?i|UkszNFi^0vgT z<}dA;VYeVUo;bFG7UTp_Z22)(O-(F9kzsAWyvwoV z5%rdJ>Wo-_7Zy|10gjsh-D1Gj(pI+yo%Y&dCz$u2!zz&COU=%%Rm~Pr8ti7lJr$+I zs!k3r!4y^2q?4yR5Xe!K*CTsE3K6AG2B1mG?A4B-TGYbUZ^u1DCm(_i9wE_#t7vFy zGFBd+%-Txmub5NvZS4X;r)G^A+MWh#;$=>v?3z$cQ#9eGR*+5~4phx*g`VASO38I* zr5jJ=$Q#qjcE*}gmms}c+@EZ%pX_={J}nnX(Sh~e$Fi1OsD*i{$&is(hQHSe)RB=_ zh;MXCyb$b1qC68LD!^BkFJb)k!s3YK52lC6gUXV}M4iwtoO%!7hAxynL0flNxt6;T z*qyM;&Y8g|!LKR{J(VD}*y4hzL>YIY$)u7bm6T7Jymj7px0@wt1%JQP@HGmnjw1ik> z2>t!dthghxg-(3ZtvcJLqCX-7{LW z287%p2dqe_zDg@1o&H>%%Q_P`+;VcE^eI&oz2XC*>KtrbL95G7dX-kHUn%^ASL&PT zUH!fF1W&uJBr5cXtVz(r1)bm#<$eY+oW+uo*jA`ADuJTc6j?~IOips4f3g1(c=dTr z!!0@o92Kxh(Icag%wt^ki&LU8&s`ux_J!hxO1qRvLNO8!B;@DSQL6n5p%guFN&1Ji z^jCh0TB?m2^G8deO2tv&AQb3emPSHlqI?_FH8DPHXFo5$p7=|dLc{NTpex%>m_4_n zFk5Or2?(@_6$Mlb>MMQdUHd)PYTaTq-xAQN{Ad9{GOCq>(fH*97scv^>pi!O27;y% zSZ3!KM(t2}$;pRkDc}Im37swV20B5uF`{cQ zW+U2{HcYPTU=1IkYktAx3ukC8A4ivRvCadMw>+$&_#!G2OsI&Ow2E57-Px#ecs0MD z>wQ?YwM;OEWIQZHCcPGQR=%`|kRLjs+cvdWo$97>H9kR5^J5Zig-ctPdU%Z;p|wwR z)(K6j_6C=zGF_1LoMO&aJB4YOfu{;lm+;Q*5X`CGTI5qQ4$lLrTQ_X|wlbVr6`rXm zZni?=5n=Ph>GA6f`#qWP&pZz7^n#ggSfUNXCWA7&O-oWQCWUu5|(d9q7(SUZiXZ*7%r?+&#uV(>`^K|1x%zasyv8zafz*>)BI zI<3#emxuE~E5B_f9!~|*_|doChZp|lgERVLQ#_+{V66(XQXy|mtaKMG`w<`afaZ~T zi1Z9ZUAau+_#-~INl$~~jW+1uTRu-!IsU_}{3*Qn_@nwVR(1H}x@sxbRpnKQWX}0d zm4TaGsUz^pDP9v(Xbs=fh`{6(oU=qdPH$;?5nS52B|hEQM4~spPzeL03G)~0oV|j0 zbn7`Quw6%i1&sxJ1n4dtW-KgbAWYRjmQiF|@2AOjG;6hLNz?`E&7usNxL@2+u zNzR{{Xh{;sG^YaiUfARY8}t|}Mr(ze> z2TrbLO)TBL71^W689p&whhFwkP8hGdNaU^}1mS^fUoV=`G@mR7J~>Rs|A+q}Xo+%s z!qq(5me~1^onu4=Tew88wBLKZ7$Ot6=!%ZTaetX;+lC0VHhJwYw=)xw?S5y|s4?`( zbT%brz~Z4JddlbO2T0OAZtsccd! zIo79GfE>J~R8I35Z9?6Pj_U8?Y8~L%DcgW7VAHso?FXID6Qb+tDpE_q=VjqQ{~}@C zRE(QdW%rClea#G0@q%2hwaWr!KN#g|E-vE8WbyU@K4Qp3@r#~^=tTeKpyj5RxaD+~ z7`ZTRe=t+5E{mbVN~i0&8oAk00YGHlS6!+JaZ-sAWrBODBb

0MD8T9Vb8@fTs@1 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

LeTU53i-a)dqw2^zjn-wAB$4&eFee!)Z& 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 z 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

w^ZrHQWCUV};gId`si8t7Wi0$Pm-SULzV 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

{T;1@)ipyt|^h@r2a{8rx=g@OQd7Cw`g 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 Z($hqaf8lVPbewbx?4ds30+}7|{{d*}ahCu9 literal 0 HcmV?d00001 diff --git a/Tools/NewApplication/AppController.j b/Tools/NewApplication/AppController.j new file mode 100644 index 000000000..d8c791511 --- /dev/null +++ b/Tools/NewApplication/AppController.j @@ -0,0 +1,32 @@ + +import + + +@implementation AppController : CPObject +{ +} + +- (void)applicationDidFinishLaunching:(CPNotification)aNotification +{ + var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask], + contentView = [theWindow contentView]; + + var label = [[CPTextField alloc] initWithFrame:CGRectMakeZero()]; + + [label setStringValue:@"Hello World!"]; + [label setFont:[CPFont boldSystemFontOfSize:24.0]]; + + [label sizeToFit]; + + [label setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin | CPViewMinYMargin | CPViewMaxYMargin]; + [label setFrameOrigin:CGPointMake((CGRectGetWidth([contentView bounds]) - CGRectGetWidth([label frame])) / 2.0, (CGRectGetHeight([contentView bounds]) - CGRectGetHeight([label frame])) / 2.0)]; + + [contentView addSubview:label]; + + [theWindow orderFront:self]; + + // Uncomment the following line to turn on the standard menu bar. + //[CPMenu setMenuBarVisible:YES]; +} + +@end \ No newline at end of file diff --git a/Tools/NewApplication/Info.plist b/Tools/NewApplication/Info.plist new file mode 100644 index 000000000..92ab8b53d --- /dev/null +++ b/Tools/NewApplication/Info.plist @@ -0,0 +1,12 @@ + + + + + CPApplicationDelegateClass + AppController + CPBundleName + Hello World + CPPrincipalClass + CPApplication + + diff --git a/Tools/NewApplication/build.xml b/Tools/NewApplication/build.xml new file mode 100644 index 000000000..5a9377c2b --- /dev/null +++ b/Tools/NewApplication/build.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Tools/NewApplication/index.html b/Tools/NewApplication/index.html new file mode 100644 index 000000000..61892d8f7 --- /dev/null +++ b/Tools/NewApplication/index.html @@ -0,0 +1,36 @@ + + + + + + + Hello World + + + + + + + + +

+
+ +
+
+ + + \ No newline at end of file diff --git a/Tools/NewApplication/main.j b/Tools/NewApplication/main.j new file mode 100755 index 000000000..6357f21dc --- /dev/null +++ b/Tools/NewApplication/main.j @@ -0,0 +1,17 @@ +// +// main.j +// PhotoAlbum +// +// Created by Francisco Tolmasky on July 18th, 2008. +// Copyright 2005 - 2008, 280 North, Inc. All rights reserved. +// + +import +import + +import "AppController.j" + +function main(args, namedArgs) +{ + CPApplicationMain(args, namedArgs); +} diff --git a/Tools/NibApp/Info.plist b/Tools/NibApp/Info.plist new file mode 100644 index 000000000..ca4dfaaab --- /dev/null +++ b/Tools/NibApp/Info.plist @@ -0,0 +1,25 @@ + + + + + CPBundleDocumentTypes + + + CFBundleTypeExtensions + + MyDocument + + CPBundleTypeName + MyDocument + CPBundleTypeRole + Editor + CPDocumentClass + MyDocument + + + CPBundleName + MyApplication + CPPrincipalClass + CPApplication + + diff --git a/Tools/NibApp/MyDocument.j b/Tools/NibApp/MyDocument.j new file mode 100644 index 000000000..964c9ca48 --- /dev/null +++ b/Tools/NibApp/MyDocument.j @@ -0,0 +1,33 @@ +// +// Document.j +// Editor +// +// Created by Francisco Tolmasky on May 21, 2008. +// Copyright 2005 - 2008, 280 North, Inc. All rights reserved. +// + +import +import + + +@implementation MyDocument : CPDocument +{ + CPTextField _textField; +} + +- (void)windowControllerDidLoadNib:(CPWindowController)aWindowController +{ + [super windowControllerDidLoadNib:aWindowController]; + + var nib = [[CPNib alloc] initWithContentsOfURL:@"MainMenu.cib"]; + + var x = [nib instantiateNibWithExternalNameTable:nil]; + + [x setBackgroundColor:[CPColor blueColor]]; + + //alert([[x subviews] count]); + + [[[aWindowController window] contentView] addSubview:x]; +} + +@end diff --git a/Tools/NibApp/Resources/spinner.gif b/Tools/NibApp/Resources/spinner.gif new file mode 100644 index 0000000000000000000000000000000000000000..0d2567cd01553badc23cce79cdaa7bbd95178927 GIT binary patch literal 4481 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 literal 0 HcmV?d00001 diff --git a/Tools/NibApp/index.html b/Tools/NibApp/index.html new file mode 100644 index 000000000..774cb7e91 --- /dev/null +++ b/Tools/NibApp/index.html @@ -0,0 +1,34 @@ + + + + + + + Loading... + + + + + + + + +
+ +
+ + + \ No newline at end of file diff --git a/Tools/NibApp/main.j b/Tools/NibApp/main.j new file mode 100755 index 000000000..d92a85b6f --- /dev/null +++ b/Tools/NibApp/main.j @@ -0,0 +1,20 @@ +// +// main.j +// Editor +// +// Created by Francisco Tolmasky on May 21, 2008. +// Copyright 2005 - 2008, 280 North, Inc. All rights reserved. +// + +import +import + +import "MyDocument.j" + + +function main(args, namedArgs) +{ + CPApplicationMain(args, namedArgs); +} + +window.setTimeout(main, 0); \ No newline at end of file diff --git a/Tools/SubEthaEdit/Objective-J.mode/Contents/Info.plist b/Tools/SubEthaEdit/Objective-J.mode/Contents/Info.plist new file mode 100644 index 000000000..380234629 --- /dev/null +++ b/Tools/SubEthaEdit/Objective-J.mode/Contents/Info.plist @@ -0,0 +1,23 @@ + + + + + CFBundleGetInfoString + 1.0, Copyright Arcaeum, LLC + CFBundleIdentifier + SEEMode.Objective-J + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Objective-J + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.0 + NSHumanReadableCopyright + © 2006 Arcaeum, LLC +http://www.codingmonkeys.de + + diff --git a/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/ChangeLog.txt b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/ChangeLog.txt new file mode 100644 index 000000000..8c5e05b33 --- /dev/null +++ b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/ChangeLog.txt @@ -0,0 +1,25 @@ +Changes with Version 1.6 (SEE 2.5.1) + *) Uncomment script had wrong icon. + +Changes with Version 1.5 (SEE 2.5) + + *) Added Scripts: NSLog with Function Call, Insert Call To Super, Open Counterpart, Open File In Project, Open Xcode Project, Compile Using Xcode, Un/Comment Selected Lines, Lookup in AppKiDo. + *) AUTOCOMPLETE: added missing constants (AddressBook, NSError) + +Changes with Version 1.4 (SEE 2.3) + + *) SYMBOLS: Fixed SEE-490. + *) AUTOCOMPLETE: Added important Carbon keywords + +Changes with Version 1.3 + + *) SYNTAX: Added some missing Classes and Constants. HYR-587. + +Changes with Version 1.2 + + *) SYNTAX: Fixed preprocessor end regex. HYR-410. + +Changes with Version 1.1 + + *) SYNTAX: Changed Character to state to fix HYR-371. + *) Adding additional Cocoa classes, constants and functions diff --git a/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/English.lproj/InfoPlist.strings b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/English.lproj/InfoPlist.strings new file mode 100644 index 0000000000000000000000000000000000000000..baacc4cd015157cde288255e385d21697d5ed2c5 GIT binary patch literal 220 zcmX|*%?`m(6okKZpQ5o8KP7fzqX{9z!V{oWk+xAJJUl*K$j!Ou+?hEu_x+(ulaK`k zJ2qU%c(ErDd)Tj3A_ciUv>&`@z7EbE%35D>6FsYb)~cqSfhT6dn7isk-JYp+`){wE yuX^XCZjY=6E4G|e?c}mLzs+1`X<8y4(la%p#JgA$JvP7MR zl-_U;@q`z=^Dd(QH+=APi5VqLi-30_wp=A`u9Z)@*>N3c8__l+0@2&@zT^@Nb)5fc zYtL<%nmOCvm*gU4Cb>cw;0zODGDt3nD`tKXu5kW`zunuZMB@@pQpNaDF(kFnj0)o! zBh>l!>$)}UWA>IzXUswBl=Ecg?`PL%p)+};FX1a@-`IZKdsFER^DMX}x@$9oPpU0l z1kFA&J=m>fF!;J{#k%i^$j-sfg{|4;aaM6FFHS1j@7ZV36+vF}0k2%rr;94iM)4}$ zX;|^+G39Gtvjg@O&Op7q!0}_==z>*?$&gHkNbywiR9I2kGy=@&S*+{HAYACo=JfJK z?(Znih*&sCx!hME^GhaJx4xcLGOgPDugFr;sDY0Vw=V0>1LbXy2Y y(X(-OWpQ5o8e-%5i(S%5dg(pC@iqOMsW zVau8mB`AnShC?DYwN5G{%uua7P@6B{ccF~O=#JrqLrRMm4bb^qEF8ls5K<|0?VBx A#> z&dixJXJ-5TBLnG6R{~i|h z+9_d+)v5>UDej)!%9A`}F9QBtUa|7ThlLSKnE`c-6;W3*MHW6Mh&xfZKI{?h5D~s4 zc$c`C-DYrohK^5GqwM3bU89Q`p!O8ZbKp^x133c^lm7@iWFN_~9M)O>LW@voB3~8z z1iF5rRw`c9@l+&5#sayi4?Cgtq~004ZOs94HxU`BdpJd=0=d}P1!CvQo4L}RsBNvU z(1#3B>{*VLtBuv$6Ycj>`;n*V-3>6PA@jQN58y!VuCI@s5PqS`*^aO^So|i(J0NoU z-W{Eq{5YZi&DlNlr)n-|w`OCvOsthts`cWDV$b%W3>$viYS^jg*(Bqsn!-_qIs?B# z&7L`DmV+mku*I@L{)2$I=Ca9a|JW|z{SaCW{26}8NkG13B$pw%Z zt>=Je+-h?U21_7~6|UAN#az(GooN1v9#ytx1eLN8oRY5cbTA?I6&-? literal 0 HcmV?d00001 diff --git a/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/ModeSettings.xml b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/ModeSettings.xml new file mode 100644 index 000000000..ca848ad16 --- /dev/null +++ b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/ModeSettings.xml @@ -0,0 +1,8 @@ + + + + + j + J + + diff --git a/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/RegexSymbols.xml b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/RegexSymbols.xml new file mode 100644 index 000000000..38256d22f --- /dev/null +++ b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/RegexSymbols.xml @@ -0,0 +1,56 @@ + + + + + + { + } + + + + (^[ \t]*[-+][^(-;]*\([A-Za-z0-9 *_]*\)[A-Za-z0-9_ \t]+[^{;]*) + + (:) *\([^\)]*\) *[a-zA-Z0-9]* + \1 + ([\n\r\t]| +|\([^\)]*\)) + + + + + + (?<=[\n\r]|^)\s*function\s+([^{]*)(?=\s*\{) + + \([^\)]*\) + () + [\n\r] + + [ \t]+ + + + + + + (@implementation[^[:cntrl:]{]*) + + ([\n\r]| +) + + + + + + (@interface[^[:cntrl:]{]*|@protocol[^[:cntrl:]{]*) + + ([\n\r]| +) + + + + + + ^<<<<<<<[^=]*======[^>]*>>>>>>> + + .* + Versioning conflict! + + + + \ No newline at end of file diff --git a/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/10-InsertNSLogWithFunctionCall.scpt b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/10-InsertNSLogWithFunctionCall.scpt new file mode 100644 index 0000000000000000000000000000000000000000..8174f7b1e14081c56645aefcbfe946def08f88b0 GIT binary patch literal 1944 zcma)7NpllN6#ix;yv(RQl8r%_ZSWGn7+WT+PO1V0xNrjIV5rI=lxwgQtU{Jl)+mKf z;hv)4kb@5#a>+53pMX!PRLCI*%)Z&ij@cn>VavHgN$X_To2oOOzYM|UgD#hvh z>Fj|5+4+@mR-jT5m}z|nAy}{#L8vRhAur{HJh$Z~Y7>Z2M4@jmo%dhKfhjL2N}g+* zY#2L(Yn6y7>NP$KunMR$o`&QZs^HjM8WV^fObzYNd4tJ9e{Rt4EBgOXdS)n!?8X2^ zXuqQoL{W)Q}0x-&v-*wZy@yw=_aDc6o?5iOf?b4q5+G$ zvW3*3?{@d>%pGuZU%H*eY@eUbW!X1K>$`&=c zwS?{>sxY^tgjqms1hv}Mp;Qp)GI^q-UCB8Q^A!PeL?4)=$MVRK$MjGhX_on%aV$^- zuhRGsb%s3DX{;l;+V%TWuGi-my^LGRg%)LE0p~(2QUo*7<5(;Y6c)qW9i$@vAMpfP~Xzq+qt)U>z=ON z-MzglKcWyOxDjSH&;)#d<%+;)Ctd+d{@{nOmEUv7S6E)6&q0OUx8%O2_oOl=>M3T0 z+*4RlvL!+jSE5-Fm|swkPTeZBC<3}ThjJ5iXFt{jwN@rg05t@ zLR*O*fg`sqxjm!Ukh|LYmXgCPD7h7qTZk$&m-uTiPi|UrbJkF~r}>wb_;qzA93+fi zDzZhEjvmI9!*U$a$4{M};{NS^zqdV^_FKJtzJA_lzc+knT2A~%wr`J|sU11~35JQE z{B+;&&peAqzc%96<;2C$_YMDgdq;B61HJMx=|Uh_*NqX{mea4|tz)F&>32I;@#rnu z-+JMF#MMVKBS%kuGs_|zK&3m2&#d7+d=h+|6~IWt&10m-g8k7Sb%QdPCfWk$r|*e; zO#9c;{EjX8d?wxJ=_gm{*fsPTs^xXO5jnO3mruS2MeN6R_~?hnHHkF$t=#ANbEr3j zZOCB&)kyqXXxr;L+O&?gH+9s&XoL3AkO%rrE#hpK8w%~SZwhi1+JfTe**Q(cPupZ@d6;Zi@8o7*GxnvXlf4$e{rS~;en*#r+0C}#I?z(D#xk9TJ6$BY>*3b9viVq&RIm?9R!69vwwAQbeQO1xEIPxy@NobD literal 0 HcmV?d00001 diff --git a/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/20-InsertCallToSuper.scpt b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/20-InsertCallToSuper.scpt new file mode 100644 index 0000000000000000000000000000000000000000..392374083ad2206064f40f071d6fa9ad24cac4c7 GIT binary patch literal 4830 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 literal 0 HcmV?d00001 diff --git a/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/30-OpenCounterpart.scpt b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/30-OpenCounterpart.scpt new file mode 100644 index 0000000000000000000000000000000000000000..d17f9ddf703b6172aff6445981ffdc3bd78fd8d7 GIT binary patch literal 5788 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 Nj6ue)AAE58{{hF=E&>1m literal 0 HcmV?d00001 diff --git a/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/60-un_comment_lines.scpt b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/60-un_comment_lines.scpt new file mode 100644 index 0000000000000000000000000000000000000000..6021abf9346aa352f461a86478cf2e29005a2b2e GIT binary patch literal 6594 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 literal 0 HcmV?d00001 diff --git a/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/Lookup in AppKiDo.scpt b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/Lookup in AppKiDo.scpt new file mode 100644 index 0000000000000000000000000000000000000000..db81cff3c4fde1b136c657dd33897f82b54157dd GIT binary patch literal 2622 zcma)8S#MKE6#njYn#I=>I|*S4l)4T98badGur#cJ1VJgHQi9YM9&YTb#>KHC`v#G| zv@d@(zp35_N zYRPj{Mp2e^oNO$U=y9`->n2j4X8}{5Y4B7_FNX1ncg#YGLJ5p@9_EL?5PtaNUswoO zoMuE3+U)dortM5T+m+6^v0nEDr9DqkWH-7gLVKVBR8Runj1^tPP>28pK0zsh7N@Ex zEH|A_cG{UlES(xf))G-<^2GS)a43KfCZMz<$K2A>vo6t^&PfbX;$xJd+~PEo?j}-M z*G|Q0WL~x=wdYBB35o|i=?o+)0;pgV%v4@tIVJvs3G&F|G(8HHNYNnI+3I#Xsa}n) z%AxCtD%#~qVhT_hK&5uK&&hhm$s8*H64(L^1zUX43a$1ER#4UV~Qde zWw|f+47sma?rD}O995XA2=XieOq06`(_n7!G8VwQn63!S4DkZy;XQ;Eftm8~617okM%_~i}?{5>68U4=-FUVtLG?U&n{-tHt7!Z6aFe8??JZXpsyFzY0pn43s5 z)EQRPON4fhpfEib6F651*0e6aH-5XSAOE;!4!7Q*{f!64BF_CTxog|LZ%0^!A5an=!Si!L2MdSgTMX=~ zzP6pzGH<=@SAC}q-U!-);2%E`Swj1pXnr#*Jei2uUWA+1_q~E@dCjjyj+Z5jAllK3 zPPD;A7i`XPB)G2Ux`)3Y_4?3?G`dla=*vPIUe(c{bu_%LqXI?)w2y||)fG9FV+Lvz z!D!LmlpBWJ)GRkNOAW_N%u)m%i@q(h<+{S`T#;)01Jo)4vyJf&A63lT3zLH6wuvN9d963lV?Tu`{u*aD>_^vOZV9Y&vqyl568E;JTc~ z5YrV6Aj<2 z`?BeHHs;py%hw*Vu^!&+1v&F7F;Rvr85+|(Q--wxm$U&*91G=w!on9e4$6QbgPLW4 zEOG(N2%{Vfv9t>1JQm?2G-ENA7(`h1i%=lvq+ia;8B5N+?LG2KKRvLWEpD0_&2@^e z>BM$uZ!9@GuB2IVW=!8oXwvA$poMLxS`Ns5*~g0;mA$gZF9-6^i(mHVA0Ug{<9S*v**j*E{jz6_%TOkVF!g*n zN@@q{2J706Zrm{Rd(Ci7+wl#5d=Wqqqq7*sZ)huH_bg@qbl5wS{G|~q#S*=>x(uuF zCEKdwZG`j9HOW>R|H88&CTCfB6r%{I-z* literal 0 HcmV?d00001 diff --git a/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/shell/insert_super.py b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/shell/insert_super.py new file mode 100755 index 000000000..c6917e613 --- /dev/null +++ b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/Scripts/shell/insert_super.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python + +"""Inserts a [super method] call suitable for the current method. + Inserted as a snippet with the incoming arguments used as defaults. + + The default behavior is to add brackets if there is no "[" to the left + of the caret (ignoring the tab trigger). This can be changed by modifying + the useBrackets line below. + + The command uses heuristics to find which method implementation is + being edited. It should be reasonably tolerant to various coding styles, + including different bracket and indentation styles. +""" + +import sys, os, re, itertools + +protoRe = re.compile(r"^\s*(\+|-)\s*\([^)]+\)((\n|[^{])*)[^;]\{", re.M) + +nlines = int(os.environ["LINE_NUMBER"])-1 +interestingLines = [l for (count, l) in itertools.takewhile(lambda (n, l): n <= nlines, enumerate(sys.stdin))] +invokationLine = interestingLines[-1] + +needsBracket = True +postfix = ";" + +protos = protoRe.findall(''.join(interestingLines)) + +if len(protos) == 0: + sys.exit(1) + +lastProtoSelWithTypes = re.sub(r'\s+', ' ', protos[-1][1]) + +counter = itertools.count(1) +def replFunc(match): + return '%s' % ( match.groups()[0]) + +methodCall = re.sub(r'\([^)]+\)\s*(([A-Za-z0-9_][A-Za-z0-9_]*))', replFunc, lastProtoSelWithTypes) + +brackets = needsBracket and ('[', ']') or ('', '') +outString = '%ssuper %s%s%s' % (brackets[0], methodCall.strip(), brackets[1], postfix) + +sys.stdout.write(outString) diff --git a/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/SyntaxDefinition.xml b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/SyntaxDefinition.xml new file mode 100644 index 000000000..e36d0813a --- /dev/null +++ b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/SyntaxDefinition.xml @@ -0,0 +1,2833 @@ + + + + + + Objective-C + + + + + + + + + + + + (?<=[^\w\d]|^)(((([0-9]+\.[0-9]*)|(\.[0-9]+))([eE][+\-]?[0-9]+)?[fFlL]?)|((([1-9][0-9]*)|0[0-7]*|(0[xX][0-9a-fA-F]+))(([uU][lL]?)|([lL][uU]?))?))(?=[^\w\d]|$) + + + + ([A-Za-z0-9_]+ *)\( + + + + class + const + enum + export + extends + + abstract + boolean + byte + + debugger + + final + + goto + implements + + interface + + native + package + private + protected + public + + static + synchronized + throws + transient + volatile + + + + __proto__ + break + case + catch + continue + default + delete + do + else + false + finally + for + function + if + in + instanceof + new + null + prototype + return + switch + this + throw + true + try + typeof + var + while + with + + + + id + NULL + nil + Nil + void + self + super + YES + NO + IBAction + IBOutlet + int + long + float + double + char + unichar + unsigned + signed + BOOL + SEL + Class + short + + + + @class + @end + @implementation + @interface + @private + @protected + @protocol + @public + @defs + @encode + @selector + + + + [^:]\([^)]*\)[ ]*([A-Za-z0-9_]+)[ ]*[{;] + \)[ ]*([A-Za-z0-9_]+:) + ([A-Za-z0-9_]+:) + ([A-Za-z0-9_]+)] + [\-\+][ ]*\([A-Za-z0-9_]+\)[ ]*([A-Za-z0-9_]+) + + + + CPAccessibility + CPActionCell + CPAffineTransform + CPAppleEventDescriptor + CPAppleEventManager + CPAppleScript + CPApplication + CPArchiver + CPArray + CPAssertionHandler + CPAttributedString + CPAutoreleasePool + CPBezierPath + CPBitmapImageRep + CPBox + CPBrowser + CPBrowserCell + CPBundle + CPButton + CPButtonCell + CPCachedImageRep + CPCalendarDate + CPCell + CPChangeSpelling + CPCharacterSet + CPClassDescription + CPClipView + CPCloneCommand + CPCloseCommand + CPCoder + CPCoding + CPColor + CPColorList + CPColorPanel + CPColorPicker + CPColorPickingCustom + CPColorPickingDefault + CPColorWell + CPComboBox + CPComboBoxCell + CPComboBoxCellDataSource + CPComboBoxDataSource + CPComparisonMethods + CPConditionLock + CPConnection + CPControl + CPCopying + CPCountCommand + CPCountedSet + CPCreateCommand + CPCursor + CPCustomImageRep + CPData + CPDate + CPDateFormatter + CPDecimalNumber + CPDecimalNumberBehaviors + CPDecimalNumberHandler + CPDeleteCommand + CPDeserializer + CPDictionary + CPDirectoryEnumerator + CPDistantObject + CPDistantObjectRequest + CPDistributedLock + CPDistributedNotificationCenter + CPDocument + CPDocumentController + CPDraggingDestination + CPDraggingInfo + CPDraggingSource + CPDrawer + CPEPSImageRep + CPEnumerator + CPEvent + CPException + CPExistsCommand + CPFileHandle + CPFileManager + CPFileWrapper + CPFont + CPFontManager + CPFontPanel + CPForm + CPFormCell + CPFormatter + CPGetCommand + CPGlyphInfo + CPGraphicsContext + CPHelpManager + CPHost + CPIgnoreMisspelledWords + CPImageCell + CPImageRep + CPImageView + CPIndexSpecifier + CPImage + CPInputManager + CPInputServerMouseTracker + CPInputServiceProvider + CPInputServer + CPInvocation + CPKeyValueCoding + CPKeyedArchiver + CPKeyedUnarchiver + CPLayoutManager + CPLock + CPLocking + CPLogicalTest + CPMachBootstrapServer + CPMachPort + CPMatrix + CPMenu + CPMenuItem + CPMenuItemCell + CPMenuValidation + CPMenuView + CPMessagePort + CPMessagePortNameServer + CPMethodSignature + CPMiddleSpecifier + CPMoveCommand + CPMovie + CPMovieView + CPMutableArray + CPMutableAttributedString + CPMutableCharacterSet + CPMutableCopying + CPMutableData + CPMutableDictionary + CPMutableParagraphStyle + CPMutableSet + CPMutableString + CPNameSpecifier + CPNetService + CPNetServiceBrowser + CPNibAwaking + CPNibConnector + CPNibControlConnector + CPNibOutletConnector + CPNotificationCenter + CPNotificationQueue + CPNotification + CPNull + CPNumber + CPNumberFormatter + CPObjCTypeSerializationCallBack + CPObject + CPOpenGLContext + CPOpenGLPixelFormat + CPOpenGLView + CPOpenPanel + CPOutlineView + CPOutlineViewDataSource + CPPDFImageRep + CPPICTImageRep + CPPageLayout + CPPanel + CPParagraphStyle + CPPasteboard + CPPipe + CPPopUpButton + CPPopUpButtonCell + CPPort + CPPortCoder + CPPortMessage + CPPortNameServer + CPPositionalSpecifier + CPPrintInfo + CPPrintOperation + CPPrintPanel + CPPrinter + CPProcessInfo + CPProgressIndicator + CPPropertyListSerialization + CPPropertySpecifier + CPProtocolChecker + CPProxy + CPQuickDrawView + CPQuitCommand + CPRandomSpecifier + CPRangeSpecifier + CPRecursiveLock + CPRelativeSpecifier + CPResponder + CPRulerMarker + CPRulerView + CPRunLoop + CPSavePanel + CPScanner + CPScreen + CPScriptClassDescription + CPScriptCoercionHandler + CPScriptCommand + CPScriptCommandDescription + CPScriptExecutionContext + CPScriptKeyValueCoding + CPScriptObjectSpecifier + CPScriptObjectSpecifiers + CPScriptSuiteRegistry + CPScriptWhoseTest + CPScriptingComparisonMethods + CPScrollView + CPScroller + CPSecureTextField + CPSecureTextFieldCell + CPSerializer + CPServicesRequests + CPSet + CPSetCommand + CPSimpleHorizontalTypesetter + CPSlider + CPSliderCell + CPSocketPort + CPSocketPortNameServer + CPSound + CPSpecifierTest + CPSpellChecker + CPSpellServer + CPSplitView + CPStatusBar + CPStatusItem + CPStepper + CPStepperCell + CPString + CPTabView + CPTabViewItem + CPTableColumn + CPTableDataSource + CPTableHeaderCell + CPTableHeaderView + CPTableView + CPTask + CPText + CPTextAttachment + CPTextAttachmentCell + CPTextContainer + CPTextField + CPTextFieldCell + CPTextInput + CPTextStorage + CPTextStorageScripting + CPTextTab + CPTextView + CPThread + CPTimeZone + CPTimer + CPToolTipOwner + CPToolbar + CPToolbarItem + CPToolbarItemValidation + CPTypesetter + CPURL + CPURLHandle + CPURLHandleClient + CPUnarchiver + CPUndoManager + CPUniqueIDSpecifier + CPUserDefaults + CPUserInterfaceValidations + CPValidatedUserInterfaceItem + CPValue + CPView + CPWhoseSpecifier + CPWindow + CPWindowController + CPWindowScripting + CPWorkspace + + CPError + CPCachedURLResponse + CPHTTPCookie + CPHTTPCookieStorage + CPHTTPURLResponse + CPIndexSet + CPInputStream + CPMutableIndexSet + CPMutableURLRequest + CPOutputStream + CPSortDescriptor + CPStream + CPURLAuthenticationChallenge + CPURLCache + CPURLConnection + CPURLCredential + CPURLCredentialStorage + CPURLDownload + CPURLProtectionSpace + CPURLProtocol + CPURLRequest + CPURLResponse + CPValueTransformer + CPXMLParser + + ABActionDelegate + WebFrameLoadDelegate + WebPolicyDelegate + WebResourceLoadDelegate + ABImageClient + CPEditor + CPEditorRegistration + CPFontPanelValidation + CPGlyphStorage + CPKeyValueBindingCreation + CPPlaceholders + CPObjCTypeSerialization + CPJavaClassesForBundle + CPJavaClassesFromPath + CPJavaSetupVirtualMachine + CPCopyHashTableWithZone + CPCreateHashTable + CPCreateHashTableWithZone + CPEnumerateHashTable + CPFreeHashTable + CPHashInsert + CPHashInsertIfAbsent + CPHashInsertKnownAbsent + CPHashRemove + CPNextHashEnumeratorItem + CPResetHashTable + CPAllMapTableKeys + CPAllMapTableValues + CPCopyMapTableWithZone + CPCreateMapTable + CPCreateMapTableWithZone + CPEnumerateMapTable + CPFreeMapTable + CPMapGet + CPMapInsert + CPMapInsertIfAbsent + CPMapInsertKnownAbsent + CPMapMember + CPMapRemove + CPNextMapEnumeratorPair + CPResetMapTable + CPAllocateObject + CPCopyObject + CPDeallocateObject + CPDecrementExtraRefCountWasZero + CPExtraRefCount + CPIncrementExtraRefCount + CPDivideRect + CPGetUncaughtExceptionHandler + CPSetUncaughtExceptionHandler + CPAllocateMemoryPages + CPCopyMemoryPages + CPCreateZone + CPDeallocateMemoryPages + CPDefaultMallocZone + CPLogPageSize + CPPageSize + CPRecycleZone + CPRoundDownToMultipleOfPageSize + CPRoundUpToMultipleOfPageSize + CPSetZoneName + CPZoneCalloc + CPZoneFree + CPZoneMalloc + CPZoneName + CPZoneRealloc + CPDecNumberBehaviors + CPURLAuthenticationChallengeSender + CPURLClient + CPURLProtocolClient + WebDocumentRepresentation + WebDocumentSearching + WebOpenPanelResultListener + WebPolicyDecisionListener + WebUIDelegate + WebDocumentText + WebDocumentView + + CPATSTypesetter + CPAlert + CPAnimation + CPArrayController + CPAttributeDescription + CPCIImageRep + CPColorSpace + CPController + CPDatePicker + CPDatePickerCell + CPEntityDescription + CPFetchRequest + CPFetchedPropertyDescription + CPFontDescriptor + CPGlyphGenerator + CPLevelIndicator + CPLevelIndicatorCell + CPManagedObject + CPManagedObjectContext + CPManagedObjectID + CPManagedObjectModel + CPNib + CPObjectController + CPOpenGLPixelBuffer + CPPersistentDocument + CPPersistentStoreCoordinator + CPPropertyDescription + CPRelationshipDescription + CPSearchField + CPSearchFieldCell + CPSegmentedCell + CPSegmentedControl + CPShadow + CPSpeechRecognizer + CPSpeechSynthesizer + CPTextBlock + CPTextList + CPTextTable + CPTextTableBlock + CPTokenField + CPTokenFieldCell + CPTreeController + CPUserDefaultsController + CPViewAnimation + + CPCalendar + CPCoercionHandler + CPComparisonPredicate + CPCompoundPredicate + CPConstantString + CPDateComponents + CPExceptionHandler + CPExpression + CPIndexPath + CPJavaConfiguration + CPJavaVirtualMachine + CPLocale + CPMailDelivery + CPMetadataItem + CPMetadataQuery + CPMetadataQueryAttributeValueTuple + CPMetadataQueryResultGroup + CPObjectSpecifier + CPPredicate + CPPreferencePane + CPSimpleCString + CPWhoseTest + CPXMLDTD + CPXMLDTDNode + CPXMLDocument + CPXMLElement + CPXMLNode + + + + CPAffineTransformStruct + CPApplicationTerminateReply + CPBackingStoreType + CPBezelStyle + CPBezierPathElement + CPBitmapImageFileType + CPBorderType + CPBoxType + CPButtonType + CPCellAttribute + CPCellImagePosition + CPCellState + CPCellType + CPCharacterCollection + CPControlSize + CPControlTint + CPDocumentChangeType + CPDragOperation + CPDrawerState + CPEventType + CPFocusRingPlacement + CPFontAction + CPFontTraitMask + CPGlyph + CPGlyphInscription + CPGlyphLayoutMode + CPGlyphRelation + CPGradientType + CPImageAlignment + CPImageCacheMode + CPImageFrameStyle + CPImageInterpolation + CPImageLoadStatus + CPImageRepLoadStatus + CPImageScaling + CPInterfaceStyle + CPLayoutDirection + CPLayoutStatus + CPLineBreakMode + CPLineCapStyle + CPLineJoinStyle + CPLineMovementDirection + CPLineSweepDirection + CPMatrixMode + CPModalSession + CPMultibyteGlyphPacking + CPOpenGLContextAuxiliary + CPOpenGLContextParameter + CPOpenGLPixelFormatAttribute + CPOpenGLPixelFormatAuxiliary + CPPopUpArrowPosition + CPPrinterTableStatus + CPPrintingOrientation + CPPrintingPageOrder + CPPrintingPaginationMode + CPProgressIndicatorStyle + CPProgressIndicatorThickness + CPQTMovieLoopMode + CPRequestUserAttentionType + CPRulerOrientation + CPSaveOperationType + CPScreenAuxiliaryOpaque + CPScrollArrowPosition + CPScrollerArrow + CPScrollerPart + CPSelectionAffinity + CPSelectionDirection + CPSelectionGranularity + CPTabState + CPTabViewItemAuxiliaryOpaque + CPTabViewType + CPTableViewDropOperation + CPTextAlignment + CPTextFieldBezelStyle + CPTextTabType + CPTickMarkPosition + CPTIFFCompression + CPTitlePosition + CPToolbarDisplayMode + CPToolbarSizeMode + CPToolTipTag + CPTrackingRectTag + CPTypesetterBehavior + CPUsableScrollerParts + CPWindingRule + CPWindowAuxiliaryOpaque + CPWindowButton + CPWindowOrderingMode + CPWritingDirection + CPCalculationError + CPComparisonResult + CPHashEnumerator + CPHashTable + CPInsertionPosition + CPMapEnumerator + CPMapTable + CPNetServicesError + CPNotificationCoalescing + CPNotificationSuspensionBehavior + CPObjCValue + CPPoint + CPZeroPoint + CPPointArray + CPPointPointer + CPPostingStyle + CPPropertyListFormat + CPPropertyListMutabilityOptions + CPRange + CPRangePointer + CPRect + CPRectEdge + CPZeroRect + CPRectArray + CPRectPointer + CPRelativePosition + CPDecimal + CPDecimalMaxSize + CPRoundingMode + CPSaveOptions + CPSearchPathDomainMask + CPSize + CPZeroSize + CPSizeArray + CPSizePointer + CPSwappedDouble + CPSwappedFloat + CPTestComparisonOperation + CPTimeInterval + CPUncaughtExceptionHandler + CPURLHandleStatus + CPWhoseSubelementIdentifier + CPZone + CPNotFound + CPOpenStepUnicodeReservedBase + CPStringEncoding + CPCompositingOperation + + + + CPDecimalMaxSize + CPDecimalNoScale + CPMaximumStringLength + CPNotAnIntMapKey + CPNotAPointerMapKey + CPCocoaErrorDomain + CPURLErrorDomain + CFStreamErrorDomain + CPFilePathErrorKey + CPErrorFailingURLStringKey + CPPOSIXErrorDomain + CPOSStatusErrorDomain + CPMachErrorDomain + CPUnderlyingErrorKey + CPLocalizedDescriptionKey + CPLocalizedFailureReasonErrorKey + CPLocalizedRecoverySuggestionErrorKey + CPLocalizedRecoveryOptionsErrorKey + CPRecoveryAttempterErrorKey + CPStringEncodingErrorKey + CPURLErrorKey + CPFilePathErrorKey + CPURLCredentialStorageChangedNotification + CPUserDefaultsDidChangeNotification + CPWillBecomeMultiThreadedNotification + CPDidBecomeSingleThreadedNotification + CPThreadWillExitNotification + CPUndoManagerCheckpointNotification + CPUndoManagerWillUndoChangeNotification + CPUndoManagerWillRedoChangeNotification + CPUndoManagerDidUndoChangeNotification + CPUndoManagerDidRedoChangeNotification + CPUndoManagerDidOpenUndoGroupNotification + CPUndoManagerWillCloseUndoGroupNotification + CPPortDidBecomeInvalidNotification + CPTaskDidTerminateNotification + CPJavaWillSetupVirtualMachineNotification + CPJavaDidSetupVirtualMachineNotification + CPJavaWillCreateVirtualMachineNotification + CPJavaDidCreateVirtualMachineNotification + CPAppleEventManagerWillProcessFirstEventNotification + CPBundleDidLoadNotification + CPClassDescriptionNeededForClassNotification + CPConnectionDidDieNotification + CPConnectionDidInitializeNotification + CPFileHandleReadCompletionNotification + CPFileHandleReadToEndOfFileCompletionNotification + CPFileHandleConnectionAcceptedNotification + CPFileHandleDataAvailableNotification + CPHTTPCookieManagerAcceptPolicyChangedNotification + CPHTTPCookieManagerCookiesChangedNotification + BPF_MODE_DISABLED + BPF_MODE_INPUT + BPF_MODE_INPUT_OUTPUT + BPF_MODE_OUTPUT + DRFileForkData + DRFileForkResource + DRFilesystemInclusionMaskHFSPlus + DRFilesystemInclusionMaskISO9660 + DRFilesystemInclusionMaskJoliet + DRFilesystemInclusionMaskUDF + DRSetupPanelDeviceSelectionChangedNotification + DRSetupPanelSelectedDeviceKey + FFCAP_ET_CONSTANTFORCE + FFCAP_ET_CUSTOMFORCE + FFCAP_ET_DAMPER + FFCAP_ET_FRICTION + FFCAP_ET_INERTIA + FFCAP_ET_RAMPFORCE + FFCAP_ET_SAWTOOTHDOWN + FFCAP_ET_SAWTOOTHUP + FFCAP_ET_SINE + FFCAP_ET_SPRING + FFCAP_ET_SQUARE + FFCAP_ET_TRIANGLE + FFEFF_CARTESIAN + FFEFF_POLAR + FFEFF_SPHERICAL + IFNET_CSUM_FRAGMENT + IFNET_CSUM_IP + IFNET_CSUM_TCP + IFNET_CSUM_UDP + IFNET_FAMILY_ANY + IFNET_FAMILY_BOND + IFNET_FAMILY_DISC + IFNET_FAMILY_ETHERNET + IFNET_FAMILY_FAITH + IFNET_FAMILY_FIREWIRE + IFNET_FAMILY_GIF + IFNET_FAMILY_LOOPBACK + IFNET_FAMILY_MDECAP + IFNET_FAMILY_PPP + IFNET_FAMILY_PVC + IFNET_FAMILY_SLIP + IFNET_FAMILY_STF + IFNET_FAMILY_TUN + IFNET_FAMILY_VLAN + IFNET_IP_FRAGMENT + IFNET_VLAN_MTU + IFNET_VLAN_TAGGING + IMCapabilityAudioConference + IMCapabilityDirectIM + IMCapabilityFileSharing + IMCapabilityFileTransfer + IMCapabilityText + IMCapabilityVideoConference + IMPersonAVBusyKey + IMPersonCapabilitiesKey + IMPersonEmailKey + IMPersonFirstNameKey + IMPersonIdleSinceKey + IMPersonInfoChangedNotification + IMPersonLastNameKey + IMPersonPictureDataKey + IMPersonScreenNameKey + IMPersonServiceNameKey + IMPersonStatus + IMPersonStatusAvailable + IMPersonStatusAway + IMPersonStatusChangedNotification + IMPersonStatusIdle + IMPersonStatusKey + IMPersonStatusMessageKey + IMPersonStatusOffline + IMPersonStatusUnknown + IMServiceStatus + IMServiceStatusChangedNotification + IMServiceStatusDisconnected + IMServiceStatusLoggedIn + IMServiceStatusLoggedOut + IMServiceStatusLoggingIn + IMServiceStatusLoggingOut + IMStatusImagesChangedAppearanceNotification + ISyncChangePropertyActionKey + ISyncChangePropertyClear + ISyncChangePropertyNameKey + ISyncChangePropertySet + ISyncChangePropertyValueKey + ISyncChangeType + ISyncChangeTypeAdd + ISyncChangeTypeDelete + ISyncChangeTypeModify + ISyncClientTypeApplication + ISyncClientTypeDevice + ISyncClientTypePeer + ISyncClientTypeServer + ISyncInvalidEntityException + ISyncInvalidRecordException + ISyncInvalidRecordIdentifiersKey + ISyncInvalidRecordReasonsKey + ISyncInvalidRecordsKey + ISyncRecordEntityNameKey + ISyncServerUnavailableException + ISyncSessionCancelledException + ISyncSessionUnavailableException + ISyncStatus + ISyncStatusCancelled + ISyncStatusErrors + ISyncStatusFailed + ISyncStatusNever + ISyncStatusRunning + ISyncStatusSuccess + ISyncStatusWarnings + ISyncUnsupportedEntityException + InstallerDirectionBackward + InstallerDirectionForward + InstallerDirectionUndefined + MBUF_BCAST + MBUF_CSUM_DID_DATA + MBUF_CSUM_DID_IP + MBUF_CSUM_IP_GOOD + MBUF_CSUM_PSEUDO_HDR + MBUF_CSUM_REQ_IP + MBUF_CSUM_REQ_TCP + MBUF_CSUM_REQ_UDP + MBUF_DONTWAIT + MBUF_EOR + MBUF_EXT + MBUF_FIRSTFRAG + MBUF_FRAG + MBUF_LASTFRAG + MBUF_MCAST + MBUF_MT_ATABLE + MBUF_MT_CONTROL + MBUF_MT_DATA + MBUF_MT_FREE + MBUF_MT_FTABLE + MBUF_MT_HEADER + MBUF_MT_HTABLE + MBUF_MT_IFADDR + MBUF_MT_OOBDATA + MBUF_MT_PCB + MBUF_MT_RIGHTS + MBUF_MT_RTABLE + MBUF_MT_SOCKET + MBUF_MT_SONAME + MBUF_PKTHDR + MBUF_PROMISC + MBUF_WAITOK + CPAFMAscender + CPAFMCapHeight + CPAFMCharacterSet + CPAFMDescender + CPAFMEncodingScheme + CPAFMFamilyName + CPAFMFontName + CPAFMFormatVersion + CPAFMFullName + CPAFMItalicAngle + CPAFMMappingScheme + CPAFMNotice + CPAFMUnderlinePosition + CPAFMUnderlineThickness + CPAFMVersion + CPAFMWeight + CPAFMXHeight + CPASCIIStringEncoding + CPAWTEventType + CPAbortModalException + CPAbortPrintingException + CPAboveBottom + CPAboveTop + CPAccessibilityApplicationActivatedNotification + CPAccessibilityApplicationDeactivatedNotification + CPAccessibilityApplicationHiddenNotification + CPAccessibilityApplicationRole + CPAccessibilityApplicationShownNotification + CPAccessibilityAttributedStringForRangeParameterizedAttribute + CPAccessibilityBoundsForRangeParameterizedAttribute + CPAccessibilityBrowserRole + CPAccessibilityBusyIndicatorRole + CPAccessibilityButtonRole + CPAccessibilityCancelAction + CPAccessibilityCancelButtonAttribute + CPAccessibilityCheckBoxRole + CPAccessibilityChildrenAttribute + CPAccessibilityClearButtonAttribute + CPAccessibilityCloseButtonAttribute + CPAccessibilityCloseButtonSubrole + CPAccessibilityColorWellRole + CPAccessibilityColumnRole + CPAccessibilityColumnTitlesAttribute + CPAccessibilityColumnsAttribute + CPAccessibilityComboBoxRole + CPAccessibilityConfirmAction + CPAccessibilityContentsAttribute + CPAccessibilityDecrementAction + CPAccessibilityDecrementArrowSubrole + CPAccessibilityDecrementButtonAttribute + CPAccessibilityDecrementPageSubrole + CPAccessibilityDefaultButtonAttribute + CPAccessibilityDialogSubrole + CPAccessibilityDisclosedByRowAttribute + CPAccessibilityDisclosedRowsAttribute + CPAccessibilityDisclosingAttribute + CPAccessibilityDocumentAttribute + CPAccessibilityDrawerCreatedNotification + CPAccessibilityDrawerRole + CPAccessibilityEditedAttribute + CPAccessibilityEnabledAttribute + CPAccessibilityErrorCodeExceptionInfo + CPAccessibilityException + CPAccessibilityExpandedAttribute + CPAccessibilityFilenameAttribute + CPAccessibilityFloatingWindowSubrole + CPAccessibilityFocusedAttribute + CPAccessibilityFocusedUIElementAttribute + CPAccessibilityFocusedUIElementChangedNotification + CPAccessibilityFocusedWindowAttribute + CPAccessibilityFocusedWindowChangedNotification + CPAccessibilityFrontmostAttribute + CPAccessibilityGroupRole + CPAccessibilityGrowAreaAttribute + CPAccessibilityGrowAreaRole + CPAccessibilityHeaderAttribute + CPAccessibilityHelpAttribute + CPAccessibilityHiddenAttribute + CPAccessibilityHorizontalOrientationValue + CPAccessibilityHorizontalScrollBarAttribute + CPAccessibilityImageRole + CPAccessibilityIncrementAction + CPAccessibilityIncrementArrowSubrole + CPAccessibilityIncrementButtonAttribute + CPAccessibilityIncrementPageSubrole + CPAccessibilityIncrementorRole + CPAccessibilityLineForIndexParameterizedAttribute + CPAccessibilityLinkRole + CPAccessibilityListRole + CPAccessibilityMainAttribute + CPAccessibilityMainWindowAttribute + CPAccessibilityMainWindowChangedNotification + CPAccessibilityMatteContentUIElementAttribute + CPAccessibilityMatteRole + CPAccessibilityMaxValueAttribute + CPAccessibilityMenuBarAttribute + CPAccessibilityMenuBarRole + CPAccessibilityMenuButtonRole + CPAccessibilityMenuItemRole + CPAccessibilityMenuRole + CPAccessibilityMinValueAttribute + CPAccessibilityMinimizeButtonAttribute + CPAccessibilityMinimizeButtonSubrole + CPAccessibilityMinimizedAttribute + CPAccessibilityModalAttribute + CPAccessibilityNextContentsAttribute + CPAccessibilityNumberOfCharactersAttribute + CPAccessibilityOrientationAttribute + CPAccessibilityOutlineRole + CPAccessibilityOutlineRowSubrole + CPAccessibilityOverflowButtonAttribute + CPAccessibilityParentAttribute + CPAccessibilityPickAction + CPAccessibilityPopUpButtonRole + CPAccessibilityPositionAttribute + CPAccessibilityPressAction + CPAccessibilityPreviousContentsAttribute + CPAccessibilityProgressIndicatorRole + CPAccessibilityProxyAttribute + CPAccessibilityRTFForRangeParameterizedAttribute + CPAccessibilityRadioButtonRole + CPAccessibilityRadioGroupRole + CPAccessibilityRaiseAction + CPAccessibilityRangeForIndexParameterizedAttribute + CPAccessibilityRangeForLineParameterizedAttribute + CPAccessibilityRangeForPositionParameterizedAttribute + CPAccessibilityRoleAttribute + CPAccessibilityRoleDescriptionAttribute + CPAccessibilityRowRole + CPAccessibilityRowsAttribute + CPAccessibilityRulerRole + CPAccessibilityScrollAreaRole + CPAccessibilityScrollBarRole + CPAccessibilitySearchButtonAttribute + CPAccessibilitySearchFieldSubrole + CPAccessibilitySearchMenuAttribute + CPAccessibilitySecureTextFieldSubrole + CPAccessibilitySelectedAttribute + CPAccessibilitySelectedChildrenAttribute + CPAccessibilitySelectedColumnsAttribute + CPAccessibilitySelectedRowsAttribute + CPAccessibilitySelectedTextAttribute + CPAccessibilitySelectedTextRangeAttribute + CPAccessibilitySheetCreatedNotification + CPAccessibilitySheetRole + CPAccessibilityShownMenuAttribute + CPAccessibilitySizeAttribute + CPAccessibilitySliderRole + CPAccessibilitySortDirectionAttribute + CPAccessibilitySplitGroupRole + CPAccessibilitySplitterRole + CPAccessibilitySplittersAttribute + CPAccessibilityStandardWindowSubrole + CPAccessibilityStaticTextRole + CPAccessibilityStringForRangeParameterizedAttribute + CPAccessibilityStyleRangeForIndexParameterizedAttribute + CPAccessibilitySubroleAttribute + CPAccessibilitySystemDialogSubrole + CPAccessibilitySystemFloatingWindowSubrole + CPAccessibilitySystemWideRole + CPAccessibilityTabGroupRole + CPAccessibilityTableRole + CPAccessibilityTableRowSubrole + CPAccessibilityTabsAttribute + CPAccessibilityTextAreaRole + CPAccessibilityTextFieldRole + CPAccessibilityTitleAttribute + CPAccessibilityTitleUIElementAttribute + CPAccessibilityToolbarButtonAttribute + CPAccessibilityToolbarButtonSubrole + CPAccessibilityToolbarRole + CPAccessibilityTopLevelUIElementAttribute + CPAccessibilityUIElementDestroyedNotification + CPAccessibilityUnknownRole + CPAccessibilityUnknownSubrole + CPAccessibilityValueAttribute + CPAccessibilityValueChangedNotification + CPAccessibilityValueIndicatorRole + CPAccessibilityVerticalOrientationValue + CPAccessibilityVerticalScrollBarAttribute + CPAccessibilityVisibleCharacterRangeAttribute + CPAccessibilityVisibleChildrenAttribute + CPAccessibilityVisibleColumnsAttribute + CPAccessibilityVisibleRowsAttribute + CPAccessibilityWindowAttribute + CPAccessibilityWindowCreatedNotification + CPAccessibilityWindowDeminiaturizedNotification + CPAccessibilityWindowMiniaturizedNotification + CPAccessibilityWindowMovedNotification + CPAccessibilityWindowResizedNotification + CPAccessibilityWindowRole + CPAccessibilityWindowsAttribute + CPAccessibilityZoomButtonAttribute + CPAccessibilityZoomButtonSubrole + CPAddTraitFontAction + CPAdminApplicationDirectory + CPAdobeCNS + CPAdobeGB + CPAdobeJapan + CPAdobeKorea + CPAffectedObjectsErrorKey + CPAffectedStoresErrorKey + CPAlertAlternateReturn + CPAlertDefaultReturn + CPAlertErrorReturn + CPAlertFirstButtonReturn + CPAlertOtherReturn + CPAlertSecondButtonReturn + CPAlertThirdButtonReturn + CPAllApplicationsDirectory + CPAllDomainsMask + CPAllLibrariesDirectory + CPAllPredicateModifier + CPAllScrollerParts + CPAlphaFirstBitmapFormat + CPAlphaNonpremultipliedBitmapFormat + CPAlphaShiftKeyMask + CPAlternateKeyMask + CPAnchoredSearch + CPAndPredicateType + CPAnimationBlocking + CPAnimationEaseIn + CPAnimationEaseInOut + CPAnimationEaseOut + CPAnimationEffectDisappearingItemDefault + CPAnimationEffectPoof + CPAnimationLinear + CPAnimationNonblocking + CPAnimationNonblockingThreaded + CPAnyEventMask + CPAnyPredicateModifier + CPAnyType + CPAppKitDefined + CPAppKitDefinedMask + CPAppKitIgnoredException + CPAppKitVirtualMemoryException + CPAppleEventManagerSuspensionID + CPAppleEventTimeOutDefault + CPAppleEventTimeOutNone + CPApplicationActivatedEventType + CPApplicationDeactivatedEventType + CPApplicationDefined + CPApplicationDefinedMask + CPApplicationDelegateReplyCancel + CPApplicationDelegateReplyFailure + CPApplicationDelegateReplySuccess + CPApplicationDidBecomeActiveNotification + CPApplicationDidChangeScreenParametersNotification + CPApplicationDidFinishLaunchingNotification + CPApplicationDidHideNotification + CPApplicationDidResignActiveNotification + CPApplicationDidUnhideNotification + CPApplicationDidUpdateNotification + CPApplicationDirectory + CPApplicationFileType + CPApplicationSupportDirectory + CPApplicationWillBecomeActiveNotification + CPApplicationWillFinishLaunchingNotification + CPApplicationWillHideNotification + CPApplicationWillResignActiveNotification + CPApplicationWillTerminateNotification + CPApplicationWillUnhideNotification + CPApplicationWillUpdateNotification + CPArgumentEvaluationScriptError + CPArgumentsWrongScriptError + CPAscendingPageOrder + CPAsciiWithDoubleByteEUCGlyphPacking + CPAtBottom + CPAtTop + CPAttachmentAttributeName + CPAttachmentCharacter + CPAttributeType + CPAutoPagination + CPAutosaveOperation + CPBMPFileType + CPBackTabCharacter + CPBackgroundColorAttributeName + CPBackgroundTab + CPBackingStoreBuffered + CPBackingStoreNonretained + CPBackingStoreRetained + CPBackspaceCharacter + CPBacktabTextMovement + CPBackwardsSearch + CPBadBitmapParametersException + CPBadComparisonException + CPBadRTFColorTableException + CPBadRTFDirectiveException + CPBadRTFFontTableException + CPBadRTFStyleSheetException + CPBaselineOffsetAttributeName + CPBeginFunctionKey + CPBeginsWithComparison + CPBeginsWithPredicateOperatorType + CPBelowBottom + CPBelowTop + CPBevelLineJoinStyle + CPBezelBorder + CPBinaryDataAttributeType + CPBlueControlTint + CPBoldFontMask + CPBooleanAttributeType + CPBorderlessWindowMask + CPBottomTabsBezelBorder + CPBoxOldStyle + CPBoxPrimary + CPBoxSecondary + CPBoxSeparator + CPBreakFunctionKey + CPBrowserAutoColumnResizing + CPBrowserColumnConfigurationDidChangeNotification + CPBrowserIllegalDelegateException + CPBrowserNoColumnResizing + CPBrowserUserColumnResizing + CPButtLineCapStyle + CPCMYKColorSpaceModel + CPCMYKModeColorPanel + CPCachesDirectory + CPCalculationDivideByZero + CPCalculationLossOfPrecision + CPCalculationNoError + CPCalculationOverflow + CPCalculationUnderflow + CPCalibratedBlackColorSpace + CPCalibratedRGBColorSpace + CPCalibratedWhiteColorSpace + CPCancelButton + CPCancelTextMovement + CPCannotCreateScriptCommandError + CPCarriageReturnCharacter + CPCascadeDeleteRule + CPCaseInsensitiveSearch + CPCellAllowsMixedState + CPCellChangesContents + CPCellDisabled + CPCellEditable + CPCellHasImageHorizontal + CPCellHasImageOnLeftOrBottom + CPCellHasOverlappingImage + CPCellHighlighted + CPCellIsBordered + CPCellIsInsetButton + CPCellLightsByBackground + CPCellLightsByContents + CPCellLightsByGray + CPCenterTabStopType + CPCenterTextAlignment + CPChangeAutosaved + CPChangeBackgroundCell + CPChangeBackgroundCellMask + CPChangeCleared + CPChangeDone + CPChangeGrayCell + CPChangeGrayCellMask + CPChangeReadOtherContents + CPChangeUndone + CPCharacterShapeAttributeName + CPCircularBezelStyle + CPCircularSlider + CPClearControlTint + CPClearDisplayFunctionKey + CPClearLineFunctionKey + CPClipPagination + CPClockAndCalendarDatePickerStyle + CPClosableWindowMask + CPClosePathBezierPathElement + CPColorListDidChangeNotification + CPColorListIOException + CPColorListModeColorPanel + CPColorListNotEditableException + CPColorPanelAllModesMask + CPColorPanelCMYKModeMask + CPColorPanelColorDidChangeNotification + CPColorPanelColorListModeMask + CPColorPanelCrayonModeMask + CPColorPanelCustomPaletteModeMask + CPColorPanelGrayModeMask + CPColorPanelHSBModeMask + CPColorPanelRGBModeMask + CPColorPanelWheelModeMask + CPColorPboardType + CPComboBoxSelectionDidChangeNotification + CPComboBoxSelectionIsChangingNotification + CPComboBoxWillDismissNotification + CPComboBoxWillPopUpNotification + CPCommandKeyMask + CPCompositeClear + CPCompositeCopy + CPCompositeDestinationAtop + CPCompositeDestinationIn + CPCompositeDestinationOut + CPCompositeDestinationOver + CPCompositeHighlight + CPCompositePlusDarker + CPCompositePlusLighter + CPCompositeSourceAtop + CPCompositeSourceIn + CPCompositeSourceOut + CPCompositeSourceOver + CPCompositeXOR + CPCompressedFontMask + CPCondensedFontMask + CPConstantValueExpressionType + CPContainerSpecifierError + CPContainsComparison + CPContentsCellMask + CPContextHelpModeDidActivateNotification + CPContextHelpModeDidDeactivateNotification + CPContinuousCapacityLevelIndicatorStyle + CPControlGlyph + CPControlKeyMask + CPControlTextDidBeginEditingNotification + CPControlTextDidChangeNotification + CPControlTextDidEndEditingNotification + CPControlTintDidChangeNotification + CPCoreServiceDirectory + CPCrayonModeColorPanel + CPCriticalAlertStyle + CPCriticalRequest + CPCursorAttributeName + CPCursorPointingDevice + CPCursorUpdate + CPCursorUpdateMask + CPCurveToBezierPathElement + CPCustomColorSpace + CPCustomPaletteModeColorPanel + CPCustomSelectorPredicateOperatorType + CPDateAttributeType + CPDateFormatterBehavior + CPDateFormatterBehaviorDefault + CPDateFormatterFullStyle + CPDateFormatterLongStyle + CPDateFormatterMediumStyle + CPDateFormatterNoStyle + CPDateFormatterShortStyle + CPDayCalendarUnit + CPDecimalAttributeType + CPDecimalTabStopType + CPDefaultControlTint + CPDefaultTokenStyle + CPDeleteCharFunctionKey + CPDeleteCharacter + CPDeleteFunctionKey + CPDeleteLineFunctionKey + CPDeleteRule + CPDemoApplicationDirectory + CPDenyDeleteRule + CPDescendingPageOrder + CPDesktopDirectory + CPDetailedErrorsKey + CPDeveloperApplicationDirectory + CPDeveloperDirectory + CPDeviceBitsPerSample + CPDeviceBlackColorSpace + CPDeviceCMYKColorSpace + CPDeviceColorSpaceName + CPDeviceIsPrinter + CPDeviceIsScreen + CPDeviceNColorSpaceModel + CPDeviceRGBColorSpace + CPDeviceResolution + CPDeviceSize + CPDeviceWhiteColorSpace + CPDirectPredicateModifier + CPDirectSelection + CPDirectoryFileType + CPDisclosureBezelStyle + CPDiscreteCapacityLevelIndicatorStyle + CPDisplayWindowRunLoopOrdering + CPDocFormatTextDocumentType + CPDocModalWindowMask + CPDocumentDirectory + CPDocumentationDirectory + CPDoubleAttributeType + CPDoubleType + CPDownArrowFunctionKey + CPDownTextMovement + CPDragOperationAll + CPDragOperationCopy + CPDragOperationDelete + CPDragOperationEvery + CPDragOperationGeneric + CPDragOperationLink + CPDragOperationMove + CPDragOperationNone + CPDragOperationPrivate + CPDragPboard + CPDraggingException + CPDrawerClosedState + CPDrawerClosingState + CPDrawerDidCloseNotification + CPDrawerDidOpenNotification + CPDrawerOpenState + CPDrawerOpeningState + CPDrawerWillCloseNotification + CPDrawerWillOpenNotification + CPEndFunctionKey + CPEndsWithComparison + CPEndsWithPredicateOperatorType + CPEnterCharacter + CPEqualToComparison + CPEqualToPredicateOperatorType + CPEraCalendarUnit + CPEraDatePickerElementFlag + CPEraserPointingDevice + CPEvaluatedObjectExpressionType + CPEvenOddWindingRule + CPEventTrackingRunLoopMode + CPEverySubelement + CPExecuteFunctionKey + CPExpandedFontMask + CPExpansionAttributeName + CPF + CPFPCurrentField + CPFPPreviewButton + CPFPPreviewField + CPFPRevertButton + CPFPSetButton + CPFPSizeField + CPFPSizeTitle + CPFaxButton + CPFileAppendOnly + CPFileBusy + CPFileContentsPboardType + CPFileCreationDate + CPFileDeviceIdentifier + CPFileExtensionHidden + CPFileGroupOwnerAccountID + CPFileGroupOwnerAccountName + CPFileHFSCreatorCode + CPFileHFSTypeCode + CPFileHandlingPanelCancelButton + CPFileHandlingPanelOKButton + CPFileImmutable + CPFileModificationDate + CPFileOwnerAccountID + CPFileOwnerAccountName + CPFilePosixPermissions + CPFileReferenceCount + CPFileSize + CPFileSystemFileNumber + CPFileSystemFreeNodes + CPFileSystemFreeSize + CPFileSystemNodes + CPFileSystemNumber + CPFileSystemSize + CPFileType + CPFileTypeBlockSpecial + CPFileTypeCharacterSpecial + CPFileTypeDirectory + CPFileTypeRegular + CPFileTypeSocket + CPFileTypeSymbolicLink + CPFileTypeUnknown + CPFilenamesPboardType + CPFilesPromisePboardType + CPFilesystemFileType + CPFindFunctionKey + CPFindPanelActionNext + CPFindPanelActionPrevious + CPFindPanelActionReplace + CPFindPanelActionReplaceAll + CPFindPanelActionReplaceAllInSelection + CPFindPanelActionReplaceAndFind + CPFindPanelActionSelectAll + CPFindPanelActionSelectAllInSelection + CPFindPanelActionSetFindString + CPFindPanelActionShowFindPanel + CPFindPboard + CPFitPagination + CPFixedPitchFontMask + CPFlagsChanged + CPFlagsChangedMask + CPFloatAttributeType + CPFloatType + CPFloatingPointSamplesBitmapFormat + CPFocusRingAbove + CPFocusRingBelow + CPFocusRingOnly + CPFocusRingTypeDefault + CPFocusRingTypeExterior + CPFocusRingTypeNone + CPFontAntialiasedIntegerAdvancementsRenderingMode + CPFontAntialiasedRenderingMode + CPFontAttributeName + CPFontCascadeListAttribute + CPFontCharacterSetAttribute + CPFontClarendonSerifsClass + CPFontCollectionApplicationOnlyMask + CPFontColorAttribute + CPFontDefaultRenderingMode + CPFontFaceAttribute + CPFontFamilyAttribute + CPFontFixedAdvanceAttribute + CPFontFreeformSerifsClass + CPFontIntegerAdvancementsRenderingMode + CPFontMatrixAttribute + CPFontModernSerifsClass + CPFontNameAttribute + CPFontOldStyleSerifsClass + CPFontOrnamentalsClass + CPFontPanelAllModesMask + CPFontPanelCollectionModeMask + CPFontPanelFaceModeMask + CPFontPanelSizeModeMask + CPFontPanelStandardModesMask + CPFontPboard + CPFontPboardType + CPFontSansSerifClass + CPFontScriptsClass + CPFontSizeAttribute + CPFontSlabSerifsClass + CPFontSlantTrait + CPFontSymbolicClass + CPFontSymbolicTrait + CPFontTraitsAttribute + CPFontTransitionalSerifsClass + CPFontUnavailableException + CPFontUnknownClass + CPFontVariationAttribute + CPFontVariationAxisDefaultValueKey + CPFontVariationAxisIdentifierKey + CPFontVariationAxisMaximumValueKey + CPFontVariationAxisMinimumValueKey + CPFontVariationAxisNameKey + CPFontVisibleNameAttribute + CPFontWeightTrait + CPFontWidthTrait + CPForegroundColorAttributeName + CPFormFeedCharacter + CPFoundationVersionWithFileManagerResourceForkSupport + CPFourByteGlyphPacking + CPFunctionExpressionType + CPFunctionKeyMask + CPGIFFileType + CPGeneralPboard + CPGlobalDomain + CPGlyphAbove + CPGlyphAttributeBidiLevel + CPGlyphAttributeElastic + CPGlyphAttributeInscribe + CPGlyphAttributeSoft + CPGlyphBelow + CPGlyphInfoAttributeName + CPGlyphInscribeAbove + CPGlyphInscribeBase + CPGlyphInscribeBelow + CPGlyphInscribeOverBelow + CPGlyphInscribeOverstrike + CPGlyphLayoutAgainstAPoint + CPGlyphLayoutAtAPoint + CPGlyphLayoutWithPrevious + CPGradientConcaveStrong + CPGradientConcaveWeak + CPGradientConvexStrong + CPGradientConvexWeak + CPGradientNone + CPGraphicsContextDestinationAttributeName + CPGraphicsContextPDFFormat + CPGraphicsContextPSFormat + CPGraphicsContextRepresentationFormatAttributeName + CPGraphiteControlTint + CPGrayColorSpaceModel + CPGrayModeColorPanel + CPGreaterThanComparison + CPGreaterThanOrEqualToComparison + CPGreaterThanOrEqualToPredicateOperatorType + CPGreaterThanPredicateOperatorType + CPGrooveBorder + CPHFSFileTypes + CPHPUXOperatingSystem + CPHSBModeColorPanel + CPHTMLPboardType + CPHTMLTextDocumentType + CPHTTPCookieAcceptPolicyAlways + CPHTTPCookieAcceptPolicyNever + CPHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain + CPHandleOtherExceptionMask + CPHandleTopLevelExceptionMask + CPHandleUncaughtExceptionMask + CPHandleUncaughtRuntimeErrorMask + CPHandleUncaughtSystemExceptionMask + CPHangOnOtherExceptionMask + CPHangOnTopLevelExceptionMask + CPHangOnUncaughtExceptionMask + CPHangOnUncaughtRuntimeErrorMask + CPHangOnUncaughtSystemExceptionMask + CPHashTableCallBacks + CPHeavierFontAction + CPHelpButtonBezelStyle + CPHelpFunctionKey + CPHelpKeyMask + CPHighlightModeMatrix + CPHomeFunctionKey + CPHorizontalRuler + CPHourCalendarUnit + CPISO + CPISOLatin + CPIdentityMappingCharacterCollection + CPIllegalSelectorException + CPIllegalTextMovement + CPImageAbove + CPImageAlignBottom + CPImageAlignBottomLeft + CPImageAlignBottomRight + CPImageAlignCenter + CPImageAlignLeft + CPImageAlignRight + CPImageAlignTop + CPImageAlignTopLeft + CPImageAlignTopRight + CPImageBelow + CPImageCacheAlways + CPImageCacheBySize + CPImageCacheDefault + CPImageCacheException + CPImageCacheNever + CPImageCellType + CPImageColorSyncProfileData + CPImageCompressionFactor + CPImageCompressionMethod + CPImageCurrentFrame + CPImageCurrentFrameDuration + CPImageDitherTransparency + CPImageFrameButton + CPImageFrameCount + CPImageFrameGrayBezel + CPImageFrameGroove + CPImageFrameNone + CPImageFramePhoto + CPImageInterlaced + CPImageInterpolationDefault + CPImageInterpolationHigh + CPImageInterpolationLow + CPImageInterpolationNone + CPImageLeft + CPImageLoadStatusCancelled + CPImageLoadStatusCompleted + CPImageLoadStatusInvalidData + CPImageLoadStatusReadError + CPImageLoadStatusUnexpectedEOF + CPImageLoopCount + CPImageOnly + CPImageOverlaps + CPImageRGBColorTable + CPImageRepLoadStatusCompleted + CPImageRepLoadStatusInvalidData + CPImageRepLoadStatusReadingHeader + CPImageRepLoadStatusUnexpectedEOF + CPImageRepLoadStatusUnknownType + CPImageRepLoadStatusWillNeedAllData + CPImageRepMatchesDevice + CPImageRepRegistryDidChangeNotification + CPImageRight + CPInPredicateOperatorType + CPIndexSubelement + CPInformationalAlertStyle + CPInformationalRequest + CPInsertCharFunctionKey + CPInsertFunctionKey + CPInsertLineFunctionKey + CPIntHashCallBacks + CPIntMapKeyCallBacks + CPIntMapValueCallBacks + CPIntType + CPInteger16AttributeType + CPInteger32AttributeType + CPInteger64AttributeType + CPInteger + CPInterfaceStyleDefault + CPInternalScriptError + CPInternalSpecifierError + CPInvalidIndexSpecifierError + CPItalicFontMask + CPJPEG + CPJPEGFileType + CPJapaneseEUCGlyphPacking + CPJapaneseEUCStringEncoding + CPJustifiedTextAlignment + CPKernAttributeName + CPKeyDown + CPKeyDownMask + CPKeyPathExpressionType + CPKeySpecifierEvaluationScriptError + CPKeyUp + CPKeyUpMask + CPKeyValueChangeInsertion + CPKeyValueChangeRemoval + CPKeyValueChangeReplacement + CPKeyValueChangeSetting + CPKeyValueIntersectSetMutation + CPKeyValueMinusSetMutation + CPKeyValueObservingOptionNew + CPKeyValueObservingOptionOld + CPKeyValueSetSetMutation + CPKeyValueUnionSetMutation + CPL + CPLABColorSpaceModel + CPLError + CPLPrepareRequest + CPLStandardGetURL + CPLandscapeOrientation + CPLayoutCantFit + CPLayoutDone + CPLayoutLeftToRight + CPLayoutNotDone + CPLayoutOutOfGlyphs + CPLayoutRightToLeft + CPLeftArrowFunctionKey + CPLeftMouseDown + CPLeftMouseDownMask + CPLeftMouseDragged + CPLeftMouseDraggedMask + CPLeftMouseUp + CPLeftMouseUpMask + CPLeftTabStopType + CPLeftTabsBezelBorder + CPLeftTextAlignment + CPLeftTextMovement + CPLessThanComparison + CPLessThanOrEqualToComparison + CPLessThanOrEqualToPredicateOperatorType + CPLessThanPredicateOperatorType + CPLibraryDirectory + CPLigatureAttributeName + CPLighterFontAction + CPLikePredicateOperatorType + CPLineBorder + CPLineBreakByCharWrapping + CPLineBreakByClipping + CPLineBreakByTruncatingHead + CPLineBreakByTruncatingMiddle + CPLineBreakByTruncatingTail + CPLineBreakByWordWrapping + CPLineDoesntMove + CPLineMovesDown + CPLineMovesLeft + CPLineMovesRight + CPLineMovesUp + CPLineSeparatorCharacter + CPLineSweepDown + CPLineSweepLeft + CPLineSweepRight + CPLineSweepUp + CPLineToBezierPathElement + CPLinearSlider + CPLinkAttributeName + CPListModeMatrix + CPLiteralSearch + CPLocalDomainMask + CPLocalizedDescriptionKey + CPLogOtherExceptionMask + CPLogTopLevelExceptionMask + CPLogUncaughtExceptionMask + CPLogUncaughtRuntimeErrorMask + CPLogUncaughtSystemExceptionMask + CPM + CPMACHOperatingSystem + CPMacOSRomanStringEncoding + CPMacSimpleTextDocumentType + CPMachErrorDomain + CPMacintoshInterfaceStyle + CPManagedObjectContextLockingError + CPManagedObjectExternalRelationshipError + CPManagedObjectMergeError + CPManagedObjectReferentialIntegrityError + CPManagedObjectValidationError + CPMapTableKeyCallBacks + CPMapTableValueCallBacks + CPMatchesPredicateOperatorType + CPMaxXEdge + CPMaxYEdge + CPMenuDidAddItemNotification + CPMenuDidChangeItemNotification + CPMenuDidEndTrackingNotification + CPMenuDidRemoveItemNotification + CPMenuDidSendActionNotification + CPMenuFunctionKey + CPMenuWillSendActionNotification + CPMiddleSubelement + CPMinXEdge + CPMinYEdge + CPMiniControlSize + CPMiniaturizableWindowMask + CPMinuteCalendarUnit + CPMiterLineJoinStyle + CPMixedState + CPModalPanelRunLoopMode + CPModeSwitchFunctionKey + CPMomentaryChangeButton + CPMomentaryLight + CPMomentaryLightButton + CPMomentaryPushButton + CPMomentaryPushInButton + CPMonthCalendarUnit + CPMouseEntered + CPMouseEnteredMask + CPMouseExited + CPMouseExitedMask + CPMouseMoved + CPMouseMovedMask + CPMouseTracker + CPMoveToBezierPathElement + CPNEXTSTEPStringEncoding + CPNamedColorSpace + CPNarrowFontMask + CPNativeShortGlyphPacking + CPNaturalTextAlignment + CPNetServicesActivityInProgress + CPNetServicesBadArgumentError + CPNetServicesCancelledError + CPNetServicesCollisionError + CPNetServicesInvalidError + CPNetServicesNotFoundError + CPNetServicesTimeoutError + CPNetServicesUnknownError + CPNetworkDomainMask + CPNewNotifyingTextView + CPNewlineCharacter + CPNextFunctionKey + CPNextStepInterfaceStyle + CPNibLoadingException + CPNibOwner + CPNibTopLevelObjects + CPNoActionDeleteRule + CPNoBorder + CPNoCellMask + CPNoFontChangeAction + CPNoImage + CPNoInterfaceStyle + CPNoScriptError + CPNoScrollerParts + CPNoSpecifierError + CPNoSubelement + CPNoTabsBezelBorder + CPNoTabsLineBorder + CPNoTabsNoBorder + CPNoTitle + CPNoTopLevelContainersSpecifierError + CPNoUnderlineStyle + CPNonLossyASCIIStringEncoding + CPNonOwnedPointerHashCallBacks + CPNonOwnedPointerMapKeyCallBacks + CPNonOwnedPointerMapValueCallBacks + CPNonOwnedPointerOrNullMapKeyCallBacks + CPNonRetainedObjectHashCallBacks + CPNonRetainedObjectMapKeyCallBacks + CPNonRetainedObjectMapValueCallBacks + CPNonStandardCharacterSetFontMask + CPNonZeroWindingRule + CPNonactivatingPanelMask + CPNotEqualToPredicateOperatorType + CPNotPredicateType + CPNotificationCoalescingOnName + CPNotificationCoalescingOnSender + CPNotificationDeliverImmediately + CPNotificationNoCoalescing + CPNotificationPostToAllSessions + CPNotificationSuspensionBehaviorCoalesce + CPNotificationSuspensionBehaviorDeliverImmediately + CPNotificationSuspensionBehaviorDrop + CPNotificationSuspensionBehaviorHold + CPNullCellType + CPNullGlyph + CPNullifyDeleteRule + CPNumberFormatterBehavior10_0 + CPNumberFormatterBehavior10_4 + CPNumberFormatterBehavior + CPNumberFormatterBehaviorDefault + CPNumberFormatterCurrencyStyle + CPNumberFormatterDecimalStyle + CPNumberFormatterNoStyle + CPNumberFormatterPadAfterPrefix + CPNumberFormatterPadAfterSuffix + CPNumberFormatterPadBeforePrefix + CPNumberFormatterPadBeforeSuffix + CPNumberFormatterPercentStyle + CPNumberFormatterRoundCeiling + CPNumberFormatterRoundDown + CPNumberFormatterRoundFloor + CPNumberFormatterRoundHalfDown + CPNumberFormatterRoundHalfEven + CPNumberFormatterRoundHalfUp + CPNumberFormatterRoundUp + CPNumberFormatterScientificStyle + CPNumberFormatterSpellOutStyle + CPNumericPadKeyMask + CPNumericSearch + CPOKButton + CPOSF + CPOSStatusErrorDomain + CPObjCArrayType + CPObjCBitfield + CPObjCBoolType + CPObjCCharType + CPObjCDoubleType + CPObjCFloatType + CPObjCLongType + CPObjCLonglongType + CPObjCNoType + CPObjCObjectType + CPObjCPointerType + CPObjCSelectorType + CPObjCShortType + CPObjCStringType + CPObjCStructType + CPObjCUnionType + CPObjCVoidType + CPObjectHashCallBacks + CPObjectMapKeyCallBacks + CPObjectMapValueCallBacks + CPObliquenessAttributeName + CPOffState + CPOldNotifyingTextView + CPOldSelectedCharacterRange + CPOnOffButton + CPOnState + CPOneByteGlyphPacking + CPOnlyScrollerArrows + CPOpenGLCPRasterizationEnable + CPOpenGLCPStateValidation + CPOpenGLCPSurfaceOpacity + CPOpenGLCPSurfaceOrder + CPOpenGLCPSwapInterval + CPOpenGLCPSwapRectangle + CPOpenGLCPSwapRectangleEnable + CPOpenGLGOClearFormatCache + CPOpenGLGOFormatCacheSize + CPOpenGLGOResetLibrary + CPOpenGLGORetainRenderers + CPOpenGLPFAAccelerated + CPOpenGLPFAAccumSize + CPOpenGLPFAAllRenderers + CPOpenGLPFAAlphaSize + CPOpenGLPFAAuxBuffers + CPOpenGLPFAAuxDepthStencil + CPOpenGLPFABackingStore + CPOpenGLPFAClosestPolicy + CPOpenGLPFAColorFloat + CPOpenGLPFAColorSize + CPOpenGLPFACompliant + CPOpenGLPFADepthSize + CPOpenGLPFADoubleBuffer + CPOpenGLPFAFullScreen + CPOpenGLPFAMPSafe + CPOpenGLPFAMaximumPolicy + CPOpenGLPFAMinimumPolicy + CPOpenGLPFAMultiScreen + CPOpenGLPFAMultisample + CPOpenGLPFANoRecovery + CPOpenGLPFAOffScreen + CPOpenGLPFAPixelBuffer + CPOpenGLPFARendererID + CPOpenGLPFARobust + CPOpenGLPFASampleAlpha + CPOpenGLPFASampleBuffers + CPOpenGLPFASamples + CPOpenGLPFAScreenMask + CPOpenGLPFASingleRenderer + CPOpenGLPFAStencilSize + CPOpenGLPFAStereo + CPOpenGLPFASupersample + CPOpenGLPFAVirtualScreenCount + CPOpenGLPFAWindow + CPOperationNotSupportedForKeyScriptError + CPOperationNotSupportedForKeySpecifierError + CPOrPredicateType + CPOrderedAscending + CPOrderedDescending + CPOrderedSame + CPOtherMouseDown + CPOtherMouseDownMask + CPOtherMouseDragged + CPOtherMouseDraggedMask + CPOtherMouseUp + CPOtherMouseUpMask + CPOtherTextMovement + CPOutlineViewColumnDidMoveNotification + CPOutlineViewColumnDidResizeNotification + CPOutlineViewDropOnItemIndex + CPOutlineViewItemDidCollapseNotification + CPOutlineViewItemDidExpandNotification + CPOutlineViewItemWillCollapseNotification + CPOutlineViewItemWillExpandNotification + CPOutlineViewSelectionDidChangeNotification + CPOutlineViewSelectionIsChangingNotification + CPOwnedObjectIdentityHashCallBacks + CPOwnedPointerHashCallBacks + CPOwnedPointerMapKeyCallBacks + CPOwnedPointerMapValueCallBacks + CPPDFPboardType + CPPICTPboardType + CPPLCancelButton + CPPLHeightForm + CPPLImageButton + CPPLOKButton + CPPLOrientationMatrix + CPPLPaperNameButton + CPPLTitleField + CPPLUnitsButton + CPPLWidthForm + CPPNGFileType + CPPOSIXErrorDomain + CPPPCopiesField + CPPPDIncludeNotFoundException + CPPPDIncludeStackOverflowException + CPPPDIncludeStackUnderflowException + CPPPDParseException + CPPPImageButton + CPPPLayoutButton + CPPPNameField + CPPPNameTitle + CPPPNoteField + CPPPNoteTitle + CPPPOptionsButton + CPPPPageChoiceMatrix + CPPPPageRangeFrom + CPPPPageRangeTo + CPPPPaperFeedButton + CPPPPreviewButton + CPPPSaveButton + CPPPScaleField + CPPPStatusField + CPPPStatusTitle + CPPPTitleField + CPPageDownFunctionKey + CPPageUpFunctionKey + CPParagraphSeparatorCharacter + CPParagraphStyleAttributeName + CPPasteboardCommunicationException + CPPatternColorSpace + CPPauseFunctionKey + CPPenPointingDevice + CPPeriodic + CPPeriodicMask + CPPersistentStoreCoordinatorLockingError + CPPersistentStoreIncompatibleSchemaError + CPPersistentStoreIncompleteSaveError + CPPersistentStoreInvalidTypeError + CPPersistentStoreSaveError + CPPersistentStoreTypeMismatchError + CPPlainFileType + CPPlainTextDocumentType + CPPlainTextTokenStyle + CPPointerToStructHashCallBacks + CPPopUpArrowAtBottom + CPPopUpArrowAtCenter + CPPopUpButtonCellWillPopUpNotification + CPPopUpButtonWillPopUpNotification + CPPopUpNoArrow + CPPortraitOrientation + CPPositionAfter + CPPositionBefore + CPPositionBeginning + CPPositionEnd + CPPositionReplace + CPPositiveDoubleType + CPPositiveFloatType + CPPositiveIntType + CPPostASAP + CPPostNow + CPPostScriptPboardType + CPPostWhenIdle + CPPosterFontMask + CPPowerOffEventType + CPPressedTab + CPPrevFunctionKey + CPPrintAllPages + CPPrintBottomMargin + CPPrintCancelJob + CPPrintCopies + CPPrintFaxCoverSheetName + CPPrintFaxHighResolution + CPPrintFaxJob + CPPrintFaxModem + CPPrintFaxReceiverNames + CPPrintFaxReceiverNumbers + CPPrintFaxReturnReceipt + CPPrintFaxSendTime + CPPrintFaxTrimPageEnds + CPPrintFaxUseCoverSheet + CPPrintFirstPage + CPPrintFormName + CPPrintFunctionKey + CPPrintHorizontalPagination + CPPrintHorizontallyCentered + CPPrintJobDisposition + CPPrintJobFeatures + CPPrintLastPage + CPPrintLeftMargin + CPPrintManualFeed + CPPrintMustCollate + CPPrintOperationExistsException + CPPrintOrientation + CPPrintPackageException + CPPrintPagesPerSheet + CPPrintPaperFeed + CPPrintPaperName + CPPrintPaperSize + CPPrintPhotoJobStyleHint + CPPrintPreviewJob + CPPrintPrinter + CPPrintReversePageOrder + CPPrintRightMargin + CPPrintSaveJob + CPPrintSavePath + CPPrintScalingFactor + CPPrintScreenFunctionKey + CPPrintSpoolJob + CPPrintTopMargin + CPPrintVerticalPagination + CPPrintVerticallyCentered + CPPrinterTableError + CPPrinterTableNotFound + CPPrinterTableOK + CPPrintingCancelled + CPPrintingCommunicationException + CPPrintingFailure + CPPrintingReplyLater + CPPrintingSuccess + CPProgressIndicatorBarStyle + CPProgressIndicatorPreferredAquaThickness + CPProgressIndicatorPreferredLargeThickness + CPProgressIndicatorPreferredSmallThickness + CPProgressIndicatorPreferredThickness + CPProgressIndicatorSpinningStyle + CPPropertyListBinaryFormat + CPPropertyListImmutable + CPPropertyListMutableContainers + CPPropertyListMutableContainersAndLeaves + CPPropertyListOpenStepFormat + CPPropertyListXMLFormat + CPProprietaryStringEncoding + CPPushInCell + CPPushInCellMask + CPPushOnPushOffButton + CPQTMovieLoopingBackAndForthPlayback + CPQTMovieLoopingPlayback + CPQTMovieNormalPlayback + CPRGBColorSpaceModel + CPRGBModeColorPanel + CPRTFDPboardType + CPRTFDTextDocumentType + CPRTFPboardType + CPRTFPropertyStackOverflowException + CPRTFTextDocumentType + CPRadioButton + CPRadioModeMatrix + CPRandomSubelement + CPRangeDateMode + CPRatingLevelIndicatorStyle + CPReceiverEvaluationScriptError + CPReceiversCantHandleCommandScriptError + CPRecessedBezelStyle + CPRedoFunctionKey + CPRegularControlSize + CPRegularSquareBezelStyle + CPRelativeAfter + CPRelativeBefore + CPRelevancyLevelIndicatorStyle + CPRemoveTraitFontAction + CPRequiredArgumentsMissingScriptError + CPResetCursorRectsRunLoopOrdering + CPResetFunctionKey + CPResizableWindowMask + CPReturnTextMovement + CPRightArrowFunctionKey + CPRightMouseDown + CPRightMouseDownMask + CPRightMouseDragged + CPRightMouseDraggedMask + CPRightMouseUp + CPRightMouseUpMask + CPRightTabStopType + CPRightTabsBezelBorder + CPRightTextAlignment + CPRightTextMovement + CPRoundBankers + CPRoundDown + CPRoundLineCapStyle + CPRoundLineJoinStyle + CPRoundPlain + CPRoundRectBezelStyle + CPRoundUp + CPRoundedBezelStyle + CPRoundedDisclosureBezelStyle + CPRoundedTokenStyle + CPRulerPboard + CPRulerPboardType + CPRunAbortedResponse + CPRunContinuesResponse + CPRunStoppedResponse + CPSaveAsOperation + CPSaveOperation + CPSaveOptionsAsk + CPSaveOptionsNo + CPSaveOptionsYes + CPSaveToOperation + CPScaleNone + CPScaleProportionally + CPScaleToFit + CPScreenChangedEventType + CPScrollLockFunctionKey + CPScrollWheel + CPScrollWheelMask + CPScrollerArrowsDefaultSetting + CPScrollerArrowsMaxEnd + CPScrollerArrowsMinEnd + CPScrollerArrowsNone + CPScrollerDecrementArrow + CPScrollerDecrementLine + CPScrollerDecrementPage + CPScrollerIncrementArrow + CPScrollerIncrementLine + CPScrollerIncrementPage + CPScrollerKnob + CPScrollerKnobSlot + CPScrollerNoPart + CPSecondCalendarUnit + CPSegmentSwitchTrackingMomentary + CPSegmentSwitchTrackingSelectAny + CPSegmentSwitchTrackingSelectOne + CPSelectByCharacter + CPSelectByParagraph + CPSelectByWord + CPSelectFunctionKey + CPSelectedTab + CPSelectingNext + CPSelectingPrevious + CPSelectionAffinityDownstream + CPSelectionAffinityUpstream + CPShadowAttributeName + CPShadowlessSquareBezelStyle + CPShellCommandFileType + CPShiftJISStringEncoding + CPShiftKeyMask + CPShowControlGlyphs + CPShowInvisibleGlyphs + CPSingleDateMode + CPSingleUnderlineStyle + CPSizeDownFontAction + CPSizeUpFontAction + CPSmallCapsFontMask + CPSmallControlSize + CPSmallIconButtonBezelStyle + CPSmallSquareBezelStyle + CPSolarisOperatingSystem + CPSoundPboardType + CPSpecialPageOrder + CPSplitViewDidResizeSubviewsNotification + CPSplitViewWillResizeSubviewsNotification + CPSquareLineCapStyle + CPStopFunctionKey + CPStreamEventEndEncountered + CPStreamEventErrorOccurred + CPStreamEventHasBytesAvailable + CPStreamEventHasSpaceAvailable + CPStreamEventNone + CPStreamEventOpenCompleted + CPStreamStatusAtEnd + CPStreamStatusClosed + CPStreamStatusError + CPStreamStatusNotOpen + CPStreamStatusOpen + CPStreamStatusOpening + CPStreamStatusReading + CPStreamStatusWriting + CPStrikethroughColorAttributeName + CPStrikethroughStyleAttributeName + CPStringAttributeType + CPStringDrawingDisableScreenFontSubstitution + CPStringDrawingOneShot + CPStringDrawingUsesDeviceMetrics + CPStringDrawingUsesFontLeading + CPStringDrawingUsesLineFragmentOrigin + CPStringEncodingErrorKey + CPStringPboardType + CPStrokeColorAttributeName + CPStrokeWidthAttributeName + CPSunOSOperatingSystem + CPSuperscriptAttributeName + CPSwitchButton + CPSymbolStringEncoding + CPSysReqFunctionKey + CPSystemColorsDidChangeNotification + CPSystemDefined + CPSystemDefinedMask + CPSystemDomainMask + CPSystemFunctionKey + CPTIFFCompressionCCITTFAX + CPTIFFCompressionJPEG + CPTIFFCompressionLZW + CPTIFFCompressionNEXT + CPTIFFCompressionNone + CPTIFFCompressionOldJPEG + CPTIFFCompressionPackBits + CPTIFFException + CPTIFFFileType + CPTIFFPboardType + CPTabCharacter + CPTabColumnTerminatorsAttributeName + CPTabTextMovement + CPTableViewColumnDidMoveNotification + CPTableViewColumnDidResizeNotification + CPTableViewDropAbove + CPTableViewDropOn + CPTableViewFirstColumnOnlyAutoresizingStyle + CPTableViewGridNone + CPTableViewLastColumnOnlyAutoresizingStyle + CPTableViewNoColumnAutoresizing + CPTableViewReverseSequentialColumnAutoresizingStyle + CPTableViewSelectionDidChangeNotification + CPTableViewSelectionIsChangingNotification + CPTableViewSequentialColumnAutoresizingStyle + CPTableViewSolidHorizontalGridLineMask + CPTableViewSolidVerticalGridLineMask + CPTableViewUniformColumnAutoresizingStyle + CPTabletPoint + CPTabletPointEventSubtype + CPTabletPointMask + CPTabletProximity + CPTabletProximityEventSubtype + CPTabletProximityMask + CPTabularTextPboardType + CPTerminateCancel + CPTerminateLater + CPTerminateNow + CPTextBlockAbsoluteValueType + CPTextBlockBaselineAlignment + CPTextBlockBorder + CPTextBlockBottomAlignment + CPTextBlockHeight + CPTextBlockMargin + CPTextBlockMaximumHeight + CPTextBlockMaximumWidth + CPTextBlockMiddleAlignment + CPTextBlockMinimumHeight + CPTextBlockMinimumWidth + CPTextBlockPadding + CPTextBlockPercentageValueType + CPTextBlockTopAlignment + CPTextBlockWidth + CPTextCellType + CPTextDidBeginEditingNotification + CPTextDidChangeNotification + CPTextDidEndEditingNotification + CPTextFieldAndStepperDatePickerStyle + CPTextFieldRoundedBezel + CPTextFieldSquareBezel + CPTextLineTooLongException + CPTextNoSelectionException + CPTextReadException + CPTextReadInapplicableDocumentTypeError + CPTextReadWriteErrorMaximum + CPTextReadWriteErrorMinimum + CPTextSizeMultiplierDocumentOption + CPTextStorageDidProcessEditingNotification + CPTextStorageEditedAttributes + CPTextStorageEditedCharacters + CPTextStorageWillProcessEditingNotification + CPTextTableAutomaticLayoutAlgorithm + CPTextTableFixedLayoutAlgorithm + CPTextViewDidChangeSelectionNotification + CPTextViewDidChangeTypingAttributesNotification + CPTextViewWillChangeNotifyingTextViewNotification + CPTextViews + CPTextWriteException + CPTextWriteInapplicableDocumentTypeError + CPTexturedBackgroundWindowMask + CPTexturedRoundedBezelStyle + CPTexturedSquareBezelStyle + CPThickSquareBezelStyle + CPThickerSquareBezelStyle + CPTickMarkAbove + CPTickMarkBelow + CPTickMarkLeft + CPTickMarkRight + CPTitledWindowMask + CPToggleButton + CPToolTipAttributeName + CPToolbarCustomizeToolbarItemIdentifier + CPToolbarDidRemoveItemNotification + CPToolbarFlexibleSpaceItemIdentifier + CPToolbarPrintItemIdentifier + CPToolbarSeparatorItemIdentifier + CPToolbarShowColorsItemIdentifier + CPToolbarShowFontsItemIdentifier + CPToolbarSpaceItemIdentifier + CPToolbarWillAddItemNotification + CPTopTabsBezelBorder + CPTrackModeMatrix + CPTwoByteGlyphPacking + CPTypedStreamVersionException + CPTypesetterContainerBreakAction + CPTypesetterHorizontalTabAction + CPTypesetterLatestBehavior + CPTypesetterLineBreakAction + CPTypesetterOriginalBehavior + CPTypesetterParagraphBreakAction + CPTypesetterWhitespaceAction + CPTypesetterZeroAdvancementAction + CPURLCacheStorageAllowed + CPURLCacheStorageAllowedInMemoryOnly + CPURLCacheStorageNotAllowed + CPURLCacheStoragePolicy + CPURLCredentialPersistenceForSession + CPURLCredentialPersistenceNone + CPURLCredentialPersistencePermanent + CPURLCredentialStorageInternal + CPURLErrorBadServerResponse + CPURLErrorBadURL + CPURLErrorCancelled + CPURLErrorCannotCloseFile + CPURLErrorCannotConnectToHost + CPURLErrorCannotCreateFile + CPURLErrorCannotFindHost + CPURLErrorCannotLoadFromNetwork + CPURLErrorCannotMoveFile + CPURLErrorCannotOpenFile + CPURLErrorCannotRemoveFile + CPURLErrorCannotWriteToFile + CPURLErrorDNSLookupFailed + CPURLErrorDownloadDecodingFailedMidStream + CPURLErrorDownloadDecodingFailedToComplete + CPURLErrorFileDoesNotExist + CPURLErrorFileIsDirectory + CPURLErrorHTTPTooManyRedirects + CPURLErrorNetworkConnectionLost + CPURLErrorNoPermissionsToReadFile + CPURLErrorNotConnectedToInternet + CPURLErrorRedirectToNonExistentLocation + CPURLErrorResourceUnavailable + CPURLErrorSecureConnectionFailed + CPURLErrorServerCertificateHasBadDate + CPURLErrorServerCertificateHasUnknownRoot + CPURLErrorServerCertificateUntrusted + CPURLErrorTimedOut + CPURLErrorUnknown + CPURLErrorUnsupportedURL + CPURLErrorUserAuthenticationRequired + CPURLErrorUserCancelledAuthentication + CPURLErrorZeroByteResource + CPURLHandleLoadFailed + CPURLHandleLoadInProgress + CPURLHandleLoadSucceeded + CPURLHandleNotLoaded + CPURLPboardType + CPURLRequestCachePolicy + CPURLRequestReloadIgnoringCacheData + CPURLRequestReturnCacheDataDontLoad + CPURLRequestReturnCacheDataElseLoad + CPURLRequestUseProtocolCachePolicy + CPUTF8StringEncoding + CPUnboldFontMask + CPUndefinedAttributeType + CPUnderlineColorAttributeName + CPUnderlinePatternDash + CPUnderlinePatternDashDot + CPUnderlinePatternDashDotDot + CPUnderlinePatternDot + CPUnderlinePatternSolid + CPUnderlineStyleAttributeName + CPUnderlineStyleDouble + CPUnderlineStyleNone + CPUnderlineStyleSingle + CPUnderlineStyleThick + CPUnderlyingErrorKey + CPUndoCloseGroupingRunLoopOrdering + CPUndoFunctionKey + CPUndoManagerDidRedoChangeNotification + CPUndoManagerDidUndoChangeNotification + CPUndoManagerWillCloseUndoGroupNotification + CPUnicodeStringEncoding + CPUnitalicFontMask + CPUnknownColorSpaceModel + CPUnknownKeyScriptError + CPUnknownKeySpecifierError + CPUnknownPageOrder + CPUnknownPointingDevice + CPUnselectCancel + CPUnselectLater + CPUnselectNow + CPUpArrowFunctionKey + CPUpTextMovement + CPUpdateWindowsRunLoopOrdering + CPUserDirectory + CPUserDomainMask + CPUserFunctionKey + CPUserKeyEquivalents + CPUtilityWindowMask + CPVCardPboardType + CPValidationDateTooLateError + CPValidationDateTooSoonError + CPValidationInvalidDateError + CPValidationKeyErrorKey + CPValidationMissingMandatoryPropertyError + CPValidationMultipleErrorsError + CPValidationNumberTooLargeError + CPValidationNumberTooSmallError + CPValidationObjectErrorKey + CPValidationPredicateErrorKey + CPValidationRelationshipDeniedDeleteError + CPValidationRelationshipExceedsMaximumCountError + CPValidationRelationshipLacksMinimumCountError + CPValidationStringPatternMatchingError + CPValidationStringTooLongError + CPValidationStringTooShortError + CPValidationValueErrorKey + CPVariableExpressionType + CPVerticalRuler + CPViaPanelFontAction + CPViewBoundsDidChangeNotification + CPViewFocusDidChangeNotification + CPViewFrameDidChangeNotification + CPViewGlobalFrameDidChangeNotification + CPViewHeightSizable + CPViewMaxXMargin + CPViewMaxYMargin + CPViewMinXMargin + CPViewMinYMargin + CPViewNotSizable + CPViewWidthSizable + CPVoiceAge + CPVoiceDemoText + CPVoiceGender + CPVoiceGenderFemale + CPVoiceGenderMale + CPVoiceGenderNeuter + CPVoiceIdentifier + CPVoiceLanguage + CPVoiceName + CPWantsBidiLevels + CPWarningAlertStyle + CPWeekCalendarUnit + CPWeekdayCalendarUnit + CPWeekdayOrdinalCalendarUnit + CPWheelModeColorPanel + CPWindowAbove + CPWindowBelow + CPWindowCloseButton + CPWindowDidBecomeKeyNotification + CPWindowDidBecomeMainNotification + CPWindowDidChangeScreenNotification + CPWindowDidDeminiaturizeNotification + CPWindowDidEndSheetNotification + CPWindowDidExposeNotification + CPWindowDidMiniaturizeNotification + CPWindowDidMoveNotification + CPWindowDidResignKeyNotification + CPWindowDidResignMainNotification + CPWindowDidResizeNotification + CPWindowDidUpdateNotification + CPWindowDocumentIconButton + CPWindowExposedEventType + CPWindowMiniaturizeButton + CPWindowMovedEventType + CPWindowOut + CPWindowServerCommunicationException + CPWindowToolbarButton + CPWindowWillBeginSheetNotification + CPWindowWillCloseNotification + CPWindowWillMiniaturizeNotification + CPWindowWillMoveNotification + CPWindowZoomButton + CPWindows + CPWindowsCP + CPWindowsNTOperatingSystem + CPWordMLTextDocumentType + CPWordTablesReadException + CPWordTablesWriteException + CPWorkspaceCompressOperation + CPWorkspaceCopyOperation + CPWorkspaceDecompressOperation + CPWorkspaceDecryptOperation + CPWorkspaceDestroyOperation + CPWorkspaceDidLaunchApplicationNotification + CPWorkspaceDidMountNotification + CPWorkspaceDidPerformFileOperationNotification + CPWorkspaceDidTerminateApplicationNotification + CPWorkspaceDidUnmountNotification + CPWorkspaceDidWakeNotification + CPWorkspaceDuplicateOperation + CPWorkspaceEncryptOperation + CPWorkspaceLaunchAllowingClassicStartup + CPWorkspaceLaunchAndDisplayFailures + CPWorkspaceLaunchAndHide + CPWorkspaceLaunchAndHideOthers + CPWorkspaceLaunchAndPrint + CPWorkspaceLaunchAsync + CPWorkspaceLaunchDefault + CPWorkspaceLaunchInhibitingBackgroundOnly + CPWorkspaceLaunchNewInstance + CPWorkspaceLaunchPreferringClassic + CPWorkspaceLaunchWithoutActivation + CPWorkspaceLaunchWithoutAddingToRecents + CPWorkspaceLinkOperation + CPWorkspaceMoveOperation + CPWorkspaceRecycleOperation + CPWorkspaceSessionDidBecomeActiveNotification + CPWorkspaceSessionDidResignActiveNotification + CPWorkspaceWillLaunchApplicationNotification + CPWorkspaceWillPowerOffNotification + CPWorkspaceWillSleepNotification + CPWorkspaceWillUnmountNotification + CPWritingDirectionLeftToRight + CPWritingDirectionNatural + CPWritingDirectionRightToLeft + CPXMLAttributeCDATAKind + CPXMLAttributeDeclarationKind + CPXMLAttributeEntitiesKind + CPXMLAttributeEntityKind + CPXMLAttributeEnumerationKind + CPXMLAttributeIDKind + CPXMLAttributeIDRefKind + CPXMLAttributeIDRefsKind + CPXMLAttributeKind + CPXMLAttributeNMTokenKind + CPXMLAttributeNMTokensKind + CPXMLAttributeNotationKind + CPXMLCommentKind + CPXMLDTDKind + CPXMLDocumentHTMLKind + CPXMLDocumentIncludeContentTypeDeclaration + CPXMLDocumentKind + CPXMLDocumentTextKind + CPXMLDocumentTidyHTML + CPXMLDocumentTidyXML + CPXMLDocumentValidate + CPXMLDocumentXHTMLKind + CPXMLDocumentXMLKind + CPXMLElementDeclarationAnyKind + CPXMLElementDeclarationElementKind + CPXMLElementDeclarationEmptyKind + CPXMLElementDeclarationKind + CPXMLElementDeclarationMixedKind + CPXMLElementDeclarationUndefinedKind + CPXMLElementKind + CPXMLEntityDeclarationKind + CPXMLEntityGeneralKind + CPXMLEntityParameterKind + CPXMLEntityParsedKind + CPXMLEntityPredefined + CPXMLEntityUnparsedKind + CPXMLInvalidKind + CPXMLNamespaceKind + CPXMLNodeCompactEmptyElement + CPXMLNodeExpandEmptyElement + CPXMLNodeIsCDATA + CPXMLNodeOptionsNone + CPXMLNodePreserveAll + CPXMLNodePreserveAttributeOrder + CPXMLNodePreserveCDATA + CPXMLNodePreserveDTD + CPXMLNodePreserveEmptyElements + CPXMLNodePreserveEntities + CPXMLNodePreserveNamespaceOrder + CPXMLNodePreservePrefixes + CPXMLNodePreserveQuotes + CPXMLNodePreserveWhitespace + CPXMLNodePrettyPrint + CPXMLNodeUseDoubleQuotes + CPXMLNodeUseSingleQuotes + CPXMLNotationDeclarationKind + CPXMLParserAttributeHasNoValueError + CPXMLParserAttributeListNotFinishedError + CPXMLParserAttributeListNotStartedError + CPXMLParserAttributeNotFinishedError + CPXMLParserAttributeNotStartedError + CPXMLParserAttributeRedefinedError + CPXMLParserCDATANotFinishedError + CPXMLParserCharacterRefAtEOFError + CPXMLParserCharacterRefInDTDError + CPXMLParserCharacterRefInEpilogError + CPXMLParserCharacterRefInPrologError + CPXMLParserCommentContainsDoubleHyphenError + CPXMLParserCommentNotFinishedError + CPXMLParserConditionalSectionNotFinishedError + CPXMLParserConditionalSectionNotStartedError + CPXMLParserDOCTYPEDeclNotFinishedError + CPXMLParserDelegateAbortedParseError + CPXMLParserDocumentStartError + CPXMLParserElementContentDeclNotFinishedError + CPXMLParserElementContentDeclNotStartedError + CPXMLParserEmptyDocumentError + CPXMLParserEncodingNotSupportedError + CPXMLParserEntityBoundaryError + CPXMLParserEntityIsExternalError + CPXMLParserEntityIsParameterError + CPXMLParserEntityNotFinishedError + CPXMLParserEntityNotStartedError + CPXMLParserEntityRefAtEOFError + CPXMLParserEntityRefInDTDError + CPXMLParserEntityRefInEpilogError + CPXMLParserEntityRefInPrologError + CPXMLParserEntityRefLoopError + CPXMLParserEntityReferenceMissingSemiError + CPXMLParserEntityReferenceWithoutNameError + CPXMLParserEntityValueRequiredError + CPXMLParserEqualExpectedError + CPXMLParserExternalStandaloneEntityError + CPXMLParserExternalSubsetNotFinishedError + CPXMLParserExtraContentError + CPXMLParserGTRequiredError + CPXMLParserInternalError + CPXMLParserInvalidCharacterError + CPXMLParserInvalidCharacterInEntityError + CPXMLParserInvalidCharacterRefError + CPXMLParserInvalidConditionalSectionError + CPXMLParserInvalidDecimalCharacterRefError + CPXMLParserInvalidEncodingError + CPXMLParserInvalidEncodingNameError + CPXMLParserInvalidHexCharacterRefError + CPXMLParserInvalidURIError + CPXMLParserLTRequiredError + CPXMLParserLTSlashRequiredError + CPXMLParserLessThanSymbolInAttributeError + CPXMLParserLiteralNotFinishedError + CPXMLParserLiteralNotStartedError + CPXMLParserMisplacedCDATAEndStringError + CPXMLParserMisplacedXMLDeclarationError + CPXMLParserMixedContentDeclNotFinishedError + CPXMLParserMixedContentDeclNotStartedError + CPXMLParserNAMERequiredError + CPXMLParserNMTOKENRequiredError + CPXMLParserNamespaceDeclarationError + CPXMLParserNoDTDError + CPXMLParserNotWellBalancedError + CPXMLParserNotationNotFinishedError + CPXMLParserNotationNotStartedError + CPXMLParserOutOfMemoryError + CPXMLParserPCDATARequiredError + CPXMLParserParsedEntityRefAtEOFError + CPXMLParserParsedEntityRefInEpilogError + CPXMLParserParsedEntityRefInInternalError + CPXMLParserParsedEntityRefInInternalSubsetError + CPXMLParserParsedEntityRefInPrologError + CPXMLParserParsedEntityRefMissingSemiError + CPXMLParserParsedEntityRefNoNameError + CPXMLParserPrematureDocumentEndError + CPXMLParserProcessingInstructionNotFinishedError + CPXMLParserProcessingInstructionNotStartedError + CPXMLParserPublicIdentifierRequiredError + CPXMLParserSeparatorRequiredError + CPXMLParserSpaceRequiredError + CPXMLParserStandaloneValueError + CPXMLParserStringNotClosedError + CPXMLParserStringNotStartedError + CPXMLParserTagNameMismatchError + CPXMLParserURIFragmentError + CPXMLParserURIRequiredError + CPXMLParserUndeclaredEntityError + CPXMLParserUnfinishedTagError + CPXMLParserUnknownEncodingError + CPXMLParserUnparsedEntityError + CPXMLParserXMLDeclNotFinishedError + CPXMLParserXMLDeclNotStartedError + CPXMLProcessingInstructionKind + CPXMLTextKind + CPYearCalendarUnit + + + + + + ^\s*import + ((?<=[^\\])[\n\r])|(^[\n\r]) + + + + '(?=\\?.') + (\\'')|(.') + + + + /\*" + "\*/ + + + + /\* + \*/ + + + + // + [\n\r] + + + + @?" + (((?<!\\)(\\\\)*)|^)" + + + + diff --git a/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/ToolbarAppKiDo.png b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/ToolbarAppKiDo.png new file mode 100644 index 0000000000000000000000000000000000000000..5c9adc58dd4c15100c083e2d09b1078a5c739d1b GIT binary patch literal 5206 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 QJpcdz07*qoM6N<$f)$ALs{jB1 literal 0 HcmV?d00001 diff --git a/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/ToolbarBuild.tiff b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/ToolbarBuild.tiff new file mode 100644 index 0000000000000000000000000000000000000000..c6294820e4933918432a57281425f1de766341a9 GIT binary patch literal 16080 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 XzJxBE%tjU800000NkvXXu0mjfdt4C0 literal 0 HcmV?d00001 diff --git a/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/ToolbarXcodeProject.png b/Tools/SubEthaEdit/Objective-J.mode/Contents/Resources/ToolbarXcodeProject.png new file mode 100644 index 0000000000000000000000000000000000000000..0381058f35ca0d9fa7a7e0a498545381a114912b GIT binary patch literal 1867 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 literal 0 HcmV?d00001 diff --git a/Tools/Utilities/bridge.js b/Tools/Utilities/bridge.js new file mode 100644 index 000000000..9dc6e9bd2 --- /dev/null +++ b/Tools/Utilities/bridge.js @@ -0,0 +1,476 @@ + //////////// + // window // + //////////// + +if (!this.window) + this.window = this; + + /////////////// + // DOMParser // + /////////////// + +/*function DOMParser() {}; +DOMParser.prototype.parseFromString = function(text, contentType) { + return new DOMDocument( + new Packages.org.xml.sax.InputSource( + new Packages.java.io.StringReader(text))); +};*/ + +function Image() { } + + /////////////////////// + // window.setTimeout // + /////////////////////// + +function setTimeout(code, delay) { + var func; + + if (typeof code == "function") + func = code; + else if (typeof code == "string") + func = function () { eval(code); }; + else + return; + + pendingTimeouts.push(func); +} + +pendingTimeouts = []; + +function pendingTimeout() { + return pendingTimeouts.length > 0; +} + +function serviceTimeout() { + if (pendingTimeout()) { + func = pendingTimeouts.shift(); + return func(); + } +} + +function serviceTimeouts() { + while (pendingTimeout()) { + serviceTimeout(); + } +} + + //////////////////////////// + // alert, prompt, confirm // + //////////////////////////// + +if (typeof alert == "undefined") +{ + alert = function(obj) { + if (typeof debug != "undefined" && debug) { + var result = typeof Packages != "undefined" ? Packages.java.lang.Thread.currentThread().getName() + ": " + obj : String(obj); + + if (typeof print != "undefined") + print(result); + else if (typeof Packages != "undefined") + Packages.java.lang.System.out.println(result); + } + } + confirm = function(obj) { alert(obj); return true; } + prompt = function(obj) { alert(obj); return ""; } +} + + + //////////////////// + // readFile, load // + //////////////////// + +if (typeof readFile == "undefined") { + if (typeof File != "undefined") { + alert("Setting up \"readFile()\" for Spidermonkey"); + this.readFile = function(path) { + var f = new File(path); + + if (!f.canRead) { + //alert("can't read: " + f.path) + return ""; + } + + //alert("reading: " + f.path); + + f.open("read", "text"); + + var result = f.readAll().join("\n"); + + f.close(); + + return result; + } + } + else if (typeof Packages != "undefined") { + alert("Setting up \"readFile()\" for Rhino"); + readFile = function(path, characterCoding) { + var f = new Packages.java.io.File(path); + + if (!f.canRead()) { + //alert("can't read: " + f.path) + return ""; + } + + //alert("reading: " + f.getAbsolutePath()); + + var fis = new Packages.java.io.FileInputStream(f); + + var b = Packages.java.lang.reflect.Array.newInstance(Packages.java.lang.Byte.TYPE, fis.available()); + fis.read(b); + + fis.close(); + + //return String(new Packages.java.lang.String(b)); + if (characterCoding) + return new Packages.java.lang.String(b, characterCoding); + else + return new Packages.java.lang.String(b); + } + } + else { + alert("Warning: No \"readFile\" implementation available.") + } +} + +if (typeof load == "undefined") { + alert("Setting up \"load()\""); + load = function(path) { + return eval(readFile(path)); + } +} + + ///////////// + // inspect // + ///////////// + +function insp(obj) { + for (var i in obj) + alert(i + " ("+(typeof obj[i])+")"); +} +function inspect(obj) { + var a = []; + for (var i in obj) + a.push({name:i, type:(typeof obj[i])}); + a = a.sort(function(a,b) { return a.name.localeCompare(b.name); }); + for (var i = 0; i < a.length; i++) + alert(a[i].name + " ("+a[i].type+")"); +} + +function time(fn) { + var start = new Date(); + + fn(); + + var elapsed = ((new Date()) - start) / 1000; + var minutes = Math.floor(elapsed/60); + var seconds = elapsed - minutes * 60; + + alert("real\t"+minutes+"m"+seconds+"s"); +} + +function recordGlobals() { + GLOBALS_BEFORE = {}; + for (var i in this) + GLOBALS_BEFORE[i] = true; +} +function printGlobalsDiff() { + for (var i in this) + if (GLOBALS_BEFORE[i] == undefined) + alert("NEW: " + i); + for (var i in GLOBALS_BEFORE) + if (this[i] == undefined) + alert("MISSING: " + i); +} + +var hex_lookup = "0123456789abcdef"; +function bytesToHexString(buf) +{ + var buffer = ""; + for (var i = 0 ; i < buf.length; i++) + buffer += hex_lookup[(buf[i] >> 4) & 0x0F] + hex_lookup[buf[i] & 0x0F]; + return buffer; +} + +// Rhino utilities +if (typeof Packages != "undefined") { + alert("Setting up Rhino utilties"); + + jsArrayToJavaArray = function(js_array, type) + { + var java_class = null; + var java_converter = null; + + switch (type || ((js_array && js_array.length > 0) && typeof js_array[0])) + { + case "string": + case "String": + java_class = Packages.java.lang.String; + java_converter = Packages.java.lang.String.valueOf; + break; + case "Boolean": + java_class = Packages.java.lang.Boolean; + java_converter = Packages.java.lang.Boolean.valueOf; + break; + case "boolean": + java_class = Packages.java.lang.Boolean.TYPE; + java_converter = function(input) { return Packages.java.lang.Boolean.valueOf(input).booleanValue(); }; + break; + default: + return null; + } + + if (js_array && js_array.length > 0) + { + var java_array = Packages.java.lang.reflect.Array.newInstance(java_class, js_array.length); + for (var i = 0; i < js_array.length; i++) + java_array[i] = java_converter ? java_converter(js_array[i]) : js_array[i]; + return java_array; + } + + return Packages.java.lang.reflect.Array.newInstance(java_class, 0); + } + + jsObjectToJavaHashMap = function(js_object) + { + var map = Packages.java.util.HashMap(); + for (var i in js_object) + map.put(i, js_object[i]); + return map; + } + + objj_console = function() + { + var br = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(Packages.java.lang.System["in"])); + + keepgoing = true; + while (keepgoing) + { + try { + Packages.java.lang.System.out.print("objj> "); + + var input = br.readLine(); + + var fragments = objj_preprocess(String(input)), + count = fragments.length, + ctx = (new objj_context); + + if (count == 1 && (fragments[0].type & FRAGMENT_CODE)) + { + var fragment = fragments[0]; + var result = eval(fragment.info); + if (result != undefined) + print(result); + } + else if (count > 0) + { + while (count--) + { + var fragment = fragments[count]; + + if (fragment.type & FRAGMENT_FILE) + objj_request_file(fragment.info, (fragment.type & FRAGMENT_LOCAL), NULL); + + ctx.pushFragment(fragment); + } + + ctx.schedule(); + } + + serviceTimeouts(); + } catch (e) { + print(e); + } + } + }; + + var xhr_builder = Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder(); + xhr_builder.setErrorHandler(function(exception, methodName) { + //print("xml error!"); + throw exception; + }); + + copyInputStreamToOutputStream = function(is, os) + { + var buf = Packages.java.lang.reflect.Array.newInstance(Packages.java.lang.Byte.TYPE, 1024*10); + var len = 0; + while ((len = is.read(buf)) != -1) + { + os.write(buf, 0, len); + } + } + var lineEnd = "\r\n"; + var twoHyphens = "--"; + var boundary = "----------------------------b453b5d52446"; + //var boundary = "----CappuccinoBoundary" + (new Date().getTime()); + multipartRequest = function(method, url, headers, parts) + { + var bufferSize = 1024*10, + buffer = Packages.java.lang.reflect.Array.newInstance(Packages.java.lang.Byte.TYPE, bufferSize); + + var url = new Packages.java.net.URL(url), + connection = url.openConnection(); + + connection.setDoOutput(true); + connection.setDoInput(true); + connection.setRequestMethod(method); + + for (var i in headers) + { + print(i+":"+headers[i]); + connection.setRequestProperty(i, headers[i]); + } + + connection.setRequestProperty("Content-Type", "multipart/form-data; boundary="+ boundary); + + var output = new Packages.java.io.DataOutputStream(connection.getOutputStream()); + + for (var i = 0; parts && i < parts.length; i++) + { + var part = parts[i]; + + output.writeBytes(twoHyphens + boundary + lineEnd); + + if (part.headers) + { + for (var header in part.headers) + { + output.writeBytes(header +": " + part.headers[header] + lineEnd); + } + } + output.writeBytes(lineEnd); + + if (part.data) + { + output.writeBytes(part.data); + } + else if (part.stream) + { + var n; + while ((n = part.stream.read(buffer, 0, bufferSize)) > 0) + { + output.write(buffer, 0, n) + } + } + + output.writeBytes(lineEnd); + } + + output.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd); + output.flush(); + output.close(); + + var buffer, + input = new Packages.java.io.DataInputStream(connection.getInputStream()), + result = new Packages.java.lang.StringBuffer(); + + while (null != (buffer = input.readLine())) + result.append(buffer); + + input.close(); + + return String(result.toString()); + } + + parseXMLString = function(string) { + return (Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( + new Packages.org.xml.sax.InputSource( + new Packages.java.io.StringReader(string))).getDocumentElement()); + } +} + +// Environment variables + +OBJJ_HOME = null; +if (typeof Packages != "undefined") + OBJJ_HOME = String(Packages.java.lang.System.getenv().get("OBJJ_HOME") || ""); +else if (typeof environment != "undefined") + OBJJ_HOME = environment["OBJJ_HOME"]; + +if (!OBJJ_HOME) +{ + OBJJ_HOME = "/usr/local/share/objj"; + alert("OBJJ_HOME environment variable not set, defaulting to " + OBJJ_HOME); +} + + //////////////////// + // XMLHttpRequest // + //////////////////// + +function XMLHttpRequest() { + this.readyState = 0; + this.responseText = ""; + this.responseXML = null; + this.status = null; + this.statusText = null; + + this.onreadystatechange = null; + + this.method = null; + this.url = null; + this.async = null; + this.username = null; + this.password = null; +} +XMLHttpRequest.prototype.abort = function() { + this.readyState = 0; +} +XMLHttpRequest.prototype.open = function(method, url, async, username, password) { + this.readyState = 1; + + this.method = method; + this.url = url; + this.async = async; + this.username = username; + this.password = password; +} +XMLHttpRequest.prototype.send = function(body) { + this.readyState = 3; + + this.responseText = ""; + this.responseXML = null; + + try { + this.responseText = readFile(this.url); + alert("xhr: " + this.url); + } catch (e) { + alert("read exception: " + this.url); + this.responseText = ""; + this.responseXML = null; + } + + if (this.responseText.length > 0) { + try { + this.responseXML = xhr_builder.parse(new Packages.org.xml.sax.InputSource(new Packages.java.io.StringReader(this.responseText))); + } catch (e) { + this.responseXML = null; + } + this.status = 200; + } + else { + alert("empty file: " + this.url); + this.status = 404; + } + + this.readyState = 4; + + if (this.onreadystatechange) + { + if (this.async) + setTimeout(this.onreadystatechange, 0); + else + this.onreadystatechange(); + } +} +XMLHttpRequest.prototype.getResponseHeader = function(header) { + return (this.readyState < 3) ? "" : ""; +} +XMLHttpRequest.prototype.getAllResponseHeaders = function() { + return (this.readyState < 3) ? null : ""; +} +XMLHttpRequest.prototype.setRequestHeader = function(name, value) { +} + +objj_request_xmlhttp = function() +{ + return new XMLHttpRequest(); +} diff --git a/Tools/Utilities/build.xml b/Tools/Utilities/build.xml new file mode 100644 index 000000000..5e790434e --- /dev/null +++ b/Tools/Utilities/build.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Utilities/cat b/Tools/Utilities/cat new file mode 100755 index 000000000..58aec1794 --- /dev/null +++ b/Tools/Utilities/cat @@ -0,0 +1,17 @@ +#!/bin/sh + +files="" +outfile="" + +while [ $# -ge 1 ]; do + case $1 in + -o) shift + outfile=$1 + ;; + + *) files="$files $1" + esac + shift +done + +cat $files > $outfile diff --git a/Tools/Utilities/regex-bridge.js b/Tools/Utilities/regex-bridge.js new file mode 100644 index 000000000..7f3afe76c --- /dev/null +++ b/Tools/Utilities/regex-bridge.js @@ -0,0 +1,76 @@ +importClass(java.util.ArrayList); +importClass(java.util.List); +importClass(java.util.regex.Matcher); +importClass(java.util.regex.Pattern); +importClass(java.util.regex.PatternSyntaxException); + +var CachedRegexData = []; + +function regexDataFromRegex(aRegex) +{ + var source = "", + flags = ""; + + if (typeof aRegex == "string") + { + if (CachedRegexData[aRegex]) + return CachedRegexData[aRegex]; + + string = aRegex; + source = aRegex; + } + else + { + string = aRegex.toString(); + + if (CachedRegexData[string]) + return CachedRegexData[string]; + + var index = string.lastIndexOf('/'); + + source = string.substr(0, index); + flags = string.substr(index + 1); + } + + source = source.replace("\\[\\^\\\\\\d\\]", ".", "g"); + source = source.replace("\\[([^\\]]*)\\\\b([^\\]]*)\\]", "[$1\\\\cH$2]", "g") // [...\b...] -> [...\cH...] + source = source.replace("(?&2 + else + echo "OBJJ_HOME not set, default at $OBJJ_HOME doesn't exist, exiting" 1>&2 + exit 2 + fi +fi + +OBJJ_LIB="$OBJJ_HOME/lib" + +BAKE="$OBJJ_LIB/bake.j" + +# convert paths for Cygwin +UNAME=`uname` +case "$UNAME" in + CYGWIN*) + OBJJ_HOME=`cygpath -w "$OBJJ_HOME"` + BAKE=`cygpath -w "$BAKE"` + ;; + *) + ;; +esac + +objj $BAKE $@ diff --git a/Tools/bake/bake.j b/Tools/bake/bake.j new file mode 100644 index 000000000..6786306a6 --- /dev/null +++ b/Tools/bake/bake.j @@ -0,0 +1,263 @@ +import +importPackage(Packages.java.io); + +var options = { + base : "trunk", + clean : false, + deploy : false, + deployHost : null, + deployPath : null, + skipUpdate : false, + tag : false, + archive : false, + message : null, + templatePath : OBJJ_HOME + "/lib/bake_template.html" +} + +var targetPath, + checkoutsPath, + buildsPath, + productsPath, + version = Math.round(new Date().getTime() / 1000); + +CPLogRegister(CPLogPrint); + +function readConfig(configFile) +{ + var fileData = String(readFile(configFile)); + if (!fileData) + throw new Error("Couldn't read file: " + configFile); + + var configs = CPJSObjectCreateWithJSON(fileData); + + return configs; +} + +function update() +{ + for (var i = 0; i < options.sources.length; i++) + { + var source = options.sources[i]; + var sourcePath = checkoutsPath + "/" + source.path.match(new RegExp("[^\\/]+$"))[0]; + + switch (source.type) + { + case "git-ssh": + if (new File(sourcePath).isDirectory()) + { + CPLog.debug("git pull (" + sourcePath + ")"); + exec("git pull", null, new File(sourcePath)); + } + else + { + var gitPath = "ssh://" + source.server + source.path; + CPLog.debug("git clone (" + gitPath + ")"); + exec(["git", "clone", gitPath, sourcePath]); + } + break; + default : + CPLog.error("Unimplemented: " + source.type); + } + + } + +} + +function build() +{ + var versionedPath = productsPath + "/" + version + "/" + version; + + for (var i = 0; i < options.sources.length; i++) + { + var source = options.sources[i]; + var sourcePath = checkoutsPath + "/" + source.path.match(/[^\/]+$/)[0]; + + for (var j = 0; j < source.parts.length; j++) + { + var part = source.parts[j]; + var fromPath = sourcePath + "/" + part.src; + var toPath = versionedPath + "/" + part.dst; + + if (part.build) + { + var buildCommand = part.build.replace("BUILD_PATH", buildsPath); + CPLog.debug("Building: " + buildCommand); + + exec(buildCommand, null, new File(fromPath)); + + fromPath = buildsPath + "/" + part.copyFrom; + } + + mkdirs(toPath); + + var rsyncCommand = "rsync -aC " + fromPath + "/. " + toPath; + CPLog.debug("Rsyncing: " + rsyncCommand); + exec(rsyncCommand); + } + } + + var results = exec(["bash", "-c", "find "+versionedPath+" \\( -name \"*.sj\" -or -name \"*.j\" \\) -exec cat {} \\; | wc -c | tr -d \" \""]); + + var filesTotal = parseInt(results.stdout); + if (isNaN(filesTotal)) + filesTotal = 0; + + CPLog.debug("FILES_TOTAL=["+filesTotal+"]"); + + var substitutions = options.templateVars; + substitutions.VERSION = version; + substitutions.FILES_TOTAL = filesTotal; + + var template = readFile(options.templatePath); + if (!template) + throw new Error("Couldn't get template"); + + for (var variable in substitutions) + template = template.replace(new RegExp("\\$" + variable, "g"), substitutions[variable]); + + templateBytes = new java.lang.String(template).getBytes(); + templateOutput = new FileOutputStream(productsPath + "/" + version + "/index.html"); + templateOutput.write(templateBytes, 0, templateBytes.length); + templateOutput.close(); + + exec(["tar", "czf", version+".tar.gz", version], null, new File(productsPath)); +} + +function deploy() +{ + for (var i = 0; i < options.deployments.length; i++) + { + var dep = options.deployments[i]; + + exec(["scp", productsPath + "/" + version + ".tar.gz", dep.host + ":~/" + version + ".tar.gz"]); + exec(["ssh", dep.host, + "tar xzf " + version + ".tar.gz; " + + "mkdir -p " + dep.path + "; " + + "mv " + version + "/" + version + "/ " + dep.path + "/" + version + "; " + + "mv " + version + "/index.html " + dep.path + "/index.html; " + + "rm " + version + ".tar.gz; " + + "rmdir " + version + "; " + + "cd " + dep.path + "; " + + "ln -nsf " + version + " Current"]); + } +} + +function main() +{ + var bakefile = "bakefile", + commandOpts = {}; + + for (var i = 0; i < args.length; i++) + { + switch (args[i]) + { + case "--base": + commandOpts.base = args[++i]; + break; + case "--tag": + commandOpts.tag = true; + break; + case "--archive": + commandOpts.archive = true; + break; + case "--clean": + commandOpts.clean = true; + break; + case "--deploy": + commandOpts.deploy = true; + break; + case "--host": + commandOpts.deployHost = args[++i]; + break; + case "--path": + commandOpts.deployPath = args[++i]; + break; + case "--skip-update": + commandOpts.skipUpdate = true + break; + case "--message": + commandOpts.message = args[++i]; + break; + default: + bakefile = args[i]; + } + } + + try + { + var configOpts = readConfig(bakefile); + + for (var i in configOpts) options[i] = configOpts[i]; + for (var i in commandOpts) options[i] = commandOpts[i]; + + targetPath = pwd() + "/" + bakefile.match(/^[^\.]+/)[0] + ".oven"; + mkdirs(targetPath); + + checkoutsPath = targetPath + "/Checkouts" + mkdirs(checkoutsPath); + + buildsPath = targetPath + "/Build" + mkdirs(buildsPath); + + productsPath = targetPath + "/Products" + mkdirs(productsPath); + + if (!options.skipUpdate) + { + CPLog.info("Updating"); + update(); + } + + CPLog.info("Building"); + build(); + + if (options.deploy) + { + CPLog.info("Deploying"); + deploy(); + } + + } + catch (e) + { + CPLog.error(e); + } +} + +function exec() +{ + var runtime = Packages.java.lang.Runtime.getRuntime() + var p = runtime.exec.apply(runtime, arguments); + + var stdout = ""; + var reader = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(p.getInputStream())); + while (s = reader.readLine()) + { + stdout += s; + CPLog.info("exec: " + s); + } + + var stderr = ""; + var reader = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(p.getErrorStream())); + while (s = reader.readLine()) + { + stdout += s; + CPLog.warn("exec: " + s); + } + + var code = p.waitFor(); + + return { code : code, stdout : stdout, stderr : stderr }; +} + +function pwd() +{ + return String(new File("").getAbsolutePath()); +} + +function mkdirs(path) +{ + return new File(path).mkdirs(); +} + +main(); \ No newline at end of file diff --git a/Tools/bake/bake_template.html b/Tools/bake/bake_template.html new file mode 100644 index 000000000..5f65e50c7 --- /dev/null +++ b/Tools/bake/bake_template.html @@ -0,0 +1,65 @@ + + + + + + + + Loading... + + + + + + +
+ +
+
+
+

Loading $APPLICATION_NAME...

+
+ + + + + + diff --git a/Tools/bake/build.xml b/Tools/bake/build.xml new file mode 100644 index 000000000..ca975f6b1 --- /dev/null +++ b/Tools/bake/build.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/bake/example.bakefile b/Tools/bake/example.bakefile new file mode 100644 index 000000000..be3a8cbc9 --- /dev/null +++ b/Tools/bake/example.bakefile @@ -0,0 +1,49 @@ +{ + "sources" : [ + { + "type" : "git-ssh", + "server" : "git@git.myserver.com", + "path" : "/home/git/cappuccino.git", + "parts" : [ + { + "src" : "Objective-J", + "dst" : "Frameworks/Objective-J", + "build" : "ant -DBuild=BUILD_PATH", + "copyFrom" : "Release/Objective-J" + }, + { + "src" : "Foundation", + "dst" : "Frameworks/Foundation", + "build" : "steam -c Release -b BUILD_PATH", + "copyFrom" : "Release/Foundation" + }, + { + "src" : "AppKit", + "dst" : "Frameworks/AppKit", + "build" : "steam -c Release -b BUILD_PATH", + "copyFrom" : "Release/AppKit" + } + ] + }, + { + "type" : "git-ssh", + "server" : "git@git.myserver.com", + "path" : "/home/git/myapp.git", + "parts" : [ + { + "src" : "Editor/Server", + "dst" : "Server" + } + ] + } + ], + "deployments" : [ + { "host" : "deploy@myserver.com", "path" : "/var/www/mysite/public" } + ], + "templatePath" : "index.html", + "templateVars" : { + "APPLICATION_NAME" : "My Application", + "BACKGROUND_COLOR" : "black", + "TEXT_COLOR" : "black" + } +} diff --git a/Tools/build.xml b/Tools/build.xml new file mode 100644 index 000000000..a363ec65b --- /dev/null +++ b/Tools/build.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Tools/nib2cib/HelloWorld.nib/classes.nib b/Tools/nib2cib/HelloWorld.nib/classes.nib new file mode 100644 index 000000000..c4b887e72 --- /dev/null +++ b/Tools/nib2cib/HelloWorld.nib/classes.nib @@ -0,0 +1,8 @@ + + + + + IBVersion + 1 + + diff --git a/Tools/nib2cib/HelloWorld.nib/info.nib b/Tools/nib2cib/HelloWorld.nib/info.nib new file mode 100644 index 000000000..2511941ff --- /dev/null +++ b/Tools/nib2cib/HelloWorld.nib/info.nib @@ -0,0 +1,18 @@ + + + + + IBFramework Version + 629 + IBOldestOS + 5 + IBOpenObjects + + 1 + + IBSystem Version + 9E17 + targetFramework + IBCocoaFramework + + diff --git a/Tools/nib2cib/HelloWorld.nib/keyedobjects.nib b/Tools/nib2cib/HelloWorld.nib/keyedobjects.nib new file mode 100644 index 000000000..f3853becd --- /dev/null +++ b/Tools/nib2cib/HelloWorld.nib/keyedobjects.nib @@ -0,0 +1,604 @@ + + + + + $archiver + NSKeyedArchiver + $objects + + $null + + $class + + CF$UID + 49 + + NSAccessibilityConnectors + + CF$UID + 46 + + NSAccessibilityOidsKeys + + CF$UID + 47 + + NSAccessibilityOidsValues + + CF$UID + 48 + + NSClassesKeys + + CF$UID + 38 + + NSClassesValues + + CF$UID + 39 + + NSConnections + + CF$UID + 8 + + NSFontManager + + CF$UID + 0 + + NSFramework + + CF$UID + 5 + + NSNamesKeys + + CF$UID + 32 + + NSNamesValues + + CF$UID + 33 + + NSNextOid + 5 + NSObjectsKeys + + CF$UID + 10 + + NSObjectsValues + + CF$UID + 31 + + NSOidsKeys + + CF$UID + 40 + + NSOidsValues + + CF$UID + 41 + + NSRoot + + CF$UID + 2 + + NSVisibleWindows + + CF$UID + 6 + + + + $class + + CF$UID + 4 + + NSClassName + + CF$UID + 3 + + + NSObject + + $classes + + NSCustomObject + NSObject + + $classname + NSCustomObject + + IBCocoaFramework + + $class + + CF$UID + 7 + + NS.objects + + + + $classes + + NSMutableSet + NSSet + NSObject + + $classname + NSMutableSet + + + $class + + CF$UID + 9 + + NS.objects + + + + $classes + + NSMutableArray + NSArray + NSObject + + $classname + NSMutableArray + + + $class + + CF$UID + 30 + + NS.objects + + + CF$UID + 11 + + + CF$UID + 13 + + + CF$UID + 16 + + + + + $class + + CF$UID + 4 + + NSClassName + + CF$UID + 12 + + + NSApplication + + $class + + CF$UID + 29 + + NSClassName + + CF$UID + 28 + + NSFrameSize + + CF$UID + 26 + + NSNextResponder + + CF$UID + 14 + + NSSubviews + + CF$UID + 15 + + NSSuperview + + CF$UID + 27 + + NSWindow + + CF$UID + 14 + + NSvFlags + 268 + + $null + + $class + + CF$UID + 9 + + NS.objects + + + CF$UID + 16 + + + + + $class + + CF$UID + 25 + + NSCell + + CF$UID + 18 + + NSEnabled + + NSFrame + + CF$UID + 17 + + NSNextResponder + + CF$UID + 13 + + NSSuperview + + CF$UID + 13 + + NSWindow + + CF$UID + 14 + + NSvFlags + 268 + + {{166, 124}, {154, 19}} + + $class + + CF$UID + 24 + + NSAlternateContents + + CF$UID + 23 + + NSButtonFlags + -2038152961 + NSButtonFlags2 + 164 + NSCellFlags + -2080244224 + NSCellFlags2 + 134217728 + NSContents + + CF$UID + 19 + + NSControlView + + CF$UID + 16 + + NSKeyEquivalent + + CF$UID + 23 + + NSPeriodicDelay + 400 + NSPeriodicInterval + 75 + NSSupport + + CF$UID + 20 + + + Hello World + + $class + + CF$UID + 22 + + NSName + + CF$UID + 21 + + NSSize + 12 + NSfFlags + 16 + + LucidaGrande + + $classes + + NSFont + NSObject + + $classname + NSFont + + + + $classes + + NSButtonCell + NSActionCell + NSCell + NSObject + + $classname + NSButtonCell + + + $classes + + NSButton + NSControl + NSView + NSResponder + NSObject + + $classname + NSButton + + {480, 272} + $null + NSView + + $classes + + NSCustomView + NSView + NSResponder + NSObject + + $classname + NSCustomView + + + $classes + + NSArray + NSObject + + $classname + NSArray + + + $class + + CF$UID + 30 + + NS.objects + + + CF$UID + 2 + + + CF$UID + 2 + + + CF$UID + 13 + + + + + $class + + CF$UID + 30 + + NS.objects + + + CF$UID + 13 + + + CF$UID + 2 + + + CF$UID + 11 + + + CF$UID + 16 + + + + + $class + + CF$UID + 30 + + NS.objects + + + CF$UID + 34 + + + CF$UID + 35 + + + CF$UID + 36 + + + CF$UID + 37 + + + + Custom View + File's Owner + Application + Round Rect Button (Hello World) + + $class + + CF$UID + 30 + + NS.objects + + + + $class + + CF$UID + 30 + + NS.objects + + + + $class + + CF$UID + 30 + + NS.objects + + + CF$UID + 13 + + + CF$UID + 2 + + + CF$UID + 11 + + + CF$UID + 16 + + + + + $class + + CF$UID + 30 + + NS.objects + + + CF$UID + 42 + + + CF$UID + 43 + + + CF$UID + 44 + + + CF$UID + 45 + + + + 1 + 4 + -3 + 2 + + $class + + CF$UID + 9 + + NS.objects + + + + $class + + CF$UID + 30 + + NS.objects + + + + $class + + CF$UID + 30 + + NS.objects + + + + $classes + + NSIBObjectData + NSObject + + $classname + NSIBObjectData + + + $top + + IB.objectdata + + CF$UID + 1 + + + $version + 100000 + + diff --git a/Tools/nib2cib/NSAppKit.j b/Tools/nib2cib/NSAppKit.j new file mode 100644 index 000000000..47def697d --- /dev/null +++ b/Tools/nib2cib/NSAppKit.j @@ -0,0 +1,10 @@ + +import "NSButton.j" +import "NSCell.j" +import "NSControl.j" +import "NSCustomView.j" +import "NSFont.j" +import "NSIBObjectData.j" +import "NSResponder.j" +import "NSSlider.j" +import "NSView.j" diff --git a/Tools/nib2cib/NSArray.j b/Tools/nib2cib/NSArray.j new file mode 100644 index 000000000..702e15d96 --- /dev/null +++ b/Tools/nib2cib/NSArray.j @@ -0,0 +1,19 @@ + +import + + +@implementation NSArray : CPObject +{ +} + +- (id)initWithCoder:(CPCoder)aCoder +{ + return [aCoder _decodeArrayOfObjectsForKey:@"NS.objects"]; +} + +@end + +@implementation NSMutableArray : NSArray +{ +} +@end \ No newline at end of file diff --git a/Tools/nib2cib/NSButton.j b/Tools/nib2cib/NSButton.j new file mode 100644 index 000000000..1a888e512 --- /dev/null +++ b/Tools/nib2cib/NSButton.j @@ -0,0 +1,88 @@ + +import + +import "NSCell.j" +import "NSControl.j" + + +@implementation CPButton (NSCoding) + +- (id)NS_initWithCoder:(CPCoder)aCoder +{ + self = [super NS_initWithCoder:aCoder]; + + if (self) + { + var cell = [aCoder decodeObjectForKey:@"NSCell"]; + + [self setBordered:[cell isBordered]]; + [self setBezelStyle:[cell bezelStyle]]; + + [self setTitle:[cell title]]; + } + + return self; +} + +@end + +@implementation NSButton : CPButton +{ +} + +- (id)initWithCoder:(CPCoder)aCoder +{ + return [self NS_initWithCoder:aCoder]; +} + +- (Class)classForKeyedArchiver +{ + return [CPButton class]; +} + +@end + +@implementation NSButtonCell : NSCell +{ + BOOL _isBordered; + unsigned _bezelStyle; + + CPString _title; +} + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super initWithCoder:aCoder]; + + if (self) + { + var buttonFlags = [aCoder decodeIntForKey:@"NSButtonFlags"], + buttonFlags2 = [aCoder decodeIntForKey:@"NSButtonFlags2"]; + + _isBordered = (buttonFlags & 0x00800000) ? YES : NO; + _bezelStyle = (buttonFlags2 & 0x7) | ((buttonFlags2 & 0x20) >> 2); + + + // NSContents for NSButton is actually the title + _title = [aCoder decodeObjectForKey:@"NSContents"]; + } + + return self; +} + +- (BOOL)isBordered +{ + return _isBordered; +} + +- (int)bezelStyle +{ + return _bezelStyle; +} + +- (CPString)title +{ + return _title; +} + +@end diff --git a/Tools/nib2cib/NSCell.j b/Tools/nib2cib/NSCell.j new file mode 100644 index 000000000..4ac39357b --- /dev/null +++ b/Tools/nib2cib/NSCell.j @@ -0,0 +1,45 @@ + +import + +import "NSFont.j" + + +@implementation NSCell : CPObject +{ + CPFont _font; + id _contents; +} + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super init]; + + if (self) + { + _font = [aCoder decodeObjectForKey:@"NSFont"]; + _contents = [aCoder decodeObjectForKey:@"NSContents"]; + } + + return self; +} + +- (id)replacementObjectForCoder:(CPCoder)aCoder +{ + return nil; +} + +//- (void)encodeWithCoder:(CPCoder)aCoder +//{ + + +- (CPFont)font +{ + return _font; +} + +- (id)contents +{ + return _contents; +} + +@end diff --git a/Tools/nib2cib/NSControl.j b/Tools/nib2cib/NSControl.j new file mode 100644 index 000000000..d5f8ccd79 --- /dev/null +++ b/Tools/nib2cib/NSControl.j @@ -0,0 +1,43 @@ + +import + +import "NSCell.j" +import "NSView.j" + + +@implementation CPControl (NSCoding) + +- (id)NS_initWithCoder:(CPCoder)aCoder +{ + self = [super NS_initWithCoder:aCoder]; + + if (self) + { + var cell = [aCoder decodeObjectForKey:@"NSCell"]; + + _value = [cell contents]; + + [self setFont:[cell font]]; + [self setEnabled:[aCoder decodeObjectForKey:@"NSEnabled"]]; + } + + return self; +} + +@end + +@implementation NSControl : CPControl +{ +} + +- (id)initWithCoder:(CPCoder)aCoder +{ + return [self NS_initWithCoder:aCoder]; +} + +- (Class)classForKeyedArchiver +{ + return [CPControl class]; +} + +@end diff --git a/Tools/nib2cib/NSCustomView.j b/Tools/nib2cib/NSCustomView.j new file mode 100644 index 000000000..4ed40b1fd --- /dev/null +++ b/Tools/nib2cib/NSCustomView.j @@ -0,0 +1,42 @@ + +import + +import "NSView.j" + + +@implementation NSCustomView : CPView +{ + CPString _className; +} + +- (id)initWithCoder:(CPCoder)aCoder +{ + self = [super NS_initWithCoder:aCoder]; + + if (self) + _className = [aCoder decodeObjectForKey:@"NSClassName"]; + + return self; +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [super encodeWithCoder:aCoder]; + + [aCoder encodeObject:_NSCustomViewMapClassName(_className) forKey:@"CPCustomViewClassNameKey"]; +} + +- (CPString)classForKeyedArchiver +{ + return [CPCustomView class]; +} + +@end + +function _NSCustomViewMapClassName(aClassName) +{ + if (aClassName == @"NSView") + return "CPView"; + + return aClassName; +} diff --git a/Tools/nib2cib/NSFont.j b/Tools/nib2cib/NSFont.j new file mode 100644 index 000000000..46ec5199f --- /dev/null +++ b/Tools/nib2cib/NSFont.j @@ -0,0 +1,28 @@ + +import + +@implementation CPFont (NSCoding) + +- (id)NS_initWithCoder:(CPCoder)aCoder +{ + // FIXME: bold? + return [self _initWithName:[aCoder decodeObjectForKey:@"NSName"] size:[aCoder decodeDoubleForKey:@"NSSize"] bold:NO]; +} + +@end + +@implementation NSFont : CPFont +{ +} + +- (id)initWithCoder:(CPCoder)aCoder +{ + return [self NS_initWithCoder:aCoder]; +} + +- (Class)classForKeyedArchiver +{ + return [CPFont class]; +} + +@end diff --git a/Tools/nib2cib/NSFoundation.j b/Tools/nib2cib/NSFoundation.j new file mode 100644 index 000000000..944c5cfc5 --- /dev/null +++ b/Tools/nib2cib/NSFoundation.j @@ -0,0 +1,2 @@ + +import "NSArray.j" diff --git a/Tools/nib2cib/NSIBObjectData.j b/Tools/nib2cib/NSIBObjectData.j new file mode 100644 index 000000000..9953f38cd --- /dev/null +++ b/Tools/nib2cib/NSIBObjectData.j @@ -0,0 +1,96 @@ + +/*#import "NSIBObjectData.h" +#import +#import +#import +#import +#import +#import "NSNibKeyedUnarchiver.h" +#import "NSCustomObject.h" +#import +#import +#import */ + +import + +import + +@implementation _CPCibObjectData (NSCoding) + +- (id)NS_initWithCoder:(CPCoder)aCoder +{ + self = [self init]; + + if (self) + { +/* NSNibKeyedUnarchiver *keyed=(NSNibKeyedUnarchiver *)coder; + NSMutableDictionary *nameTable=[NSMutableDictionary dictionaryWithDictionary:[keyed externalNameTable]]; + NSArray *uids=[keyed decodeArrayOfUidsForKey:@"NSNamesKeys"]; + int i,count; + id owner; + + if((owner=[nameTable objectForKey:NSNibOwner])!=nil) + [nameTable setObject:owner forKey:@"File's Owner"]; + + [nameTable setObject:[NSFontManager sharedFontManager] forKey:@"Font Manager"]; + + + + var count = [_namesValues count]; + + for(i=0;i + + +@implementation CPResponder (NSCoding) + +- (id)NS_initWithCoder:(CPCoder)aCoder +{ + self = [super init]; + + if (self) + [self setNextResponder:[aCoder decodeObjectForKey:@"NSNextResponder"]]; + + return self; +} + +@end + +@implementation NSResponder : CPResponder +{ +} + +- (id)initWithCoder:(CPCoder)aCoder +{ + return [self NS_initWithCoder:aCoder]; +} + +- (Class)classForKeyedArchiver +{ + return [CPResponder class]; +} + +@end \ No newline at end of file diff --git a/Tools/nib2cib/NSSlider.j b/Tools/nib2cib/NSSlider.j new file mode 100644 index 000000000..09ced75ac --- /dev/null +++ b/Tools/nib2cib/NSSlider.j @@ -0,0 +1,47 @@ + +import + +import "NSSlider.j" + + +@implementation CPSlider (CPCoding) + +- (id)NS_initWithCoder:(CPCoder)aCoder +{ + self = [super NS_initWithCoder:aCoder]; + + if (self) + { + _minValue = [aCoder decodeDoubleForKey:@"NSMinValue"]; + _maxValue = [aCoder decodeDoubleForKey:@"NSMaxValue"]; +/* _knobThickness=8.0; + _numberOfTickMarks=[keyed decodeIntForKey:@"NSNumberOfTickMarks"]; + _tickMarkPosition=[keyed decodeIntForKey:@"NSTickMarkPosition"]; + _allowsTickMarkValuesOnly=[keyed decodeBoolForKey:@"NSAllowsTickMarkValuesOnly"];*/ + } + + return self; +} + +@end + +@implementation NSSlider : CPSlider +{ +} + +- (id)initWithCoder:(CPCoder)aCoder +{ + return [self NS_initWithCoder:aCoder]; +} + +- (Class)classForKeyedArchiver +{ + return [CPSlider class]; +} + +@end + +@implementation NSSliderCell : NSCell +{ +} +@end diff --git a/Tools/nib2cib/NSView.j b/Tools/nib2cib/NSView.j new file mode 100644 index 000000000..d6d2508f6 --- /dev/null +++ b/Tools/nib2cib/NSView.j @@ -0,0 +1,96 @@ + +import + + +//unsigned int rotatedFromBase:1; +//unsigned int rotatedOrScaledFromBase:1; +//unsigned int autosizing:6; +//unsigned int autoresizeSubviews:1; +//unsigned int wantsGState:1; +//unsigned int needsDisplay:1; +//unsigned int validGState:1; +//unsigned int newGState:1; +//unsigned int noVerticalAutosizing:1; +//unsigned int frameChangeNotesSuspended:1; +//unsigned int needsFrameChangeNote:1; +//unsigned int focusChangeNotesSuspended:1; +//unsigned int boundsChangeNotesSuspended:1; +//unsigned int needsBoundsChangeNote:1; +//unsigned int removingWithoutInvalidation:1; +//unsigned int interfaceStyle0:1; +//unsigned int needsDisplayForBounds:1; +//unsigned int specialArchiving:1; +//unsigned int interfaceStyle1:1; +//unsigned int retainCount:6; +//unsigned int retainCountOverMax:1; +//unsigned int aboutToResize:1; + +@implementation CPView (NSCoding) + +- (id)NS_initWithCoder:(CPCoder)aCoder +{ + _frame = CGRectMakeZero(); + + if ([aCoder containsValueForKey:@"NSFrame"]) + _frame = [aCoder decodeRectForKey:@"NSFrame"]; + else if ([aCoder containsValueForKey:@"NSFrameSize"]) + _frame.size = [aCoder decodeSizeForKey:@"NSFrameSize"]; + + self = [super NS_initWithCoder:aCoder]; + + if (self) + { + _bounds = CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame)); + + _window = [aCoder decodeObjectForKey:@"NSWindow"]; + _superview = [aCoder decodeObjectForKey:@"NSSuperview"]; + _subviews = [aCoder decodeObjectForKey:@"NSSubviews"]; + + if (!_subviews) + _subviews = []; + + var vFlags = [aCoder decodeIntForKey:@"NSvFlags"]; + + _autoresizingMask = vFlags & (0x3F << 1); + _autoresizesSubviews = vFlags & (1 << 8); + + _hitTests = YES; + _isHidden = NO;//[aCoder decodeObjectForKey:CPViewIsHiddenKey]; + _opacity = 1.0;//[aCoder decodeIntForKey:CPViewOpacityKey]; + + if (YES/*[_superview isFlipped]*/) + { + var height = CGRectGetHeight([self bounds]), + count = [_subviews count]; + + while (count--) + { + var subview = _subviews[count], + frame = [subview frame]; + + [subview setFrameOrigin:CGPointMake(CGRectGetMinX(frame), height - CGRectGetMaxY(frame))]; + } + } + } + + return self; +} + +@end + +@implementation NSView : CPView +{ +} + +- (id)initWithCoder:(CPCoder)aCoder +{ + return [[CPView alloc] NS_initWithCoder:aCoder]; +} + +- (Class)classForKeyedArchiver +{ + return [CPView class]; +} + +@end + diff --git a/Tools/nib2cib/nib2cib b/Tools/nib2cib/nib2cib new file mode 100755 index 000000000..194aecc18 --- /dev/null +++ b/Tools/nib2cib/nib2cib @@ -0,0 +1,6 @@ +#!/bin/sh + +SELF_PATH=$(cd -P -- "$(dirname -- "$0")" && pwd -P) && SELF_PATH=$SELF_PATH/$(basename -- "$0") +SELF_DIR=`dirname $SELF_PATH` + +$SELF_DIR/objj $SELF_DIR/../nib2cib/nib2cib.j $@ diff --git a/Tools/nib2cib/nib2cib.j b/Tools/nib2cib/nib2cib.j new file mode 100644 index 000000000..65c03f233 --- /dev/null +++ b/Tools/nib2cib/nib2cib.j @@ -0,0 +1,83 @@ + +import + +import + +import "NSFoundation.j" +import "NSAppKit.j" + +importClass(java.io.FileWriter); +importClass(java.io.BufferedWriter); + + +function exec(command) +{ + var p = Packages.java.lang.Runtime.getRuntime().exec(jsArrayToJavaArray(command)); + var result = p.waitFor(); + + var reader = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(p.getInputStream())); + while (s = reader.readLine()) + print(s); + + var reader = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(p.getErrorStream())); + while (s = reader.readLine()) + print(s); + + return result; +} + +// Make sure we can read the file +if (!(new Packages.java.io.File(args[0])).canRead()) +{ + print("Could not read file at " + args[0]); + return; +} + +// Compile xib or nib to make sure we have a non-new format nib. +var temporaryNibFile = Packages.java.io.File.createTempFile("temp", ".nib"), + temporaryNibFilePath = temporaryNibFile.getAbsolutePath(); + +temporaryNibFile.deleteOnExit(); + +if (exec(["/usr/bin/ibtool", args[0], "--compile", temporaryNibFilePath])) +{ + print("Could not compile file at " + args[0]); + return; +} + +// Convert from binary plist to XML plist +var temporaryPlistFile = Packages.java.io.File.createTempFile("temp", ".plist"), + temporaryPlistFilePath = temporaryPlistFile.getAbsolutePath(); + +temporaryPlistFile.deleteOnExit(); + +if (exec(["/usr/bin/plutil", "-convert", "xml1", temporaryNibFilePath, "-o", temporaryPlistFilePath])) +{ + print("Could not convert to xml plist for file at " + args[0]); + return; +} + +var data = [CPURLConnection sendSynchronousRequest:[CPURLRequest requestWithURL:temporaryPlistFilePath] returningResponse:nil error:nil]; + +// Minor NSKeyedArchive to CPKeyedArchive conversion. +[data setString:[data string].replace(/\\s*CF\$UID\s*\<\/key\>/g, "CP$UID")]; + + +// Unarchive the NS data +var unarchiver = [[CPKeyedUnarchiver alloc] initForReadingWithData:data], + objectData = [unarchiver decodeObjectForKey:@"IB.objectdata"], + + data = [CPData data], + archiver = [[CPKeyedArchiver alloc] initForWritingWithMutableData:data]; + +// Re-archive the CP data. +[archiver encodeObject:objectData forKey:@"CPCibObjectDataKey"]; +[archiver finishEncoding]; + +var writer = new BufferedWriter(new FileWriter("MainMenu.cib"));//outputPath + name.substring(0, args[0].indexOf(".")) + ".o")); + +writer.write([data string]); + +writer.close(); + + diff --git a/Tools/nib2cib/project.properties b/Tools/nib2cib/project.properties new file mode 100644 index 000000000..b0555d24f --- /dev/null +++ b/Tools/nib2cib/project.properties @@ -0,0 +1,5 @@ + +CPBundleExecutable=nibtocib +CPBundleIdentifier=com.280North.nibtocib +CPBundleName=nibtocib +CPBundlePackageType=280N diff --git a/Tools/objj/build.xml b/Tools/objj/build.xml new file mode 100644 index 000000000..f6894ba9c --- /dev/null +++ b/Tools/objj/build.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/objj/objj b/Tools/objj/objj new file mode 100644 index 000000000..ad415c0e7 --- /dev/null +++ b/Tools/objj/objj @@ -0,0 +1,51 @@ +#!/bin/sh + +# if OBJJ_HOME isn't set, try to determine it out +if [ -z $OBJJ_HOME ]; then + SELF_PATH=$(cd -P -- "$(dirname -- "$0")" && pwd -P) && SELF_PATH=$SELF_PATH/$(basename -- "$0") + SELF_DIR=`dirname $SELF_PATH` + + export OBJJ_HOME="`dirname $SELF_DIR`/share/objj" + + if [ -d $OBJJ_HOME ]; then + echo "OBJJ_HOME not set, defaulting to $OBJJ_HOME" 1>&2 + else + echo "OBJJ_HOME not set, default at $OBJJ_HOME doesn't exist, exiting" 1>&2 + exit 2 + fi +fi + +OBJJ_LIB="$OBJJ_HOME/lib" +CLASSPATH="$OBJJ_LIB:$OBJJ_LIB/js.jar:$CLASSPATH" + +OBJJ="$OBJJ_LIB/objj.js" +RLWRAP=`which rlwrap` +FRAMEWORKS="$STEAM_BUILD" + +# if there's a "lib" directory, add all the jars from it +if [ -d "lib" ]; then + JARS=`find ./lib -name '*.jar' 2> /dev/null | tr "\n" ":"` + CLASSPATH="$JARS:$CLASSPATH" +fi + +# convert paths for Cygwin +UNAME=`uname` +case "$UNAME" in + CYGWIN*) + OBJJ_HOME=`cygpath -wp "$OBJJ_HOME"` + OBJJ_LIB=`cygpath -wp "$OBJJ_LIB"` + OBJJ=`cygpath -wp "$OBJJ"` + FRAMEWORKS=`cygpath -w "$FRAMEWORKS"` + STEAM_BUILD=`cygpath -w "$STEAM_BUILD"` + CLASSPATH=`cygpath -wp "$CLASSPATH"` + ;; + *) + ;; +esac + +if [ -e $STEAM_BUILD/Objective-J.build/Release/Rhino ]; then + $RLWRAP java -classpath $CLASSPATH objj $OBJJ_LIB $STEAM_BUILD $@ + #$RLWRAP java -classpath $CLASSPATH org.mozilla.javascript.tools.shell.Main $OBJJ $OBJJ_LIB $STEAM_BUILD $@ +else + echo "Missing frameworks at $STEAM_BUILD/Objective-J.build/Release/Rhino" 1>&2 +fi diff --git a/Tools/objj/objj.js b/Tools/objj/objj.js new file mode 100644 index 000000000..0c975b598 --- /dev/null +++ b/Tools/objj/objj.js @@ -0,0 +1,47 @@ +debug = false; +args = arguments; + +var helpersBase = arguments[0]; +var STEAM_BUILD = arguments[1]; +arguments.splice(0, 2); + +if (typeof window == "undefined") +{ + print("Loading Objective-J bridge."); + load(helpersBase+'/bridge.js'); +} + +if (typeof objj_import == "undefined") +{ + print("Loading Objective-J."); + load(STEAM_BUILD+'/Objective-J.build/Release/Rhino/Objective-J.js'); +} + +OBJJ_INCLUDE_PATHS = [STEAM_BUILD+'/Release']; + +if (arguments.length > 0) +{ + var main_file = arguments[0]; + arguments.splice(0, 1); + + if (debug) + print("Loading: " + main_file); + + objj_import(main_file, NO); + + serviceTimeouts(); + + if (debug) + print("Done!"); +} +else if (typeof objj_console != "undefined") +{ + if (debug) + print("Starting Objective-J console."); + + objj_console(); +} +else +{ + print("Error: No file provided or console available.") +} diff --git a/Tools/objjc/build.xml b/Tools/objjc/build.xml new file mode 100644 index 000000000..de9fb7d98 --- /dev/null +++ b/Tools/objjc/build.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/objjc/objjc b/Tools/objjc/objjc new file mode 100644 index 000000000..f60e89a47 --- /dev/null +++ b/Tools/objjc/objjc @@ -0,0 +1,31 @@ +#!/bin/sh + +# if OBJJ_HOME isn't set, try to determine it out +if [ -z $OBJJ_HOME ]; then + SELF_PATH=$(cd -P -- "$(dirname -- "$0")" && pwd -P) && SELF_PATH=$SELF_PATH/$(basename -- "$0") + SELF_DIR=`dirname $SELF_PATH` + + export OBJJ_HOME="`dirname $SELF_DIR`/share/objj" + + if [ -d $OBJJ_HOME ]; then + echo "OBJJ_HOME not set, defaulting to $OBJJ_HOME" 1>&2 + else + echo "OBJJ_HOME not set, default at $OBJJ_HOME doesn't exist, exiting" 1>&2 + exit 2 + fi +fi + +OBJJ_LIB="$OBJJ_HOME/lib" +CLASSPATH="$OBJJ_LIB:$OBJJ_LIB/js.jar:$CLASSPATH" + +# convert paths for Cygwin +UNAME=`uname` +case "$UNAME" in + CYGWIN*) + CLASSPATH=`cygpath -wp "$CLASSPATH"` + ;; + *) + ;; +esac + +java -classpath $CLASSPATH objjc $@ diff --git a/Tools/objjc/objjc.js b/Tools/objjc/objjc.js new file mode 100644 index 000000000..3833432d4 --- /dev/null +++ b/Tools/objjc/objjc.js @@ -0,0 +1,106 @@ + +importPackage(java.lang); + +importClass(java.io.File); +importClass(java.io.BufferedReader); +importClass(java.io.FileReader); +importClass(java.io.BufferedWriter); +importClass(java.io.FileWriter); + + +function exec(command) +{ + var p = Packages.java.lang.Runtime.getRuntime().exec(command);//jsArrayToJavaArray(command)); + + var reader = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(p.getInputStream())); + while (s = reader.readLine()) + System.out.println(s); + + var reader = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(p.getErrorStream())); + while (s = reader.readLine()) + System.out.println(s); + + var result = p.waitFor(); + + return result; +} + +function preprocess(aFilePath, outFilePath, gccArgs, shouldObjjPreprocess) +{ + print("Statically Preprocessing " + aFilePath); + + var tmpFile = java.io.File.createTempFile("OBJJC", ""); + tmpFile.deleteOnExit(); + + // -E JUST preprocess. + // -x c Interpret language as C -- closest thing to JavaScript. + // -P Don't generate #line directives + var gccComponents = ["gcc", "-E", "-x", "c", "-P", aFilePath, "-o", shouldObjjPreprocess ? tmpFile.getAbsolutePath() : outFilePath], + index = gccArgs.length; + + // Add custom gcc arguments. + while (index--) + gccComponents.splice(5, 0, gccArgs[index]); + + exec(gccComponents); + + if (!shouldObjjPreprocess) + return; + + // Read file and preprocess it. + var reader = new BufferedReader(new FileReader(tmpFile)), + fileContents = ""; + + // Get contents of the file + while (reader.ready()) + fileContents += reader.readLine() + '\n'; + + reader.close(); + + // Write file. + var writer = new BufferedWriter(new FileWriter(outFilePath)); + + writer.write(objj_preprocess_file(new File(aFilePath).getName(), fileContents)); + + writer.close(); +} + +function main() +{ + var filePaths = [], + outFilePaths = [], + + index = 0, + count = args.length, + + gccArgs = [], + + shouldObjjPreprocess = true; + + for (; index < count; ++index) + { + if (args[index] == "-o") + { + if (++index < count) + outFilePaths.push(args[index]); + } + + else if (args[index].indexOf("-D") == 0) + gccArgs.push(args[index]) + + else if (args[index].indexOf("-U") == 0) + gccArgs.push(args[index]); + + else if (args[index].indexOf("-E") == 0) + shouldObjjPreprocess = false; + + else + filePaths.push(args[index]); + } + + for (index = 0, count = filePaths.length; index < count; ++index) + preprocess(filePaths[index], outFilePaths[index], gccArgs, shouldObjjPreprocess); +} + +args = arguments; +main(); diff --git a/Tools/steam/build.xml b/Tools/steam/build.xml new file mode 100644 index 000000000..f4cbf2b1b --- /dev/null +++ b/Tools/steam/build.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/steam/sjheader.txt b/Tools/steam/sjheader.txt new file mode 100644 index 000000000..57390737c --- /dev/null +++ b/Tools/steam/sjheader.txt @@ -0,0 +1 @@ +@STATIC;1.0; \ No newline at end of file diff --git a/Tools/steam/steam b/Tools/steam/steam new file mode 100644 index 000000000..5195a437d --- /dev/null +++ b/Tools/steam/steam @@ -0,0 +1,31 @@ +#!/bin/sh + +# if OBJJ_HOME isn't set, try to determine it out +if [ -z $OBJJ_HOME ]; then + SELF_PATH=$(cd -P -- "$(dirname -- "$0")" && pwd -P) && SELF_PATH=$SELF_PATH/$(basename -- "$0") + SELF_DIR=`dirname $SELF_PATH` + + export OBJJ_HOME="`dirname $SELF_DIR`/share/objj" + + if [ -d $OBJJ_HOME ]; then + echo "OBJJ_HOME not set, defaulting to $OBJJ_HOME" 1>&2 + else + echo "OBJJ_HOME not set, default at $OBJJ_HOME doesn't exist, exiting" 1>&2 + exit 2 + fi +fi + +OBJJ_LIB="$OBJJ_HOME/lib" +CLASSPATH="$OBJJ_LIB:$OBJJ_LIB/js.jar:$CLASSPATH" + +# convert paths for Cygwin +UNAME=`uname` +case "$UNAME" in + CYGWIN*) + CLASSPATH=`cygpath -wp "$CLASSPATH"` + ;; + *) + ;; +esac + +java -classpath $CLASSPATH steam $@ diff --git a/Tools/steam/steam.js b/Tools/steam/steam.js new file mode 100644 index 000000000..1c0476ba3 --- /dev/null +++ b/Tools/steam/steam.js @@ -0,0 +1,504 @@ + +importPackage(java.lang); +importPackage(java.util); + +importClass(java.io.File); +importClass(java.io.BufferedReader); +importClass(java.io.FileReader); +importClass(java.io.BufferedWriter); +importClass(java.io.FileWriter); +importClass(java.io.SequenceInputStream); + + +function Target(dictionary) +{ + this._name = dictionary_getValue(dictionary, "name"); + + this._exclusions = []; + + var exclusions = dictionary_getValue(dictionary, "Excluded"); + + if (exclusions) + { + var index = 0, + count = exclusions.length; + + for (; index < count; ++index) + { + var file = new File(exclusions[index]).getCanonicalFile(); + + if (file.isDirectory()) + { + var files = getFiles(file); + + if (files.length) + this._exclusions = this._exclusions.concat(files); + } + else + this._exclusions.push(file); + } + } + + return this; +} + +Target.prototype.name = function() +{ + return this._name; +} + +Target.prototype.exclusions = function() +{ + return this._exclusions; +} + +function Configuration(dictionary) +{ + this._name = dictionary_getValue(dictionary, "name"); + + return this; +} + +Configuration.prototype.name = function() +{ + return this._name; +} + +function Project(/*String*/ aFilePath, /*String*/ aBuildPath) +{ + this._file = new File(aFilePath).getCanonicalFile(); + this._root = this._file.getParentFile(); + + // Read the project file (its just a plist). + this._properties = readPlist(this._file); + + // Read existing Info.plist if it exists. + var infoPlist = new File(this._root.getAbsolutePath() + "/Info.plist"); + + if (infoPlist.exists()) + this._infoDictionary = readPlist(new File(this._root.getAbsolutePath() + "/Info.plist")); + else + this._infoDictionary = new objj_dictionary(); + + this.buildPath = aBuildPath; + + // Covert target dictionaries to target objects. + var targetDictionaries = dictionary_getValue(this._properties, "Targets"); + + this._targets = []; + + for (index = 0, count = targetDictionaries.length; index < count; ++index) + this._targets.push(new Target(targetDictionaries[index])); + + this.setActiveTarget(this._targets[0]); + + // Covert target dictionaries to target objects. + var configurationDictionaries = dictionary_getValue(this._properties, "Configurations"); + + this._configurations = []; + + for (index = 0, count = configurationDictionaries.length; index < count; ++index) + this._configurations.push(new Configuration(configurationDictionaries[index])); + + this.setActiveConfiguration(this._configurations[0]); + + // Grab the Resources Directory (if it exists) + this._resources = new File(this._root.getAbsolutePath() + "/Resources/").getCanonicalFile(); + + return this; +} + +Project.prototype.targetWithName = function(/*String*/ aName) +{ + var targets = this._targets, + index = 0, + count = targets.length; + + for (; index < count; ++index) + { + var target = targets[index]; + + if (target.name() == aName) + return target; + } + + return null; +} + +Project.prototype.configurationWithName = function(/*String*/ aName) +{ + var configurations = this._configurations, + index = 0, + count = configurations.length; + + for (; index < count; ++index) + { + var configuration = configurations[index]; + + if (configuration.name() == aName) + return configuration; + } + + return null; +} + +Project.prototype.setActiveTarget = function(/*Target*/ aTarget) +{ + this._activeTarget = aTarget; + + this._buildProducts = null; + this._buildIntermediates = null; + this._buildObjects = null; +} + +Project.prototype.setActiveConfiguration = function(/*Configuration*/ aConfiguration) +{ + this._activeConfiguration = aConfiguration; + + this._buildProducts = null; + this._buildIntermediates = null; + this._buildObjects = null; +} + +Project.prototype.buildProducts = function() +{ + if (!this._buildProducts) + { + this._buildProducts = new File(this.buildPath + '/' + this._activeConfiguration.name() + '/' + this._activeTarget.name()).getCanonicalFile(); + this._buildProducts.mkdirs(); + } + + return this._buildProducts; +} + +Project.prototype.buildIntermediates = function() +{ + if (!this._buildIntermediates) + { + this._buildIntermediates = new File(this.buildPath + '/' + this._activeTarget.name() + ".build/" + this._activeConfiguration.name()).getCanonicalFile(); + this._buildIntermediates.mkdirs(); + } + + return this._buildIntermediates; +} + +Project.prototype.buildObjects = function() +{ + if (!this._buildObjects) + { + this._buildObjects = new File(this.buildIntermediates().getAbsolutePath() + '/' + this._activeTarget.name()).getCanonicalFile(); + this._buildObjects.mkdirs(); + } + + return this._buildObjects; +} + +Project.prototype.build = function() +{ + var jFiles = getFiles(this._root, "j", this._activeTarget.exclusions()), + replacedFiles = []; + hasModifiedJFiles = false; + shouldObjjPreprocess = true, + objjcComponents = ["objjc"]; + + if (!shouldObjjPreprocess) + objjcComponents.push("-E"); + + var buildObjects = this.buildObjects(), + buildProducts = this.buildProducts(); + + for (index = 0, count = jFiles.length; index < count; ++index) + { + var file = jFiles[index], + builtFile = new File(buildObjects.getAbsolutePath() + '/' + getFileNameWithoutExtension(file) + '.o'); + + replacedFiles.push(file.getName() + ""); + + if (builtFile.exists() && file.lastModified() < builtFile.lastModified()) + continue; + else + hasModifiedJFiles = true; + + objjcComponents.push(file.getAbsolutePath()); + + objjcComponents.push("-o"); + objjcComponents.push(buildObjects.getAbsolutePath() + '/' + getFileNameWithoutExtension(file) + '.o'); + } + + exec(objjcComponents, true); + + if (hasModifiedJFiles) + { + var oFiles = getFiles(buildObjects, 'o'), + sjFile = new File(buildProducts.getCanonicalPath() + '/' + this._activeTarget.name() + ".sj"), + + catComponents = [OBJJ_HOME + "/lib/cat", OBJJ_HOME + "/lib/sjheader.txt"]; + + for (index = 0, count = oFiles.length; index < count; ++index) + catComponents.push(oFiles[index].getCanonicalPath()); + + catComponents.push("-o"); + catComponents.push(sjFile.getCanonicalPath()); + + exec(catComponents); + } + + dictionary_setValue(this._infoDictionary, "CPBundleExecutable", this._activeTarget.name() + ".sj"); + dictionary_setValue(this._infoDictionary, "CPBundleReplacedFiles", replacedFiles); + + this.writeInfoPlist(); + + this.copyResources(); + + // FIXME: This should be, if this is an app... + if (dictionary_getValue(this._infoDictionary, "CPBundlePackageType") == "280N") + this.copyIndexFile(); +} + +Project.prototype.clean = function() +{ + exec(["rm", "-rf", this.buildIntermediates().getAbsolutePath()], true); + exec(["rm", "-rf", this.buildProducts().getAbsolutePath()], true); +} + +Project.prototype.copyIndexFile = function() +{ + var indexFile = new File(this._root.getAbsolutePath() + "/index.html").getCanonicalFile(); + + if (indexFile.exists()) + exec(["rsync", "-avz", indexFile.getAbsolutePath(), this.buildProducts().getAbsolutePath()]); +} + +Project.prototype.writeInfoPlist = function() +{ + var writer = new BufferedWriter(new FileWriter(this.buildProducts().getAbsolutePath() + '/' + "Info.plist")); + + writer.write(CPPropertyListCreateXMLData(this._infoDictionary).string); + + writer.close(); +} + +Project.prototype.copyResources = function() +{ + if (this._resources.exists()) + exec(["rsync", "-avz", this._resources.getAbsolutePath() + '/', this.buildProducts().getAbsolutePath() + "/Resources"]); +} + +function main() +{ + var index = 0, + count = arguments.length, + + actions = [], + + targetName = null, + configurationName = null, + + buildPath = null, + projectFilePath = null; + + for (; index < count; ++index) + { + switch (arguments[index]) + { + case "-f": if (index + 1 == count) + throw "-f needs project file."; + + projectFilePath = arguments[++index]; + break; + + case "-t": if (index + 1 == count) + throw "-t needs a target"; + + targetName = arguments[++index]; + break; + + case "-c": if (index + 1 == count) + throw "-c needs configuration"; + + configurationName = arguments[++index]; + break; + + case "-b": if (index + 1 == count) + throw "-b needs a build location"; + + buildPath = arguments[++index]; + break; + + case "clean": + case "build": actions.push(arguments[index]); + break; + } + } + + // If no project file was specified, look for one. + if (!projectFilePath) + { + var candidates = getFiles(new File('.'), "steam"); + + if (candidates.length < 1) + throw "No project file specified or found."; + + projectFilePath = candidates[0]; + } + + // Construct the Build Directory + if (!buildPath) + { + buildPath = System.getenv("STEAM_BUILD"); + + if (!buildPath) + buildPath = "Build"; + } + + var project = new Project(projectFilePath, buildPath); + + if (targetName) + { + var target = project.targetWithName(targetName); + + if (!target) + throw "Target \"" + targetName + "\" not found in project."; + + project.setActiveTarget(target); + } + + if (configurationName) + { + var configuration = project.configurationWithName(configurationName); + + if (!configuration) + throw "Configuration \"" + configurationName + "\" not found in project."; + + project.setActiveConfiguration(configuration); + } + + if (!actions.length) + actions.push("build"); + + for (index = 0, count = actions.length; index < count; ++index) + project[actions[index]](); +} + +function fileArrayContainsFile(/*Array*/ files, /*File*/ aFile) +{ + var index = 0, + count = files.length; + + for (; index < count; ++index) + if (files[index].equals(aFile)) + return true; + + return false; +} + +function getFiles(/*File*/ sourceDirectory, /*String*/ extension, /*Array*/ exclusions) +{ + var matches = [], + files = sourceDirectory.listFiles(); + + if (files) + { + var index = 0, + count = files.length; + + for (; index < count; ++index) + { + var file = files[index].getCanonicalFile(), + name = String(file.getName()); + + if ((!extension || name.substring(name.length - extension.length - 1) == ("." + extension)) && (!exclusions || !fileArrayContainsFile(exclusions, file))) + matches.push(file); + + if (file.isDirectory()) + matches = matches.concat(getFiles(file, extension, exclusions)); + } + } + + return matches; +} + +function readPlist(/*File*/ aFile) +{ + var reader = new BufferedReader(new FileReader(aFile)), + fileContents = ""; + + // Get contents of the file + while (reader.ready()) + fileContents += reader.readLine() + '\n'; + + reader.close(); + + var data = new objj_data(); + data.string = fileContents; + + return new CPPropertyListCreateFromData(data); +} + +function exec(/*Array*/ command, /*Boolean*/ showOutput) +{ + var line = "", + output = "", + + process = Packages.java.lang.Runtime.getRuntime().exec(command),//jsArrayToJavaArray(command)); + reader = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(process.getInputStream())); + + while (line = reader.readLine()) + { + if (showOutput) + System.out.println(line); + + output += line + '\n'; + } + + reader = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(process.getErrorStream())); + + while (line = reader.readLine()) + System.out.println(line); + + try + { + if (process.waitFor() != 0) + System.err.println("exit value = " + process.exitValue()); + } + catch (anException) + { + System.err.println(anException); + } + + return output; +} + +function getFileName(aPath) +{ + var index = aPath.lastIndexOf('/'); + + if (index == -1) + return aPath; + + return aPath.substr(index + 1); +} + +function getFileNameWithoutExtension(aFile) +{ + var name = aFile.getName(), + index = name.lastIndexOf('.'); + + if (index == -1 || index == 0) + return name; + + return name.substr(0, index); +} + +function getFileExtension(aPath) +{ + var slash = aPath.lastIndexOf('/'), + period = aPath.lastIndexOf('.'); + + if (period < slash || (period == slash + 1)) + return ""; + + return aPath.substr(period + 1); +} + +main.apply(main, arguments); diff --git a/Tools/steam/steam.xml b/Tools/steam/steam.xml new file mode 100644 index 000000000..5d994b3c6 --- /dev/null +++ b/Tools/steam/steam.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build.xml b/build.xml new file mode 100644 index 000000000..d0f4f2dec --- /dev/null +++ b/build.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common.xml b/common.xml new file mode 100644 index 000000000..262ef1927 --- /dev/null +++ b/common.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file