Skip to content
Browse files

code completion round 1tm_dialog

exit
;
  • Loading branch information...
1 parent 0d0d220 commit 8b7219e2c95868051dbf059340378cb182a4b69b @malkomalko committed Nov 19, 2009
Showing with 19,789 additions and 25 deletions.
  1. +36 −0 Commands/Code Completion.tmCommand
  2. +1 −3 Commands/Documentation for Word.tmCommand
  3. +31 −0 Commands/Insert Color.tmCommand
  4. +1 −1 Commands/Load Delegate Window.tmCommand
  5. +111 −0 Support/lib/autocomplete.rb
  6. +71 −6 Support/lib/delegates.rb
  7. +15 −15 Support/nib/Cappuccino.nib/designable.nib
  8. BIN Support/nib/Cappuccino.nib/keyedobjects.nib
  9. +257 −0 Support/source/CAAnimation.j
  10. +73 −0 Support/source/CABackingStore.j
  11. +50 −0 Support/source/CAFlashLayer.j
  12. +1,203 −0 Support/source/CALayer.j
  13. +102 −0 Support/source/CAMediaTimingFunction.j
  14. +152 −0 Support/source/CGAffineTransform.j
  15. +288 −0 Support/source/CGColor.j
  16. +240 −0 Support/source/CGColorSpace.j
  17. +705 −0 Support/source/CGContext.j
  18. +449 −0 Support/source/CGContextCanvas.j
  19. +320 −0 Support/source/CGContextVML.j
  20. +238 −0 Support/source/CGGeometry.j
  21. +58 −0 Support/source/CGGradient.j
  22. +397 −0 Support/source/CGPath.j
  23. +361 −0 Support/source/CPAccordionView.j
  24. +312 −0 Support/source/CPAlert.j
  25. +347 −0 Support/source/CPAnimation.j
  26. +991 −0 Support/source/CPApplication.j
  27. +464 −0 Support/source/CPArray+KVO.j
  28. +1,236 −0 Support/source/CPArray.j
  29. +844 −0 Support/source/CPAttributedString.j
  30. +291 −0 Support/source/CPBezierPath.j
  31. +244 −0 Support/source/CPBox.j
  32. +197 −0 Support/source/CPBundle.j
  33. +647 −0 Support/source/CPButton.j
  34. +61 −0 Support/source/CPButtonBar.j
  35. +64 −0 Support/source/CPCheckBox.j
  36. +220 −0 Support/source/CPClipView.j
  37. +160 −0 Support/source/CPCoder.j
  38. +733 −0 Support/source/CPCollectionView.j
  39. +85 −0 Support/source/CPCollectionViewItem.j
  40. +791 −0 Support/source/CPColor.j
  41. +662 −0 Support/source/CPColorPanel.j
  42. +375 −0 Support/source/CPColorPicker.j
  43. +308 −0 Support/source/CPColorWell.j
  44. +208 −0 Support/source/CPCompatibility.j
  45. +689 −0 Support/source/CPControl.j
  46. +114 −0 Support/source/CPCookie.j
  47. +109 −0 Support/source/CPCountedSet.j
  48. +120 −0 Support/source/CPData.j
  49. +162 −0 Support/source/CPDate.j
  50. +611 −0 Support/source/CPDictionary.j
  51. +926 −0 Support/source/CPDocument.j
  52. +456 −0 Support/source/CPDocumentController.j
  53. +436 −0 Support/source/CPDragServer.j
  54. +59 −0 Support/source/CPEnumerator.j
  55. +494 −0 Support/source/CPEvent.j
  56. +197 −0 Support/source/CPException.j
  57. +61 −0 Support/source/CPFlashMovie.j
  58. +112 −0 Support/source/CPFlashView.j
  59. +161 −0 Support/source/CPFont.j
  60. +174 −0 Support/source/CPFontManager.j
  61. +509 −0 Support/source/CPGeometry.j
Sorry, we could not display the entire diff because it was too big.
View
36 Commands/Code Completion.tmCommand
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>beforeRunningCommand</key>
+ <string>nop</string>
+ <key>command</key>
+ <string>#!/usr/bin/env ruby
+
+bundle_path = ENV['TM_BUNDLE_SUPPORT']
+support_path = ENV['TM_SUPPORT_PATH']
+
+require support_path + '/lib/ui.rb'
+require bundle_path + '/lib/autocomplete.rb'
+
+ac = Autocomplete.new(ENV['TM_CURRENT_WORD'])
+
+if ac.empty == true
+ print "#{e_sn(ac.previous_line)}$1]" if ac.previous_line.gsub(' ','').size &gt; 0
+elsif ac.brackets == true
+ #
+end</string>
+ <key>input</key>
+ <string>document</string>
+ <key>keyEquivalent</key>
+ <string>^ </string>
+ <key>name</key>
+ <string>Code Completion</string>
+ <key>output</key>
+ <string>insertAsSnippet</string>
+ <key>scope</key>
+ <string>source.js.objj</string>
+ <key>uuid</key>
+ <string>EEF2BF83-2EC4-463D-91C8-B2FF4AEFFD14</string>
+</dict>
+</plist>
View
4 Commands/Documentation for Word.tmCommand
@@ -7,9 +7,7 @@
<key>command</key>
<string>"${TM_BUNDLE_SUPPORT}/bin/show_documentation_for_word.rb"</string>
<key>input</key>
- <string>selection</string>
- <key>keyEquivalent</key>
- <string>^h</string>
+ <string>none</string>
<key>name</key>
<string>Documentation for Word</string>
<key>output</key>
View
31 Commands/Insert Color.tmCommand
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>beforeRunningCommand</key>
+ <string>nop</string>
+ <key>command</key>
+ <string>#!/usr/bin/env ruby
+
+bundle_path = ENV['TM_BUNDLE_SUPPORT']
+support_path = ENV['TM_SUPPORT_PATH']
+
+require support_path + '/lib/ui.rb'
+response = TextMate::UI.request_color
+print response</string>
+ <key>fallbackInput</key>
+ <string>word</string>
+ <key>input</key>
+ <string>none</string>
+ <key>keyEquivalent</key>
+ <string>^c</string>
+ <key>name</key>
+ <string>Insert Color</string>
+ <key>output</key>
+ <string>afterSelectedText</string>
+ <key>scope</key>
+ <string>source.js.objj</string>
+ <key>uuid</key>
+ <string>7A155973-712E-4109-8826-F5C0E6B481A5</string>
+</dict>
+</plist>
View
2 Commands/Load Delegate Window.tmCommand
@@ -29,7 +29,7 @@ response = TextMate::UI.dialog1(:nib =&gt; nib,
end
-print "- (void)#{e_sn(response)}:(id)sender
+print "- (void)#{e_sn(response)}(id)sender
{
${0}
}" if !response.nil?</string>
View
111 Support/lib/autocomplete.rb
@@ -0,0 +1,111 @@
+support_path = ENV['TM_SUPPORT_PATH']
+require support_path + '/lib/ui.rb'
+
+# TextMate::UI.alert(:warning, "Debug", "#{var}", 'Ok')
+class Autocomplete
+ attr_reader :empty, :brackets, :classes, :file_name, :previous_line, :lines_matching_regex
+
+ def initialize(current_word)
+ case current_word
+ when /\[\]/ : current_word = current_word.gsub(' ','')
+ when /^\s+$/ : current_word = nil
+ else current_word = current_word.gsub(' ','').gsub('[','').gsub(']','')
+ end
+
+ files = Dir["#{ENV['TM_DIRECTORY']}/**/*.j"] + Dir["#{ENV['TM_BUNDLE_SUPPORT']}/source/**/*.j"]
+
+ @empty, @brackets = false
+ @classes = []
+ @lines_matching_regex = []
+
+ previous_line = ENV['TM_LINE_NUMBER'].to_i - 2
+
+ files.each { |file| @classes << file.split('/').last[0..-3] }
+ classes_for_regex = @classes.join('|')
+
+ if @classes.include?(current_word)
+ custom = Dir["#{ENV['TM_DIRECTORY']}/**/*.j"].find {|a| a.include?(current_word+'.j') }.nil? ? false : true
+ @file_name = custom ? "#{ENV['TM_DIRECTORY']}/#{current_word}.j" : "#{ENV['TM_BUNDLE_SUPPORT']}/source/#{current_word}.j"
+ choices = create_choices(@file_name)
+ else
+ data = $stdin.read
+ case current_word
+ when '[]' :
+ @brackets = true
+ when nil :
+ @empty = true
+ data.each_with_index { |l,i| @previous_line = l.scan(/^\s+(\[\w+ )/).first.to_s if i == previous_line }
+ else
+ lines_matching_regex = []
+ data.each_line { |line| lines_matching_regex << line if line =~ (/(#{current_word}\s+=)|(#{current_word}=)/) }
+ if lines_matching_regex.size > 1
+ TextMate::UI.alert(:warning, "Duplicate variable", "Please make sure you use unique variable names", 'Ok')
+ elsif lines_matching_regex.size == 1
+ current_word = lines_matching_regex.first.scan(/(#{classes_for_regex})/).to_s
+ custom = Dir["#{ENV['TM_DIRECTORY']}/**/*.j"].find {|a| a.include?(current_word+'.j') }.nil? ? false : true
+ @file_name = custom ? "#{ENV['TM_DIRECTORY']}/#{current_word}.j" : "#{ENV['TM_BUNDLE_SUPPORT']}/source/#{current_word}.j"
+ choices = create_choices(@file_name, 'instance')
+ else
+ # TextMate::UI.alert(:warning, "Debug", "(#{current_word}) nothing found", 'Ok')
+ end
+ end
+ end
+
+ options = { :extra_chars => '_():', :case_insensitive => false }
+ TextMate::UI.complete(choices, options)
+ end
+
+ def create_choices(file_name, type='klass')
+ data = File.new(file_name).read
+
+ m = data.scan(/.*?(@implementation.*?\@end)/m)
+ if m.length > 0
+ for i in 0...m.length
+ line = m[i][0]
+ m2 = line.scan(/.*?@implementation\s*(\w*).*?/m)
+ if !m2.nil? && !m2[0].nil?
+ className = m2[0][0].strip()
+ if className == file_name.split('/').last[0..-3]
+ @lines_matching_regex << line.scan(/^#{type == 'klass' ? '\+' : '-'}\s*([a-zA-Z\(\)\s:_]*).*?/m)
+ add_parent_methods(line, type)
+ end
+ end
+ end
+
+ choices = []
+ @lines_matching_regex.flatten!.each do |line|
+ choices << {
+ 'display' => line.gsub(/\(\w*\)/, '').gsub(' ','').gsub(/\n+/,''),
+ 'match' => line.gsub(/\(\w*\)/, '').gsub(' ','').gsub(/\n+/,'')
+ }
+ end
+ choices.uniq.sort_by {|c| c['display'].downcase }
+ end
+ end
+
+ def add_parent_methods(line, type)
+ match = line.scan(/.*?@implementation.*?:\s*(\w+).*/m)
+ if !match.nil? && !match[0].nil?
+ parent_class = match[0][0].strip()
+ if @classes.include?(parent_class)
+ custom = Dir["#{ENV['TM_DIRECTORY']}/**/*.j"].find {|a| a.include?(parent_class+'.j') }.nil? ? false : true
+ file = custom ? "#{ENV['TM_DIRECTORY']}/#{parent_class}.j" : "#{ENV['TM_BUNDLE_SUPPORT']}/source/#{parent_class}.j"
+ data = File.new(file).read
+ m = data.scan(/.*?(@implementation.*?\@end)/m)
+ if m.length > 0
+ for i in 0...m.length
+ l = m[i][0]
+ m2 = l.scan(/.*?@implementation\s*(\w*).*?/m)
+ if !m2.nil? && !m2[0].nil?
+ className = m2[0][0].strip()
+ if className == parent_class
+ @lines_matching_regex << l.scan(/^#{type == 'klass' ? '\+' : '-'}\s*([a-zA-Z\(\)\s:_]*).*?/m)
+ add_parent_methods(l, type)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
View
77 Support/lib/delegates.rb
@@ -7,13 +7,78 @@ def self.delegates
{
'class' => 'CPTextField',
'delegates' => [
- {'delegateName' => 'controlTextDidBeginEditing'},
- {'delegateName' => 'controlTextDidChange'},
- {'delegateName' => 'controlTextDidEndEditing'},
- {'delegateName' => 'controlTextDidFocus'},
- {'delegateName' => 'controlTextDidBlur'}]
- }
+ {'delegateName' => 'controlTextDidBeginEditing:'},
+ {'delegateName' => 'controlTextDidChange:'},
+ {'delegateName' => 'controlTextDidEndEditing:'},
+ {'delegateName' => 'controlTextDidFocus:'},
+ {'delegateName' => 'controlTextDidBlur:'}
+ ]},
+ {
+ 'class' => 'CPSecureTextField',
+ 'delegates' => [
+ {'delegateName' => 'controlTextDidBeginEditing:'},
+ {'delegateName' => 'controlTextDidChange:'},
+ {'delegateName' => 'controlTextDidEndEditing:'},
+ {'delegateName' => 'controlTextDidFocus:'},
+ {'delegateName' => 'controlTextDidBlur:'}
+ ]},
+ {
+ 'class' => 'CPSearchField',
+ 'delegates' => [
+ {'delegateName' => 'controlTextDidBeginEditing:'},
+ {'delegateName' => 'controlTextDidChange:'},
+ {'delegateName' => 'controlTextDidEndEditing:'},
+ {'delegateName' => 'controlTextDidFocus:'},
+ {'delegateName' => 'controlTextDidBlur:'}
+ ]},
+ {
+ 'class' => 'CPTableView',
+ 'delegates' => [
+ {'delegateName' => 'tableViewColumnDidMove:'},
+ {'delegateName' => 'tableViewColumnDidResize:'},
+ {'delegateName' => 'tableViewSelectionDidChange:'},
+ {'delegateName' => 'tableViewSelectionIsChanging:'},
+ {'delegateName' => 'selectionShouldChangeInTableView:'},
+ {'delegateName' => 'tableView:dataViewForTableColumn:row:'},
+ {'delegateName' => 'tableView:didClickTableColumn:'},
+ {'delegateName' => 'tableView:didDragTableColumn:'},
+ {'delegateName' => 'tableView:heightOfRow:'},
+ {'delegateName' => 'tableView:isGroupRow:'},
+ {'delegateName' => 'tableView:mouseDownInHeaderOfTableColumn:'},
+ {'delegateName' => 'tableView:nextTypeSelectMatchFromRow:toRow:forString:'},
+ {'delegateName' => 'tableView:selectionIndexesForProposedSelection:'},
+ {'delegateName' => 'tableView:shouldEditTableColumn:row:'},
+ {'delegateName' => 'tableView:shouldSelectRow:'},
+ {'delegateName' => 'tableView:shouldSelectTableColumn:'},
+ {'delegateName' => 'tableView:shouldShowViewExpansionForTableColumn:row:'},
+ {'delegateName' => 'tableView:shouldTrackView:forTableColumn:row:'},
+ {'delegateName' => 'tableView:shouldTypeSelectForEvent:withCurrentSearchString:'},
+ {'delegateName' => 'tableView:toolTipForView:rect:tableColumn:row:mouseLocation:'},
+ {'delegateName' => 'tableView:typeSelectStringForTableColumn:row:'},
+ {'delegateName' => 'tableView:willDisplayView:forTableColumn:row:'}
+ ]},
+ {
+ 'class' => 'CPOutlineView',
+ 'delegates' => [
+ {'delegateName' => 'outlineViewColumnDidMove:'},
+ {'delegateName' => 'outlineViewColumnDidResize:'},
+ {'delegateName' => 'outlineViewSelectionDidChange:'},
+ {'delegateName' => 'outlineViewSelectionIsChanging:'}
+ ]},
]
}
end
end
+
+# Template
+=begin
+{
+'class' => '',
+'delegates' => [
+ {'delegateName' => ''},
+ {'delegateName' => ''},
+ {'delegateName' => ''},
+ {'delegateName' => ''},
+ {'delegateName' => ''},
+]},
+=end
View
30 Support/nib/Cappuccino.nib/designable.nib
@@ -8,7 +8,7 @@
<string key="IBDocument.HIToolboxVersion">353.00</string>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
- <integer value="2"/>
+ <integer value="1" id="9"/>
</object>
<object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -37,7 +37,7 @@
<object class="NSWindowTemplate" id="801351721">
<int key="NSWindowStyleMask">8211</int>
<int key="NSWindowBacking">2</int>
- <string key="NSWindowRect">{{436, 423}, {550, 319}}</string>
+ <string key="NSWindowRect">{{436, 423}, {796, 319}}</string>
<int key="NSWTFlags">611844096</int>
<string key="NSWindowTitle">Cappuccino Delegates</string>
<string key="NSWindowClass">NSPanel</string>
@@ -269,26 +269,26 @@
<object class="NSTableView" id="1024752599">
<reference key="NSNextResponder" ref="935849797"/>
<int key="NSvFlags">256</int>
- <string key="NSFrameSize">{223, 209}</string>
+ <string key="NSFrameSize">{469, 209}</string>
<reference key="NSSuperview" ref="935849797"/>
<bool key="NSEnabled">YES</bool>
<object class="NSTableHeaderView" key="NSHeaderView" id="536906494">
<reference key="NSNextResponder" ref="207542722"/>
<int key="NSvFlags">256</int>
- <string key="NSFrameSize">{223, 17}</string>
+ <string key="NSFrameSize">{469, 17}</string>
<reference key="NSSuperview" ref="207542722"/>
<reference key="NSTableView" ref="1024752599"/>
</object>
<object class="_NSCornerView" key="NSCornerView" id="912708374">
<reference key="NSNextResponder" ref="689388565"/>
<int key="NSvFlags">256</int>
- <string key="NSFrame">{{224, 0}, {16, 17}}</string>
+ <string key="NSFrame">{{470, 0}, {16, 17}}</string>
<reference key="NSSuperview" ref="689388565"/>
</object>
<object class="NSMutableArray" key="NSTableColumns">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSTableColumn" id="493447689">
- <double key="NSWidth">2.200000e+02</double>
+ <double key="NSWidth">4.660000e+02</double>
<double key="NSMinWidth">4.000000e+01</double>
<double key="NSMaxWidth">1.000000e+03</double>
<object class="NSTableHeaderCell" key="NSHeaderCell">
@@ -336,7 +336,7 @@
<bool key="NSAllowsTypeSelect">YES</bool>
</object>
</object>
- <string key="NSFrame">{{1, 17}, {223, 209}}</string>
+ <string key="NSFrame">{{1, 17}, {469, 209}}</string>
<reference key="NSSuperview" ref="689388565"/>
<reference key="NSNextKeyView" ref="1024752599"/>
<reference key="NSDocView" ref="1024752599"/>
@@ -346,7 +346,7 @@
<object class="NSScroller" id="117245661">
<reference key="NSNextResponder" ref="689388565"/>
<int key="NSvFlags">256</int>
- <string key="NSFrame">{{224, 17}, {15, 209}}</string>
+ <string key="NSFrame">{{470, 17}, {15, 209}}</string>
<reference key="NSSuperview" ref="689388565"/>
<reference key="NSTarget" ref="689388565"/>
<string key="NSAction">_doScroller:</string>
@@ -356,7 +356,7 @@
<object class="NSScroller" id="374244266">
<reference key="NSNextResponder" ref="689388565"/>
<int key="NSvFlags">256</int>
- <string key="NSFrame">{{1, 226}, {223, 15}}</string>
+ <string key="NSFrame">{{1, 226}, {469, 15}}</string>
<reference key="NSSuperview" ref="689388565"/>
<int key="NSsFlags">1</int>
<reference key="NSTarget" ref="689388565"/>
@@ -370,7 +370,7 @@
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="536906494"/>
</object>
- <string key="NSFrame">{{1, 0}, {223, 17}}</string>
+ <string key="NSFrame">{{1, 0}, {469, 17}}</string>
<reference key="NSSuperview" ref="689388565"/>
<reference key="NSNextKeyView" ref="536906494"/>
<reference key="NSDocView" ref="536906494"/>
@@ -379,7 +379,7 @@
</object>
<reference ref="912708374"/>
</object>
- <string key="NSFrame">{{290, 20}, {240, 242}}</string>
+ <string key="NSFrame">{{290, 20}, {486, 242}}</string>
<reference key="NSSuperview" ref="1021757474"/>
<reference key="NSNextKeyView" ref="935849797"/>
<int key="NSsFlags">50</int>
@@ -438,7 +438,7 @@
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>cancel</string>
- <integer value="1"/>
+ <reference ref="9"/>
</object>
</object>
</object>
@@ -456,7 +456,7 @@
</object>
</object>
</object>
- <string key="NSFrameSize">{550, 319}</string>
+ <string key="NSFrameSize">{796, 319}</string>
<reference key="NSSuperview"/>
</object>
<string key="NSScreenRect">{{0, 0}, {1440, 878}}</string>
@@ -943,9 +943,9 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{182, 85}, {550, 319}}</string>
+ <string>{{182, 85}, {796, 319}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{182, 85}, {550, 319}}</string>
+ <string>{{182, 85}, {796, 319}}</string>
<reference ref="5"/>
<reference ref="6"/>
<string>{541, 265}</string>
View
BIN Support/nib/Cappuccino.nib/keyedobjects.nib
Binary file not shown.
View
257 Support/source/CAAnimation.j
@@ -0,0 +1,257 @@
+/*
+ * 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 <Foundation/CPObject.j>
+@import <Foundation/CPString.j>
+
+@import "CAMediaTimingFunction.j"
+
+/*
+ This is an animation class.
+*/
+@implementation CAAnimation : CPObject
+{
+ BOOL _isRemovedOnCompletion;
+ id _delegate;
+}
+
+/*!
+ Creates a new CAAnimation instance
+ @return a new CAAnimation instance
+*/
++ (id)animation
+{
+ return [[self alloc] init];
+}
+
+- (id)init
+{
+ self = [super init];
+
+ if (self)
+ _isRemovedOnCompletion = YES;
+
+ return self;
+}
+
+/*!
+ Returns \c YES
+ @return \c YES
+*/
+- (void)shouldArchiveValueForKey:(CPString)aKey
+{
+ return YES;
+}
+
+/*!
+ Returns \c nil
+ @return \c nil
+*/
++ (id)defaultValueForKey:(CPString)aKey
+{
+ return nil;
+}
+
+/*!
+ Specifies whether this animation should be removed after it has completed.
+ @param \c YES means the animation should be removed
+*/
+- (void)setRemovedOnCompletion:(BOOL)isRemovedOnCompletion
+{
+ _isRemovedOnCompletion = isRemovedOnCompletion;
+}
+
+/*!
+ Returns \c YES if the animation is removed after completion
+*/
+- (BOOL)removedOnCompletion
+{
+ return _isRemovedOnCompletion;
+}
+
+/*!
+ Returns \c YES if the animation is removed after completion
+*/
+- (BOOL)isRemovedOnCompletion
+{
+ return _isRemovedOnCompletion;
+}
+
+/*!
+ Returns the animation's timing function. If \c nil, then it has a linear pacing.
+*/
+- (CAMediaTimingFunction)timingFunction
+{
+ // Linear Pacing
+ return nil;
+}
+
+/*!
+ Sets the animation delegate
+ @param aDelegate the new delegate
+*/
+- (void)setDelegate:(id)aDelegate
+{
+ _delegate = aDelegate;
+}
+
+/*!
+ Returns the animation's delegate
+*/
+- (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
+
+/*!
+ A CABasicAnimation is a simple animation that moves a
+ CALayer from one point to another over a specified
+ period of time.
+*/
+@implementation CABasicAnimation : CAPropertyAnimation
+{
+ id _fromValue;
+ id _toValue;
+ id _byValue;
+}
+
+/*!
+ Sets the starting position for the animation.
+ @param aValue the animation starting position
+*/
+- (void)setFromValue:(id)aValue
+{
+ _fromValue = aValue;
+}
+
+/*!
+ Returns the animation's starting position.
+*/
+- (id)fromValue
+{
+ return _fromValue;
+}
+
+/*!
+ Sets the ending position for the animation.
+ @param aValue the animation ending position
+*/
+- (void)setToValue:(id)aValue
+{
+ _toValue = aValue;
+}
+
+/*!
+ Returns the animation's ending position.
+*/
+- (id)toValue
+{
+ return _toValue;
+}
+
+/*!
+ Sets the optional byValue for animation interpolation.
+ @param aValue the byValue
+*/
+- (void)setByValue:(id)aValue
+{
+ _byValue = aValue;
+}
+
+/*!
+ Returns the animation's byValue.
+*/
+- (id)byValue
+{
+ return _byValue;
+}
+
+@end
View
73 Support/source/CABackingStore.j
@@ -0,0 +1,73 @@
+/*
+ * 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)
+{
+}
+
+}
View
50 Support/source/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 = "<object width = \"100%\" height = \"100%\"><param name = \"movie\" value = \"" +
+ aFlashMovie._fileName +
+ "\"></param><param name = \"wmode\" value = \"transparent\"></param><embed src = \"" +
+ aFlashMovie._fileName + "\" type = \"application/x-shockwave-flash\" wmode = \"transparent\" width = \"100%\" height = \"100%\"></embed></object>";
+}
+
+- (CPFlashMovie)flashMovie
+{
+ return _flashMovie;
+}
+
+@end
View
1,203 Support/source/CALayer.j
@@ -0,0 +1,1203 @@
+/*
+ * 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 <Foundation/CPObject.j>
+
+@import <AppKit/CABackingStore.j>
+
+@import <AppKit/CGContext.j>
+@import <AppKit/CGGeometry.j>
+
+#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;
+
+/*! @class CALayer
+
+ A CALayer is similar to a CPView, but with the ability
+ to have a transform applied to it.
+
+ @delegate -(void)drawLayer:(CALayer)layer inContext:(CGContextRef)ctx;
+ If the delegate implements this method, the CALayer will
+ call this in place of its \c -drawInContext:.
+ @param layer the layer to draw for
+ @param ctx the context to draw on
+
+ @delegate -(void)displayLayer:(CALayer)layer;
+ The delegate can override the layer's \c -display method
+ by implementing this method.
+*/
+@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;
+
+ // Modifying the Delegate
+
+ id _delegate;
+
+ BOOL _delegateRespondsToDisplayLayerSelector;
+ BOOL _delegateRespondsToDrawLayerInContextSelector;
+
+ // DOM Implementation
+
+ DOMElement _DOMElement;
+ DOMElement _DOMContentsElement;
+ id _contents;
+ CGContext _context;
+ CPView _owningView;
+
+ CGAffineTransform _transformToLayer;
+ CGAffineTransform _transformFromLayer;
+}
+
+/*!
+ Returns a new animation layer.
+*/
++ (CALayer)layer
+{
+ return [[[self class] alloc] init];
+}
+
+/*!
+ Initializes the animation layer.
+*/
+- (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
+/*!
+ Sets the bounds (origin and size) of the rectangle.
+ @param aBounds the new bounds for the layer
+*/
+- (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);
+}
+
+/*!
+ Returns the layer's bound.
+*/
+- (CGRect)bounds
+{
+ return _bounds;
+}
+
+/*!
+ Sets the layer's position.
+ @param aPosition the layer's new position
+*/
+- (void)setPosition:(CGPoint)aPosition
+{
+ if (CGPointEqualToPoint(_position, aPosition))
+ return;
+
+ _position = _CGPointMakeCopy(aPosition);
+
+ _CALayerRecalculateGeometry(self, CALayerGeometryPositionMask);
+}
+
+/*!
+ Returns the layer's position
+*/
+- (CGPoint)position
+{
+ return _position;
+}
+
+/*!
+ Sets the layer's z-ordering.
+ @param aZPosition the layer's new z-ordering
+*/
+- (void)setZPosition:(int)aZPosition
+{
+ if (_zPosition == aZPosition)
+ return;
+
+ _zPosition = aZPosition;
+
+ [self registerRunLoopUpdateWithMask:CALayerZPositionUpdateMask];
+}
+
+/*!
+ Sets the layer's anchor point. The default point is [0.5, 0.5].
+ @param anAnchorPoint the layer's new anchor point
+*/
+- (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);
+}
+
+/*!
+ Returns the layer's anchor point.
+*/
+- (CGPoint)anchorPoint
+{
+ return _anchorPoint;
+}
+
+/*!
+ Sets the affine transform applied to this layer.
+ @param anAffineTransform the new affine transform
+*/
+- (void)setAffineTransform:(CGAffineTransform)anAffineTransform
+{
+ if (CGAffineTransformEqualToTransform(_affineTransform, anAffineTransform))
+ return;
+
+ _affineTransform = _CGAffineTransformMakeCopy(anAffineTransform);
+
+ _CALayerRecalculateGeometry(self, CALayerGeometryAffineTransformMask);
+}
+
+/*!
+ Returns the layer's affine transform.
+*/
+- (CGAffineTransform)affineTransform
+{
+ return _affineTransform;
+}
+
+/*!
+ Sets the affine transform that gets applied to all the sublayers.
+ @param anAffineTransform the transform to apply to sublayers
+*/
+- (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);
+ }
+}
+
+/*!
+ Returns the affine transform applied to the sublayers.
+*/
+- (CGAffineTransform)sublayerTransform
+{
+ return _sublayerTransform;
+}
+
+/*
+ Private
+ @ignore
+*/
+- (CGAffineTransform)transformToLayer
+{
+ return _transformToLayer;
+}
+
+/*!
+ Sets the frame of the layer. The frame defines a bounding
+ rectangle in the superlayer's coordinate system.
+ @param aFrame the new frame rectangle
+*/
+- (void)setFrame:(CGRect)aFrame
+{
+ alert("FIXME IMPLEMENT");
+}
+
+/*!
+ Returns the layer's frame.
+
+ 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.
+ @return the backing store frame
+*/
+- (CGRect)backingStoreFrame
+{
+ return _backingStoreFrame;
+}
+
+/*!
+ Sets the frame's backing store.
+ @param aFrame the new backing store.
+*/
+- (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
+/*!
+ Returns the CGImage contents of this layer.
+ The default contents are \c nil.
+*/
+- (CGImage)contents
+{
+ return _contents;
+}
+
+/*!
+ Sets the image contents of this layer.
+ @param contents the image to display
+*/
+- (void)setContents:(CGImage)contents
+{
+ if (_contents == contents)
+ return;
+
+ _contents = contents;
+
+ [self composite];
+}
+
+/*
+ Composites this layer onto the super layer, and draws its contents as well.
+ @ignore
+*/
+- (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);
+}
+
+/*!
+ Displays the contents of this layer.
+*/
+- (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 [_delegate 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];
+}
+
+/*!
+ Draws this layer's contents into the specified context.
+ @param aContext the context to draw the layer into
+*/
+- (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
+/*!
+ Returns the opacity of the layer. The value is between
+ \c 0.0 (transparent) and \c 1.0 (opaque).
+*/
+- (float)opacity
+{
+ return _opacity;
+}
+
+/*!
+ Sets the opacity for the layer.
+ @param anOpacity the new opacity (between \c 0.0 (transparent) and \c 1.0 (opaque)).
+*/
+- (void)setOpacity:(float)anOpacity
+{
+ if (_opacity == anOpacity)
+ return;
+
+ _opacity = anOpacity;
+
+ _DOMElement.style.opacity = anOpacity;
+ _DOMElement.style.filter = "alpha(opacity=" + anOpacity * 100 + ")";
+}
+
+/*!
+ Sets whether the layer is hidden.
+ @param isHidden \c YES means the layer will be hidden. \c NO means the layer will be visible.
+*/
+- (void)setHidden:(BOOL)isHidden
+{
+ _isHidden = isHidden;
+ _DOMElement.style.display = isHidden ? "none" : "block";
+}
+
+/*!
+ Returns \c YES if the layer is hidden.
+*/
+- (BOOL)hidden
+{
+ return _isHidden;
+}
+
+/*!
+ Returns \c YES if the layer is hidden.
+*/
+- (BOOL)isHidden
+{
+ return _isHidden;
+}
+
+/*!
+ Sets whether content that goes lies outside the bounds is hidden or visible.
+ @param masksToBounds \c YES hides the excess content. \c NO makes it visible.
+*/
+- (void)setMasksToBounds:(BOOL)masksToBounds
+{
+ if (_masksToBounds == masksToBounds)
+ return;
+
+ _masksToBounds = masksToBounds;
+ _DOMElement.style.overflow = _masksToBounds ? "hidden" : "visible";
+}
+
+/*!
+ Sets the layer's background color.
+ @param aColor the new background color
+*/
+- (void)setBackgroundColor:(CPColor)aColor
+{
+ _backgroundColor = aColor;
+
+ [self setNeedsDisplay];
+}
+
+/*!
+ Returns the layer's background color.
+*/
+- (CPColor)backgroundColor
+{
+ return _backgroundColor;
+}
+
+// Managing Layer Hierarchy
+/*!
+ Returns an array of the receiver's sublayers.
+*/
+- (CPArray)sublayers
+{
+ return _sublayers;
+}
+
+/*!
+ Returns the receiver's superlayer.
+*/
+- (CALayer)superlayer
+{
+ return _superlayer;
+}
+
+#define ADJUST_CONTENTS_ZINDEX(aLayer)\
+if (_DOMContentsElement && aLayer._zPosition > _DOMContentsElement.style.zIndex)\
+ _DOMContentsElement.style.zIndex -= 100.0;\
+
+/*!
+ Adds the specified layer as a sublayer of the receiver.
+*/
+- (void)addSublayer:(CALayer)aLayer
+{
+ [self insertSublayer:aLayer atIndex:_sublayers.length];
+ return;
+ ADJUST_CONTENTS_ZINDEX(aLayer);
+
+ [_sublayers addObject:aLayer];
+ _DOMElement.appendChild(DOM(aLayer));
+}
+
+/*!
+ Removes the receiver from its superlayer.
+*/
+- (void)removeFromSuperlayer
+{
+ if (_owningView)
+ [_owningView setLayer:nil];
+
+ if (!_superlayer)
+ return;
+
+ _superlayer._DOMElement.removeChild(_DOMElement);
+ [_superlayer._sublayers removeObject:self];
+
+ _superlayer = nil;
+}
+
+/*!
+ Inserts the specified layer as a sublayer into the specified index.
+ @param aLayer the layer to insert
+ @param anIndex the index to insert the layer at
+*/
+- (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);
+}
+
+/*!
+ Inserts a layer below another layer.
+ @param aLayer the layer to insert
+ @param aSublayer the layer to insert below
+ @throws CALayerNotFoundException if \c aSublayer is not in the array of sublayers
+*/
+- (void)insertSublayer:(CALayer)aLayer below:(CALayer)aSublayer
+{
+ var index = aSublayer ? [_sublayers indexOfObjectIdenticalTo:aSublayer] : 0;
+
+ [self insertSublayer:aLayer atIndex:index == CPNotFound ? _sublayers.length : index];
+}
+
+/*!
+ Inserts a layer above another layer.
+ @param aLayer the layer to insert
+ @param aSublayer the layer to insert above
+ @throws CALayerNotFoundException if \c aSublayer is not in the array of sublayers
+*/
+- (void)insertSublayer:(CALayer)aLayer above:(CALayer)aSublayer
+{
+ var index = aSublayer ? [_sublayers indexOfObjectIdenticalTo:aSublayer] : _sublayers.length;
+ if (index == CPNotFound)
+ [CPException raise:"CALayerNotFoundException" reason:"aSublayer is not a sublayer of this layer"];
+
+ [_sublayers insertObject:aLayer atIndex:index == CPNotFound ? _sublayers.length : index + 1];
+}
+
+/*!
+ Replaces a sublayer.
+ @param aSublayer the layer to insert
+ @param aLayer the layer to replace
+*/
+- (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
+/*
+ Updates the layers on screen.
+ @ignore
+*/
++ (void)runLoopUpdateLayers
+{if (window.oops) {alert(window.latest); objj_debug_print_backtrace();}
+ window.loop = true;
+ for (UID in CALayerRegisteredRunLoopUpdates)
+ {
+ var layer = CALayerRegisteredRunLoopUpdates[UID],
+ 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;
+}
+
+/*
+ @ignore
+*/
+- (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 UID]] = self;
+}
+
+/*
+ @ignore
+*/
+- (void)setNeedsComposite
+{
+ [self registerRunLoopUpdateWithMask:CALayerCompositeUpdateMask];
+}
+
+/*!
+ Marks the layer as needing to be redrawn.
+*/
+- (void)setNeedsDisplay
+{
+ [self registerRunLoopUpdateWithMask:CALayerDisplayUpdateMask];
+}
+
+/*!
+ Sets whether the layer needs to be redrawn when its bounds are changed.
+ @param needsDisplayOnBoundsChange \c YES means the display is redraw on a bounds change.
+*/
+- (void)setNeedsDisplayOnBoundsChange:(BOOL)needsDisplayOnBoundsChange
+{
+ _needsDisplayOnBoundsChange = needsDisplayOnBoundsChange;
+}
+
+/*!
+ Returns \c YES if the display should be redrawn on a bounds change.
+*/
+- (BOOL)needsDisplayOnBoundsChange
+{
+ return _needsDisplayOnBoundsChange;
+}
+
+/*!
+ Marks the specified rectange as needing to be redrawn.
+ @param aRect the area that needs to be redrawn.
+*/
+- (void)setNeedsDisplayInRect:(CGRect)aRect
+{
+ _dirtyRect = aRect;
+ [self display];
+}
+
+// Mapping Between Coordinate and Time Spaces
+/*!
+ Converts the point from the specified layer's coordinate system into the receiver's coordinate system.
+ @param aPoint the point to convert
+ @param aLayer the layer coordinate system to convert from
+ @return the converted point
+*/
+- (CGPoint)convertPoint:(CGPoint)aPoint fromLayer:(CALayer)aLayer
+{
+ return CGPointApplyAffineTransform(aPoint, _CALayerGetTransform(aLayer, self));
+}
+
+/*!
+ Converts the point from the receiver's coordinate system to the specified layer's coordinate system.
+ @param aPoint the point to convert
+ @param aLayer the layer coordinate system to convert to
+ @return the converted point
+*/
+- (CGPoint)convertPoint:(CGPoint)aPoint toLayer:(CALayer)aLayer
+{
+ return CGPointApplyAffineTransform(aPoint, _CALayerGetTransform(self, aLayer));
+}
+
+/*!
+ Converts the rectangle from the specified layer's coordinate system to the receiver's coordinate system.
+ @param aRect the rectangle to convert
+ @param aLayer the layer coordinate system to convert from
+ @return the converted rectangle
+*/
+- (CGRect)convertRect:(CGRect)aRect fromLayer:(CALayer)aLayer
+{
+ return CGRectApplyAffineTransform(aRect, _CALayerGetTransform(aLayer, self));
+}
+
+/*!
+ Converts the rectangle from the receier's coordinate system to the specified layer's coordinate system.
+ @param aRect the rectange to convert
+ @param aLayer the layer coordinate system to convert to
+ @return the converted rectangle
+*/
+- (CGRect)convertRect:(CGRect)aRect toLayer:(CALayer)aLayer
+{
+ return CGRectApplyAffineTransform(aRect, _CALayerGetTransform(self, aLayer));
+}
+
+// Hit Testing
+/*!
+ Returns \c YES if the layer contains the point.
+ @param aPoint the point to test
+*/
+- (BOOL)containsPoint:(CGPoint)aPoint
+{
+ return _CGRectContainsPoint(_bounds, aPoint);
+}
+
+/*!
+ Returns the farthest descendant of this layer that contains the specified point.
+ @param aPoint the point to test
+ @return the containing layer or \c nil if there was no hit.
+*/
+- (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
+/*!
+ Sets the delegate for this layer.
+ @param aDelegate 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];
+}
+
+/*!
+ Returns the layer's delegate
+*/
+- (id)delegate
+{
+ return _delegate;
+}
+
+/* @ignore */
+- (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);
+}
+
+/* @ignore */
+- (void)_owningViewBoundsChanged
+{
+ _bounds.size = CGSizeMakeCopy([_owningView bounds].size);
+ _position = CGPointMake(_CGRectGetWidth(_bounds) * _anchorPoint.x, _CGRectGetHeight(_bounds) * _anchorPoint.y);
+
+ _CALayerRecalculateGeometry(self, CALayerGeometryPositionMask | CALayerGeometryBoundsMask);
+}
+
+/* @ignore */
+- (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;
+}
View
102 Support/source/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 <Foundation/CPObject.j>
+@import <Foundation/CPDictionary.j>
+@import <Foundation/CPString.j>
+
+
+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[1] = 1.0;
+ }
+}
+
+@end
View
152 Support/source/CGAffineTransform.j
@@ -0,0 +1,152 @@
+/*
+ * 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: !!!!
+ @return void
+ @group CGAffineTransform
+*/
+function CGAffineTransformCreateCopy(aTransform)
+{
+ return _CGAffineTransformMakeCopy(aTransform);
+}
+
+/*!
+ Returns a transform that rotates a coordinate system.
+ @param anAngle the amount in radians for the transform
+ to rotate a coordinate system
+ @return CGAffineTransform the transform with a specified
+ rotation
+ @group CGAffineTransform
+*/
+function CGAffineTransformMakeRotation(anAngle)
+{
+ var sin = SIN(anAngle),
+ cos = COS(anAngle);
+
+ return _CGAffineTransformMake(cos, sin, -sin, cos, 0.0, 0.0);
+}
+
+/*!
+ Rotates a transform.
+ @param aTransform the transform to rotate
+ @param anAngle the amount to rotate in radians
+ @return void
+ @group CGAffineTransform
+*/
+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
+ };
+}
+
+/*!
+ Inverts a transform.
+ @param aTransform the transform to invert
+ @return CGAffineTransform an inverted transform
+ @group CGAffineTransform
+*/
+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)
+ };
+}
+
+/*!
+ Applies a transform to the rectangle's points. The transformed rectangle
+ will be the smallest box that contains the transformed points.
+ @param aRect the rectangle to transform
+ @param anAffineTransform the transform to apply
+ @return CGRect the new transformed rectangle
+ @group CGAffineTransform
+*/
+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));
+}
+
+/*!
+ Creates and returns a string representation of an affine transform.
+ @param anAffineTransform the transform to represent as a string
+ @return CPString a string describing the transform
+ @group CGAffineTransform
+*/
+function CPStringFromCGAffineTransform(anAffineTransform)
+{
+ return '{' + anAffineTransform.a + ", " + anAffineTransform.b + ", " + anAffineTransform.c + ", " + anAffineTransform.d + ", " + anAffineTransform.tx + ", " + anAffineTransform.ty + '}';
+}
View
288 Support/source/CGColor.j
@@ -0,0 +1,288 @@
+/*
+ * 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;
+