├── CHANGELOG.md ├── Examples ├── AtkDragAndDrop_Examples │ ├── en.lproj │ │ └── InfoPlist.strings │ ├── AtkSampleViewController.h │ ├── Sample01 │ │ ├── AtkSampleOneViewController.h │ │ ├── AtkSampleOneDropZoneView.h │ │ ├── AtkSampleOneDragSourceView.h │ │ ├── AtkSampleOneDropZoneScrollView.h │ │ ├── AtkSampleOneDragSourceView.m │ │ ├── AtkSampleOneViewController.m │ │ ├── AtkSampleOneDropZoneScrollView.m │ │ ├── AtkSampleOneDropZoneView.m │ │ └── AtkSampleOneViewController.xib │ ├── Sample02 │ │ ├── AtkSampleTwoViewController.h │ │ ├── AtkSampleTwoDropZoneWrapper.h │ │ ├── AtkSampleTwoDragSourceWrapper.h │ │ ├── AtkSampleTwoDropZoneScrollViewWrapper.h │ │ ├── AtkSampleTwoDragSourceWrapper.m │ │ ├── AtkSampleTwoDropZoneScrollViewWrapper.m │ │ ├── AtkSampleTwoDropZoneWrapper.m │ │ ├── AtkSampleTwoViewController.m │ │ └── AtkSampleTwoViewController.xib │ ├── AtkAppDelegate.h │ ├── AtkDragAndDrop_Examples-Prefix.pch │ ├── main.m │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── LaunchImage.launchimage │ │ │ └── Contents.json │ ├── AtkDragAndDrop_Examples-Info.plist │ ├── AtkSampleViewController.m │ ├── AtkAppDelegate.m │ └── AtkSampleViewController.xib └── AtkDragAndDrop_Examples.xcodeproj │ ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── AtkDragAndDrop_Examples.xccheckout │ └── project.pbxproj ├── .gitignore ├── Classes ├── UIView+AtkImage.h ├── AtkDragAndDrop.h ├── AtkDefaultDragAndDropManagerDelegate.h ├── AtkDropZoneWrapper.h ├── AtkDropZoneWrapper.m ├── UIView+AtkDragAndDrop.h ├── UIView+AtkImage.m ├── AtkDragSourceProtocol.h ├── UIScrollView+AtkDragAndDrop.h ├── UIView+AtkDragAndDrop.m ├── AtkDragAndDropLifecycleProtocol.h ├── AtkDropZoneProtocol.h ├── AtkDefaultDragAndDropManagerDelegate.m ├── AtkDragAndDropManager.h ├── UIScrollView+AtkDragAndDrop.m └── AtkDragAndDropManager.m ├── LICENSE ├── AtkDragAndDrop.podspec ├── Rakefile └── README.md /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # AtkDragAndDrop CHANGELOG 2 | 3 | ## 0.1.0 4 | 5 | Initial release. 6 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | DerivedData 16 | .idea/ 17 | *.hmap 18 | 19 | #CocoaPods 20 | Pods 21 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/AtkSampleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AtkSampleViewController.h 3 | // Atkdrogen_DragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/20/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AtkSampleViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Sample01/AtkSampleOneViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AtkSampleOneViewController.h 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/15/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AtkSampleOneViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Sample02/AtkSampleTwoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AtkSampleTwoViewController.h 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/15/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AtkSampleTwoViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Classes/UIView+AtkImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Image.h 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/17/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIView (Image) 12 | 13 | /** 14 | * Creates and autoreleased image from self. 15 | */ 16 | - (UIImage*)imageFromView; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/AtkDragAndDrop.h: -------------------------------------------------------------------------------- 1 | // 2 | // AtkDragAndDrop.h 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/17/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import "AtkDragAndDropManager.h" 10 | #import "AtkDragSourceProtocol.h" 11 | #import "AtkDropZoneProtocol.h" 12 | #import "UIView+AtkDragAndDrop.h" 13 | #import "UIScrollView+AtkDragAndDrop.h" -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/AtkAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AtkAppDelegate.h 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/15/14. 6 | // Copyright (c) 2014 Rick Boykin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AtkAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Sample01/AtkSampleOneDropZoneView.h: -------------------------------------------------------------------------------- 1 | // 2 | // AtkDropZoneView.h 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/17/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AtkDragAndDrop.h" 11 | 12 | @interface AtkSampleOneDropZoneView : UIView 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Sample01/AtkSampleOneDragSourceView.h: -------------------------------------------------------------------------------- 1 | // 2 | // AtkSampleOneDragSourceView.h 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/17/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AtkDragAndDrop.h" 11 | 12 | @interface AtkSampleOneDragSourceView : UIView 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Sample01/AtkSampleOneDropZoneScrollView.h: -------------------------------------------------------------------------------- 1 | // 2 | // AtkSampleOneDropZoneScrollView.h 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/17/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AtkDragAndDrop.h" 11 | 12 | @interface AtkSampleOneDropZoneScrollView : UIScrollView 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Classes/AtkDefaultDragAndDropManagerDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AtkDefaultDragAndDropManagerDelegate.h 3 | // Atkdrogen_DragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/20/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AtkDragAndDropManager.h" 11 | 12 | @interface AtkDefaultDragAndDropManagerDelegate : NSObject 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/AtkDragAndDrop_Examples-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_3_0 10 | #warning "This project uses features only available in iOS SDK 3.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // AtkDragAndDrop_Examples 4 | // 5 | // Created by Rick Boykin on 1/28/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AtkAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AtkAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Sample02/AtkSampleTwoDropZoneWrapper.h: -------------------------------------------------------------------------------- 1 | // 2 | // AtkSampleTwoDropZoneWrapper.h 3 | // Atkdrogen_DragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/21/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AtkDragAndDrop.h" 11 | 12 | @interface AtkSampleTwoDropZoneWrapper : NSObject 13 | 14 | @property (nonatomic, strong) UIView *view; 15 | 16 | - (id)initWithView:(UIView *)view; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Sample02/AtkSampleTwoDragSourceWrapper.h: -------------------------------------------------------------------------------- 1 | // 2 | // AtkSampleTwoDragSourceWrapper.h 3 | // Atkdrogen_DragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/21/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AtkDragAndDrop.h" 11 | 12 | @interface AtkSampleTwoDragSourceWrapper : NSObject 13 | 14 | @property (nonatomic, strong) UIView *view; 15 | 16 | - (id)initWithView:(UIView *)view; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Sample02/AtkSampleTwoDropZoneScrollViewWrapper.h: -------------------------------------------------------------------------------- 1 | // 2 | // AtkSampleTwoDropZoneScrollViewWrapper.h 3 | // Atkdrogen_DragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/21/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AtkDragAndDrop.h" 11 | 12 | @interface AtkSampleTwoDropZoneScrollViewWrapper : NSObject 13 | 14 | @property (nonatomic, strong) UIScrollView *view; 15 | 16 | - (id)initWithScrollView:(UIScrollView *)view; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/AtkDropZoneWrapper.h: -------------------------------------------------------------------------------- 1 | // 2 | // AtkDropZoneWrapper.h 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/18/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AtkDropZoneProtocol.h" 11 | 12 | @interface AtkDropZoneWrapper : NSObject 13 | 14 | @property (nonatomic, strong) id dropZone; 15 | @property (nonatomic, assign) BOOL isActive; 16 | @property (nonatomic, assign) BOOL isInterested; 17 | 18 | - (id)initWithDropZone:(id)dropZone interested:(BOOL)interested; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Classes/AtkDropZoneWrapper.m: -------------------------------------------------------------------------------- 1 | // 2 | // AtkDropZoneWrapper.m 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/18/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import "AtkDropZoneWrapper.h" 10 | 11 | @implementation AtkDropZoneWrapper 12 | 13 | - (id)initWithDropZone:(id)dropZone interested:(BOOL)interested; 14 | { 15 | if((self = [super init])) 16 | { 17 | self.dropZone = dropZone; 18 | self.isActive = NO; 19 | self.isInterested = interested; 20 | } 21 | 22 | return self; 23 | } 24 | 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Sample01/AtkSampleOneDragSourceView.m: -------------------------------------------------------------------------------- 1 | // 2 | // AtkSampleOneDragSourceView.m 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/17/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import "AtkSampleOneDragSourceView.h" 10 | #import "AtkDragAndDropManager.h" 11 | 12 | @interface AtkSampleOneDragSourceView() 13 | 14 | @end 15 | 16 | @implementation AtkSampleOneDragSourceView 17 | 18 | - (id)initWithFrame:(CGRect)frame 19 | { 20 | self = [super initWithFrame:frame]; 21 | if (self) { 22 | // Initialization code 23 | } 24 | return self; 25 | } 26 | 27 | - (void)dragWillStart:(AtkDragAndDropManager *)manager 28 | { 29 | manager.pasteboard.string = [NSString stringWithFormat:@"val-%ld", (long)self.tag]; 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /Classes/UIView+AtkDragAndDrop.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+DragAndDrop.h 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/17/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AtkDragAndDrop.h" 11 | 12 | @interface UIView (AtkDragAndDrop) 13 | 14 | /** 15 | * Creates a UIView based on self that is a UIImageView with an image 16 | * of self to be used as the drag shadow for self. 17 | */ 18 | - (UIView *)createDefaultDragShadowView:(AtkDragAndDropManager *)manager; 19 | 20 | /** 21 | * determine if this view can be considered active by the AtkDragAndDropManager based on the location of point 22 | * point is give relative to manager.rootView, not this view. 23 | */ 24 | - (BOOL)isActiveDropZone:(AtkDragAndDropManager *)manager point:(CGPoint)point; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Classes/UIView+AtkImage.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Image.m 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/17/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "UIView+AtkImage.h" 11 | 12 | @implementation UIView (Image) 13 | 14 | - (UIImage*)imageFromView 15 | { 16 | UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, 0.0); 17 | 18 | if ([self respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) { 19 | [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES]; 20 | } else { 21 | [self.layer renderInContext:UIGraphicsGetCurrentContext()]; 22 | } 23 | 24 | UIImage * img = UIGraphicsGetImageFromCurrentImageContext(); 25 | 26 | UIGraphicsEndImageContext(); 27 | 28 | return img; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Classes/AtkDragSourceProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // AtkDragSourceProtocol.h 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/17/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AtkDropZoneProtocol.h" 11 | #import "AtkDragAndDropLifecycleProtocol.h" 12 | 13 | @class AtkDragAndDropManager; 14 | 15 | @protocol AtkDragSourceProtocol 16 | 17 | @optional 18 | 19 | - (UIView *)createDragShadowView:(AtkDragAndDropManager *)manager; 20 | 21 | /** 22 | * Called to determine if dragging should start on this drag source. 23 | */ 24 | - (BOOL)shouldDragStart:(AtkDragAndDropManager *)manager point:(CGPoint)point; 25 | 26 | /** 27 | * Called when a drag source has been found, but before searching for drop zones. 28 | */ 29 | - (void)dragWillStart:(AtkDragAndDropManager *)manager; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Sample02/AtkSampleTwoDragSourceWrapper.m: -------------------------------------------------------------------------------- 1 | // 2 | // AtkSampleTwoDragSourceWrapper.m 3 | // Atkdrogen_DragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/21/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import "AtkSampleTwoDragSourceWrapper.h" 10 | #import "UIView+AtkDragAndDrop.h" 11 | 12 | @implementation AtkSampleTwoDragSourceWrapper 13 | 14 | - (id)initWithView:(UIView *)view 15 | { 16 | self = [super init]; 17 | if(self) 18 | { 19 | self.view = view; 20 | } 21 | return self; 22 | } 23 | 24 | - (BOOL)shouldDragStart:(AtkDragAndDropManager *)manager point:(CGPoint)point 25 | { 26 | return YES; 27 | } 28 | 29 | - (void)dragWillStart:(AtkDragAndDropManager *)manager 30 | { 31 | manager.pasteboard.string = [NSString stringWithFormat:@"val-%ld", (long)self.view.tag]; 32 | } 33 | 34 | - (UIView *)createDragShadowView:(AtkDragAndDropManager *)manager 35 | { 36 | return [self.view createDefaultDragShadowView:manager]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Classes/UIScrollView+AtkDragAndDrop.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIScrollView+AtkDragAndDrop.h 3 | // Atkdrogen_DragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/21/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIScrollView (AtkDragAndDrop) 12 | 13 | @property (nonatomic, assign) CGFloat autoScrollEdgeTollerance; 14 | @property (nonatomic, assign) CGFloat autoScrollVelocity; 15 | @property (nonatomic, assign) CGFloat autoScrollMaxVelocity; 16 | 17 | // Notifies the UIScrollView that dragging has started. 18 | - (void)autoScrollDragStarted; 19 | 20 | // allows the UIScrollView to monitor the drag movemment and scroll appropriately 21 | // point should be converted to the UIScrollView coordinates using 22 | // [rootView convertPoint:point toView:uiScrollView] from whatever rootView 23 | // coordinate system point was originally in. 24 | - (void)autoScrollDragMoved:(CGPoint)point; 25 | 26 | // Notifies the UIScrollView that dragging has ended. 27 | - (void)autoScrollDragEnded; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Rick Boykin 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /AtkDragAndDrop.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "AtkDragAndDrop" 3 | s.version = "0.2.2" 4 | s.summary = "A drag and drop toolkit for iOS." 5 | s.description = <<-DESC 6 | iOS drag and drop toolkit with support for: 7 | 8 | * Drag Source and Drop Zones by either subclassing or wrapping UIView and subclasses 9 | * Drag shadow generation for UIView 10 | * UIScrollView drag target auto scrolling 11 | * AtkDragAndDropManager uses the delegate pattern to allow a wide varienty of drag and drop scenarios 12 | * Accepts any continuous UIGestureRecognizer class for drag recognition 13 | * Works with the UIPasteboard as a means of data passing for the drag and drop operation. 14 | * Complete set of lifecycle handlers. 15 | DESC 16 | s.homepage = "https://github.com/ptoinson/asymptotik-drag-and-drop" 17 | s.license = 'MIT' 18 | s.author = { "Rick Boykin" => "info@asymptotik.com" } 19 | s.source = { :git => "https://github.com/ptoinson/asymptotik-drag-and-drop.git", :tag => "v#{s.version.to_s}" } 20 | s.platform = :ios, '5.0' 21 | s.requires_arc = true 22 | s.source_files = 'Classes' 23 | s.frameworks = 'UIKit' 24 | end 25 | -------------------------------------------------------------------------------- /Classes/UIView+AtkDragAndDrop.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+DragAndDrop.m 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/17/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import "UIView+AtkDragAndDrop.h" 10 | #import "UIView+AtkImage.h" 11 | #import "AtkDragAndDropManager.h" 12 | 13 | @implementation UIView (DragAndDrop) 14 | 15 | - (UIView *)createDefaultDragShadowView:(AtkDragAndDropManager *)manager 16 | { 17 | UIImage *image = [self imageFromView]; 18 | UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; 19 | CGRect frame = imageView.frame; 20 | frame.origin = [self convertPoint:self.bounds.origin toView:manager.rootView]; 21 | imageView.frame = frame; 22 | imageView.alpha = 0.5; 23 | return imageView; 24 | } 25 | 26 | - (BOOL)isActiveDropZone:(AtkDragAndDropManager *)manager point:(CGPoint)point 27 | { 28 | UIView *view = self; 29 | BOOL ret = YES; 30 | 31 | // We can safely assume point is within rootView. 32 | 33 | while(ret == YES && manager.rootView != view) 34 | { 35 | CGPoint pointRelativeToView = [manager.rootView convertPoint:point toView:view]; 36 | ret = ret && [view pointInside:pointRelativeToView withEvent:nil]; 37 | view = view.superview; 38 | } 39 | 40 | return ret; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/AtkDragAndDrop_Examples-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.asymptotik.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Classes/AtkDragAndDropLifecycleProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // AtkDragAndDropLifecycleProtocol.h 3 | // AtkDragAndDrop_Examples 4 | // 5 | // Created by Rick Boykin on 4/29/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class AtkDragAndDropManager; 12 | @protocol AtkDropZoneProtocol; 13 | 14 | 15 | @protocol AtkDragAndDropLifecycleProtocol 16 | 17 | @optional 18 | 19 | /** 20 | * Called when a drag has started. All of the interested drop zoned have been found. 21 | */ 22 | - (void)dragStarted:(AtkDragAndDropManager *)manager; 23 | 24 | /** 25 | * Called when a drag has ended. 26 | */ 27 | - (void)dragEnded:(AtkDragAndDropManager *)manager; 28 | 29 | /** 30 | * Called when a drag has entered a drop zone. 31 | */ 32 | - (void)dragEntered:(AtkDragAndDropManager *)manager dropZone:(id) dropZone point:(CGPoint)point; 33 | 34 | /** 35 | * Called when a drag has exited a drop zone. 36 | */ 37 | - (void)dragExited:(AtkDragAndDropManager *)manager dropZone:(id) dropZone point:(CGPoint)point; 38 | 39 | /** 40 | * Called when a drag has moved within a drop zone. Only called after dragEntered and before dragExited. 41 | */ 42 | - (void)dragMoved:(AtkDragAndDropManager *)manager dropZone:(id) dropZone point:(CGPoint)point; 43 | 44 | /** 45 | * Called when a drag is dropped onto a drop zone. 46 | */ 47 | - (void)dragDropped:(AtkDragAndDropManager *)manager dropZone:(id) dropZone point:(CGPoint)point; 48 | 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples.xcodeproj/project.xcworkspace/xcshareddata/AtkDragAndDrop_Examples.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 78B10556-4EA7-482E-9876-CECBC2DCF540 9 | IDESourceControlProjectName 10 | AtkDragAndDrop_Examples 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 9C2B6D92-48ED-46C9-8815-CAB5193B9A07 14 | ssh://github.com/ptoinson/asymptotik-drag-and-drop.git 15 | 16 | IDESourceControlProjectPath 17 | Examples/AtkDragAndDrop_Examples.xcodeproj/project.xcworkspace 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 9C2B6D92-48ED-46C9-8815-CAB5193B9A07 21 | ../../.. 22 | 23 | IDESourceControlProjectURL 24 | ssh://github.com/ptoinson/asymptotik-drag-and-drop.git 25 | IDESourceControlProjectVersion 26 | 110 27 | IDESourceControlProjectWCCIdentifier 28 | 9C2B6D92-48ED-46C9-8815-CAB5193B9A07 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 9C2B6D92-48ED-46C9-8815-CAB5193B9A07 36 | IDESourceControlWCCName 37 | Asymptotik_AtkDragAndDrop 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/AtkSampleViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AtkSampleViewController.m 3 | // Atkdrogen_DragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/20/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import "AtkSampleViewController.h" 10 | #import "AtkSampleOneViewController.h" 11 | #import "AtkSampleTwoViewController.h" 12 | 13 | @interface AtkSampleViewController () 14 | 15 | @end 16 | 17 | @implementation AtkSampleViewController 18 | 19 | - (id)init 20 | { 21 | self = [super init]; 22 | if (self) { 23 | [self initialize]; 24 | } 25 | return self; 26 | } 27 | 28 | - (id)initWithCoder:(NSCoder *)aDecoder 29 | { 30 | self = [super initWithCoder:aDecoder]; 31 | if (self) { 32 | [self initialize]; 33 | } 34 | return self; 35 | } 36 | 37 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 38 | { 39 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 40 | if (self) { 41 | [self initialize]; 42 | } 43 | return self; 44 | } 45 | 46 | - (void)initialize 47 | { 48 | self.navigationItem.title = @"Samples"; 49 | } 50 | 51 | - (void)viewDidLoad 52 | { 53 | [super viewDidLoad]; 54 | // Do any additional setup after loading the view from its nib. 55 | } 56 | 57 | - (void)didReceiveMemoryWarning 58 | { 59 | [super didReceiveMemoryWarning]; 60 | // Dispose of any resources that can be recreated. 61 | } 62 | 63 | - (IBAction)sampleOneFired:(id)sender 64 | { 65 | [self.navigationController pushViewController:[[AtkSampleOneViewController alloc] initWithNibName:@"AtkSampleOneViewController" bundle:nil] animated: YES]; 66 | } 67 | 68 | - (IBAction)sampleTwoFired:(id)sender 69 | { 70 | [self.navigationController pushViewController:[[AtkSampleTwoViewController alloc] initWithNibName:@"AtkSampleTwoViewController" bundle:nil] animated: YES]; 71 | } 72 | 73 | - (IBAction)sampleThreeFired:(id)sender 74 | { 75 | //[self.navigationController pushViewController:[[AtkSampleThreeViewController alloc] initWithNibName:@"AtkSampleThreeViewController" bundle:nil] animated: YES]; 76 | } 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /Classes/AtkDropZoneProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // AtkDropZoneProtocol.h 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/17/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class AtkDragAndDropManager; 12 | 13 | @protocol AtkDropZoneProtocol 14 | 15 | @optional 16 | 17 | /** 18 | * Should the drop zone be considered active for the manager and point. 19 | */ 20 | - (BOOL)dropZoneIsActive:(AtkDragAndDropManager *)manager point:(CGPoint)point; 21 | 22 | /** 23 | * A drag has started, should we consider this drop zone. A drop zone that is considered 24 | * will receive calls, as appropriate, to isInterested, dragStarted and dragEnded but not 25 | * dragEntered, dragExited, dragMoved and dragDropped 26 | */ 27 | - (BOOL)dropZoneShouldDragStart:(AtkDragAndDropManager *)manager; 28 | 29 | /** 30 | * A drag has started and shouldDropStart returned YES. Should we consider this drop zone interested in receiving 31 | * the following calls dragEntered, dragExited, dragMoved, dragDropped in addition to dragStarted and dragEnded. 32 | */ 33 | - (BOOL)dropZoneIsInterested:(AtkDragAndDropManager *)manager; 34 | 35 | /* 36 | * Called on all drop zones that responded YES to dragStarted when the drag operation has started. This will 37 | * be soon after shouldDropStart responds YES. 38 | */ 39 | - (void)dropZoneDragStarted:(AtkDragAndDropManager *)manager; 40 | 41 | /* 42 | * Called on all drop zones that responded YES to dragStarted when the drag operation has ended. This will 43 | * be called last in the lifecycle of AtkDragAndDrop. 44 | */ 45 | - (void)dropZoneDragEnded:(AtkDragAndDropManager *)manager; 46 | 47 | /* 48 | * Called when the drag has entered the drop zone. 49 | */ 50 | - (void)dropZoneDragEntered:(AtkDragAndDropManager *)manager point:(CGPoint)point; 51 | 52 | /* 53 | * Called when the drag has exited the drop zone. 54 | */ 55 | - (void)dropZoneDragExited:(AtkDragAndDropManager *)manager point:(CGPoint)point; 56 | 57 | /* 58 | * Called when the drag is in the drop zone and has moved. 59 | */ 60 | - (void)dropZoneDragMoved:(AtkDragAndDropManager *)manager point:(CGPoint)point; 61 | 62 | /* 63 | * called when the drag is in the drop zone and has been dropped. 64 | */ 65 | - (void)dropZoneDragDropped:(AtkDragAndDropManager *)manager point:(CGPoint)point; 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Sample01/AtkSampleOneViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AtkSampleOneViewController.m 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/15/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import "AtkSampleOneViewController.h" 10 | #import "AtkDragAndDropManager.h" 11 | 12 | @interface AtkSampleOneViewController () 13 | 14 | @property (nonatomic, strong) IBOutlet UIView *viewSource; 15 | @property (nonatomic, strong) IBOutlet UIScrollView *scroller; 16 | @property (nonatomic, strong) IBOutlet UIView *viewParent; 17 | @property (nonatomic, strong) IBOutlet UIView *viewTarget01; 18 | @property (nonatomic, strong) IBOutlet UIView *viewTarget02; 19 | @property (nonatomic, strong) IBOutlet UIView *viewTarget03; 20 | @property (nonatomic, strong) IBOutlet UIView *viewTarget04; 21 | @property (nonatomic, strong) IBOutlet UIView *viewTarget05; 22 | @property (nonatomic, strong) IBOutlet UIView *viewTarget06; 23 | @property (nonatomic, strong) IBOutlet UIView *viewTarget07; 24 | @property (nonatomic, strong) IBOutlet UIView *viewTarget08; 25 | @property (nonatomic, strong) AtkDragAndDropManager *dragAndDropManager; 26 | 27 | @end 28 | 29 | @implementation AtkSampleOneViewController 30 | 31 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 32 | { 33 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 34 | if (self) { 35 | [self initialize]; 36 | } 37 | return self; 38 | } 39 | 40 | - (void)initialize 41 | { 42 | self.navigationItem.title = @"Sample One"; 43 | self.dragAndDropManager = [[AtkDragAndDropManager alloc] init]; 44 | } 45 | 46 | - (void)viewDidLoad 47 | { 48 | [super viewDidLoad]; 49 | 50 | CGRect viewParentFrame = _viewParent.frame; 51 | 52 | _scroller.contentSize = viewParentFrame.size; 53 | // Do any additional setup after loading the view from its nib. 54 | } 55 | 56 | - (void)viewDidAppear:(BOOL)animated 57 | { 58 | [super viewDidAppear:animated]; 59 | [self.dragAndDropManager start]; 60 | } 61 | 62 | - (void)viewWillDisappear:(BOOL)animated 63 | { 64 | [self.dragAndDropManager stop]; 65 | [super viewWillDisappear:animated]; 66 | } 67 | 68 | - (void)didReceiveMemoryWarning 69 | { 70 | [super didReceiveMemoryWarning]; 71 | // Dispose of any resources that can be recreated. 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Sample01/AtkSampleOneDropZoneScrollView.m: -------------------------------------------------------------------------------- 1 | // 2 | // AtkSampleOneDropZoneScrollView.m 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/17/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import "AtkSampleOneDropZoneScrollView.h" 10 | #import "UIScrollView+AtkDragAndDrop.h" 11 | 12 | @interface AtkSampleOneDropZoneScrollView () 13 | 14 | @property (nonatomic, strong) UIColor *savedBackgroundColor; 15 | 16 | @end 17 | 18 | @implementation AtkSampleOneDropZoneScrollView 19 | 20 | - (id)init 21 | { 22 | self = [super init]; 23 | if(self) { 24 | 25 | } 26 | return self; 27 | } 28 | 29 | - (id)initWithFrame:(CGRect)frame 30 | { 31 | self = [super initWithFrame:frame]; 32 | if (self) { 33 | 34 | } 35 | return self; 36 | } 37 | 38 | - (id)initWithCoder:(NSCoder *)aDecoder 39 | { 40 | self = [super initWithCoder:aDecoder]; 41 | if (self) { 42 | 43 | } 44 | return self; 45 | } 46 | 47 | - (BOOL)dropZoneShouldDragStart:(AtkDragAndDropManager *)manager 48 | { 49 | return YES; 50 | } 51 | 52 | - (void)dropZoneDragStarted:(AtkDragAndDropManager *)manager 53 | { 54 | //NSLog(@"AtkSampleOneDropZoneScrollView.dragStarted"); 55 | [self autoScrollDragStarted]; 56 | } 57 | 58 | - (BOOL)dropZoneIsInterested:(AtkDragAndDropManager *)manager 59 | { 60 | //NSLog(@"AtkSampleOneDropZoneScrollView.isInterested"); 61 | return YES; 62 | } 63 | 64 | - (void)dropZoneDragEnded:(AtkDragAndDropManager *)manager 65 | { 66 | //NSLog(@"AtkSampleOneDropZoneScrollView.dragEnded"); 67 | [self autoScrollDragEnded]; 68 | } 69 | 70 | - (void)dropZoneDragEntered:(AtkDragAndDropManager *)manager point:(CGPoint)point 71 | { 72 | //NSLog(@"AtkSampleOneDropZoneScrollView.dragEntered"); 73 | self.savedBackgroundColor = self.backgroundColor; 74 | self.backgroundColor = [UIColor blueColor]; 75 | } 76 | 77 | - (void)dropZoneDragExited:(AtkDragAndDropManager *)manager point:(CGPoint)point 78 | { 79 | //NSLog(@"AtkSampleOneDropZoneScrollView.dragExited"); 80 | self.backgroundColor = self.savedBackgroundColor; 81 | } 82 | 83 | - (void)dropZoneDragMoved:(AtkDragAndDropManager *)manager point:(CGPoint)point 84 | { 85 | [self autoScrollDragMoved:[manager.rootView convertPoint:point toView:self]]; 86 | } 87 | 88 | - (void)dropZoneDragDropped:(AtkDragAndDropManager *)manager point:(CGPoint)point 89 | { 90 | //NSLog(@"AtkSampleOneDropZoneScrollView.dragDropped"); 91 | self.backgroundColor = [UIColor greenColor]; 92 | } 93 | 94 | @end 95 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Sample02/AtkSampleTwoDropZoneScrollViewWrapper.m: -------------------------------------------------------------------------------- 1 | // 2 | // AtkSampleTwoDropZoneScrollViewWrapper.m 3 | // Atkdrogen_DragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/21/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import "AtkSampleTwoDropZoneScrollViewWrapper.h" 10 | #import "UIScrollView+AtkDragAndDrop.h" 11 | 12 | @interface AtkSampleTwoDropZoneScrollViewWrapper () 13 | 14 | @property (nonatomic, strong) UIColor *savedBackgroundColor; 15 | 16 | @end 17 | 18 | @implementation AtkSampleTwoDropZoneScrollViewWrapper 19 | 20 | - (id)initWithScrollView:(UIScrollView *)view 21 | { 22 | self = [super init]; 23 | if(self) 24 | { 25 | self.view = view; 26 | [self initialize]; 27 | } 28 | return self; 29 | } 30 | 31 | - (void)initialize 32 | { 33 | } 34 | 35 | - (BOOL)dropZoneIsActive:(AtkDragAndDropManager *)manager point:(CGPoint)point 36 | { 37 | return [self.view isActiveDropZone:manager point:point]; 38 | } 39 | 40 | - (BOOL)dropZoneShouldDragStart:(AtkDragAndDropManager *)manager 41 | { 42 | NSLog(@"AtkSampleOneDropZoneScrollView.shouldDragStart"); 43 | return YES; 44 | } 45 | 46 | - (void)dropZoneDragStarted:(AtkDragAndDropManager *)manager 47 | { 48 | NSLog(@"AtkSampleOneDropZoneScrollView.dragStarted"); 49 | [self.view autoScrollDragStarted]; 50 | } 51 | 52 | - (BOOL)dropZoneIsInterested:(AtkDragAndDropManager *)manager 53 | { 54 | NSLog(@"AtkSampleOneDropZoneScrollView.isInterested"); 55 | return YES; 56 | } 57 | 58 | - (void)dropZoneDragEnded:(AtkDragAndDropManager *)manager 59 | { 60 | NSLog(@"AtkSampleOneDropZoneScrollView.dragEnded"); 61 | [self.view autoScrollDragEnded]; 62 | } 63 | 64 | - (void)dropZoneDragEntered:(AtkDragAndDropManager *)manager point:(CGPoint)point 65 | { 66 | NSLog(@"AtkSampleOneDropZoneScrollView.dragEntered"); 67 | self.savedBackgroundColor = self.view.backgroundColor; 68 | self.view.backgroundColor = [UIColor blueColor]; 69 | } 70 | 71 | - (void)dropZoneDragExited:(AtkDragAndDropManager *)manager point:(CGPoint)point 72 | { 73 | NSLog(@"AtkSampleOneDropZoneScrollView.dragExited"); 74 | self.view.backgroundColor = self.savedBackgroundColor; 75 | } 76 | 77 | - (void)dropZoneDragMoved:(AtkDragAndDropManager *)manager point:(CGPoint)point 78 | { 79 | [self.view autoScrollDragMoved:[manager.rootView convertPoint:point toView:self.view]]; 80 | } 81 | 82 | - (void)dropZoneDragDropped:(AtkDragAndDropManager *)manager point:(CGPoint)point 83 | { 84 | NSLog(@"AtkSampleOneDropZoneScrollView.dragDropped"); 85 | self.view.backgroundColor = [UIColor greenColor]; 86 | } 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/AtkAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AtkAppDelegate.m 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/15/14. 6 | // Copyright (c) 2014 Rick Boykin. All rights reserved. 7 | // 8 | 9 | #import "AtkAppDelegate.h" 10 | #import "AtkSampleViewController.h" 11 | #import "AtkDragAndDrop.h" 12 | 13 | @implementation AtkAppDelegate 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 16 | { 17 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 18 | 19 | 20 | AtkSampleViewController *sampleViewController = [[AtkSampleViewController alloc] initWithNibName:@"AtkSampleViewController" bundle:nil]; 21 | UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:sampleViewController]; 22 | navController.navigationBar.translucent = NO; 23 | navController.edgesForExtendedLayout = UIRectEdgeNone; 24 | 25 | self.window.rootViewController = navController; 26 | 27 | [self.window makeKeyAndVisible]; 28 | 29 | return YES; 30 | } 31 | 32 | - (void)applicationWillResignActive:(UIApplication *)application 33 | { 34 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 35 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 36 | } 37 | 38 | - (void)applicationDidEnterBackground:(UIApplication *)application 39 | { 40 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 41 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 42 | } 43 | 44 | - (void)applicationWillEnterForeground:(UIApplication *)application 45 | { 46 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 47 | } 48 | 49 | - (void)applicationDidBecomeActive:(UIApplication *)application 50 | { 51 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 52 | } 53 | 54 | - (void)applicationWillTerminate:(UIApplication *)application 55 | { 56 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Sample01/AtkSampleOneDropZoneView.m: -------------------------------------------------------------------------------- 1 | // 2 | // AtkSampleOneDropZoneView.m 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/17/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import "AtkSampleOneDropZoneView.h" 10 | 11 | @interface AtkSampleOneDropZoneView () 12 | 13 | @property (nonatomic, strong) UIColor *savedBackgroundColor; 14 | 15 | @end 16 | 17 | @implementation AtkSampleOneDropZoneView 18 | 19 | - (id)initWithFrame:(CGRect)frame 20 | { 21 | self = [super initWithFrame:frame]; 22 | if (self) { 23 | // Initialization code 24 | } 25 | return self; 26 | } 27 | 28 | - (BOOL)dropZoneShouldDragStart:(AtkDragAndDropManager *)manager 29 | { 30 | return YES; 31 | } 32 | 33 | - (BOOL)dropZoneIsInterested:(AtkDragAndDropManager *)manager 34 | { 35 | NSLog(@"AtkSampleOneDropZoneView.isInterested"); 36 | 37 | UIPasteboard *pastebaord = manager.pasteboard; 38 | NSString *tagValue = [NSString stringWithFormat:@"val-%ld", (long)self.tag]; 39 | NSString *pasteboardString = pastebaord.string; 40 | 41 | return [tagValue isEqualToString:pasteboardString]; 42 | } 43 | 44 | - (void)dropZoneDragStarted:(AtkDragAndDropManager *)manager 45 | { 46 | NSLog(@"AtkSampleOneDropZoneView.dragStarted"); 47 | self.savedBackgroundColor = self.backgroundColor; 48 | 49 | UIPasteboard *pastebaord = manager.pasteboard; 50 | NSString *tagValue = [NSString stringWithFormat:@"val-%ld", (long)self.tag]; 51 | NSString *pasteboardString = pastebaord.string; 52 | 53 | if([tagValue isEqualToString:pasteboardString]) 54 | { 55 | self.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.0]; 56 | } 57 | else 58 | { 59 | self.backgroundColor = [UIColor redColor]; 60 | } 61 | } 62 | 63 | - (void)dropZoneDragEnded:(AtkDragAndDropManager *)manager 64 | { 65 | NSLog(@"AtkSampleOneDropZoneView.dragEnded"); 66 | [self performSelector:@selector(delayEnd) withObject:nil afterDelay:0.4]; 67 | } 68 | 69 | - (void)dropZoneDragEntered:(AtkDragAndDropManager *)manager point:(CGPoint)point 70 | { 71 | NSLog(@"AtkSampleOneDropZoneView.dragEntered"); 72 | self.backgroundColor = [UIColor orangeColor]; 73 | } 74 | 75 | - (void)dropZoneDragExited:(AtkDragAndDropManager *)manager point:(CGPoint)point 76 | { 77 | NSLog(@"AtkSampleOneDropZoneView.dragExited"); 78 | self.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.0]; 79 | } 80 | 81 | - (void)dropZoneDragMoved:(AtkDragAndDropManager *)manager point:(CGPoint)point 82 | { 83 | //NSLog(@"AtkSampleOneDropZoneView.dragMoved"); 84 | } 85 | 86 | - (void)dropZoneDragDropped:(AtkDragAndDropManager *)manager point:(CGPoint)point 87 | { 88 | NSLog(@"AtkSampleOneDropZoneView.dragDropped"); 89 | self.backgroundColor = [UIColor magentaColor]; 90 | } 91 | 92 | - (void)delayEnd 93 | { 94 | self.backgroundColor = self.savedBackgroundColor; 95 | } 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Sample02/AtkSampleTwoDropZoneWrapper.m: -------------------------------------------------------------------------------- 1 | // 2 | // AtkSampleTwoDropZoneWrapper.m 3 | // Atkdrogen_DragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/21/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import "AtkSampleTwoDropZoneWrapper.h" 10 | #import "AtkDragAndDrop.h" 11 | 12 | @interface AtkSampleTwoDropZoneWrapper() 13 | 14 | @property (nonatomic, strong) UIColor *savedBackgroundColor; 15 | 16 | @end 17 | 18 | @implementation AtkSampleTwoDropZoneWrapper 19 | 20 | - (id)initWithView:(UIView *)view 21 | { 22 | self = [super init]; 23 | if(self) 24 | { 25 | self.view = view; 26 | [self initialize]; 27 | } 28 | return self; 29 | } 30 | 31 | - (void)initialize 32 | { 33 | 34 | } 35 | 36 | - (BOOL)dropZoneIsActive:(AtkDragAndDropManager *)manager point:(CGPoint)point 37 | { 38 | return [self.view isActiveDropZone:manager point:point]; 39 | } 40 | 41 | - (BOOL)dropZoneShouldDragStart:(AtkDragAndDropManager *)manager 42 | { 43 | return YES; 44 | } 45 | 46 | - (BOOL)dropZoneIsInterested:(AtkDragAndDropManager *)manager 47 | { 48 | //NSLog(@"AtkSampleOneDropZoneView.dragStarted"); 49 | UIPasteboard *pastebaord = manager.pasteboard; 50 | NSString *tagValue = [NSString stringWithFormat:@"val-%ld", (long)self.view.tag]; 51 | NSString *pasteboardString = pastebaord.string; 52 | 53 | return [tagValue isEqualToString:pasteboardString]; 54 | } 55 | 56 | - (void)dropZoneDragStarted:(AtkDragAndDropManager *)manager 57 | { 58 | //NSLog(@"AtkSampleOneDropZoneView.dragStarted"); 59 | self.savedBackgroundColor = self.view.backgroundColor; 60 | 61 | UIPasteboard *pastebaord = manager.pasteboard; 62 | NSString *tagValue = [NSString stringWithFormat:@"val-%ld", (long)self.view.tag]; 63 | NSString *pasteboardString = pastebaord.string; 64 | 65 | if([tagValue isEqualToString:pasteboardString]) 66 | { 67 | self.view.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.0]; 68 | } 69 | else 70 | { 71 | self.view.backgroundColor = [UIColor redColor]; 72 | } 73 | } 74 | 75 | - (void)dropZoneDragEnded:(AtkDragAndDropManager *)manager 76 | { 77 | //NSLog(@"AtkSampleOneDropZoneView.dragEnded"); 78 | [self performSelector:@selector(delayEnd) withObject:nil afterDelay:0.4]; 79 | } 80 | 81 | - (void)dropZoneDragEntered:(AtkDragAndDropManager *)manager point:(CGPoint)point 82 | { 83 | //NSLog(@"AtkSampleOneDropZoneView.dragEntered"); 84 | self.view.backgroundColor = [UIColor orangeColor]; 85 | } 86 | 87 | - (void)dropZoneDragExited:(AtkDragAndDropManager *)manager point:(CGPoint)point 88 | { 89 | //NSLog(@"AtkSampleOneDropZoneView.dragExited"); 90 | self.view.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.0]; 91 | } 92 | 93 | - (void)dropZoneDragMoved:(AtkDragAndDropManager *)manager point:(CGPoint)point 94 | { 95 | //NSLog(@"AtkSampleOneDropZoneView.dragMoved"); 96 | } 97 | 98 | - (void)dropZoneDragDropped:(AtkDragAndDropManager *)manager point:(CGPoint)point 99 | { 100 | //NSLog(@"AtkSampleOneDropZoneView.dragDropped"); 101 | self.view.backgroundColor = [UIColor magentaColor]; 102 | } 103 | 104 | - (void)delayEnd 105 | { 106 | self.view.backgroundColor = self.savedBackgroundColor; 107 | } 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/AtkSampleViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 27 | 36 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /Classes/AtkDefaultDragAndDropManagerDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AtkDefaultDragAndDropManagerDelegate.m 3 | // Atkdrogen_DragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/20/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import "AtkDefaultDragAndDropManagerDelegate.h" 10 | #import "UIView+AtkDragAndDrop.h" 11 | 12 | @implementation AtkDefaultDragAndDropManagerDelegate 13 | 14 | /** 15 | * Finds the drag source. 16 | */ 17 | - (id)findDragSource:(AtkDragAndDropManager *)manager recognizer:(UIGestureRecognizer *)recognizer 18 | { 19 | BOOL dragStarted = NO; 20 | 21 | CGPoint point = [recognizer locationInView:manager.rootView]; 22 | UIView *hitView = [manager.rootView hitTest:point withEvent:nil]; 23 | 24 | while(!dragStarted && hitView) 25 | { 26 | if([hitView conformsToProtocol:@protocol(AtkDragSourceProtocol)]) 27 | { 28 | if([hitView respondsToSelector:@selector(shouldDragStart:point:)]) 29 | dragStarted = [(UIView *)hitView shouldDragStart:manager point: point]; 30 | else 31 | dragStarted = YES; 32 | } 33 | 34 | if(!dragStarted) 35 | { 36 | hitView = hitView.superview; 37 | } 38 | } 39 | 40 | return dragStarted ? (id)hitView : nil; 41 | } 42 | 43 | /** 44 | * Recursively finds any drop zones (id) in view and it's descendants that are interested in the gesture recognizer 45 | * and adds them to dropZones. The return value is the passed in dropZones. If a drop zone is found and dropZones is nil, a new 46 | * NSMutableArray will be constructed, filled and returned. 47 | */ 48 | - (NSMutableArray *)findDropZones:(AtkDragAndDropManager *)manager view:(UIView *)view recognizer:(UIGestureRecognizer *)recognizer dropZones:(NSMutableArray *)dropZones 49 | { 50 | if([view conformsToProtocol:@protocol(AtkDropZoneProtocol)] && 51 | [view respondsToSelector:@selector(dropZoneShouldDragStart:)] && 52 | [(id)view dropZoneShouldDragStart:manager]) 53 | { 54 | if(!dropZones) 55 | dropZones = [NSMutableArray array]; 56 | 57 | [dropZones addObject:view]; 58 | } 59 | 60 | for (UIView *subview in view.subviews) 61 | { 62 | dropZones = [self findDropZones:manager view:subview recognizer:recognizer dropZones:dropZones]; 63 | } 64 | 65 | return dropZones; 66 | } 67 | 68 | /** 69 | * Recursively finds any drop zones (id) in rootView and it's descendants that are interested in the gesture 70 | * recognizer and returns them. 71 | */ 72 | - (NSArray *)findDropZones:(AtkDragAndDropManager *)manager recognizer:(UIGestureRecognizer *)recognizer 73 | { 74 | NSMutableArray *ret = [self findDropZones:manager view:manager.rootView recognizer:recognizer dropZones:nil]; 75 | return ret ? [NSArray arrayWithArray:ret] : nil; 76 | } 77 | 78 | /** 79 | * Returns YES is the specified drop zone is active for the recognizer. Active means that if the 80 | * drop event were to occur immediately, that drop zone would be dropped upon. 81 | */ 82 | - (BOOL)isDropZoneActive:(AtkDragAndDropManager *)manager dropZone:(id)dropZone recognizer:(UIGestureRecognizer *)recognizer 83 | { 84 | BOOL ret = false; 85 | 86 | if([dropZone respondsToSelector:@selector(dropZoneIsActive:point:)]) 87 | { 88 | ret = [dropZone dropZoneIsActive:manager point:[recognizer locationInView:manager.rootView]]; 89 | } 90 | else if([dropZone isKindOfClass:[UIView class]]) 91 | { 92 | UIView *dropView = (UIView *)dropZone; 93 | ret = [dropView isActiveDropZone:manager point:[recognizer locationInView:manager.rootView]]; 94 | } 95 | else if([dropZone isKindOfClass:[UIViewController class]]) 96 | { 97 | UIView *dropView = ((UIViewController *)dropZone).view; 98 | ret = [dropView isActiveDropZone:manager point:[recognizer locationInView:manager.rootView]]; 99 | } 100 | 101 | return ret; 102 | } 103 | 104 | @end 105 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Sample02/AtkSampleTwoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AtkSampleTwoViewController.m 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/15/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import "AtkSampleTwoViewController.h" 10 | #import "AtkSampleTwoDragSourceWrapper.h" 11 | #import "AtkSampleTwoDropZoneWrapper.h" 12 | #import "AtkSampleTwoDropZoneScrollViewWrapper.h" 13 | #import "AtkDragAndDrop.h" 14 | 15 | @interface AtkSampleTwoViewController () 16 | 17 | @property (nonatomic, strong) IBOutlet UIView *viewSource01; 18 | @property (nonatomic, strong) IBOutlet UIView *viewSource02; 19 | @property (nonatomic, strong) IBOutlet UIScrollView *scroller; 20 | @property (nonatomic, strong) IBOutlet UIView *viewParent; 21 | @property (nonatomic, strong) AtkDragAndDropManager *dragAndDropManager; 22 | 23 | @end 24 | 25 | @implementation AtkSampleTwoViewController 26 | 27 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 28 | { 29 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 30 | if (self) { 31 | [self initialize]; 32 | } 33 | return self; 34 | } 35 | 36 | - (void)initialize 37 | { 38 | self.navigationItem.title = @"Sample Two"; 39 | self.dragAndDropManager = [[AtkDragAndDropManager alloc] init]; 40 | self.dragAndDropManager.delegate = self; 41 | } 42 | 43 | - (void)viewDidLoad 44 | { 45 | [super viewDidLoad]; 46 | 47 | CGRect viewParentFrame = _viewParent.frame; 48 | 49 | _scroller.contentSize = viewParentFrame.size; 50 | // Do any additional setup after loading the view from its nib. 51 | } 52 | 53 | - (void)viewDidAppear:(BOOL)animated 54 | { 55 | [super viewDidAppear:animated]; 56 | [self.dragAndDropManager start:[[UIApplication sharedApplication] keyWindow] recognizerClass:[UILongPressGestureRecognizer class]]; 57 | } 58 | 59 | - (void)viewWillDisappear:(BOOL)animated 60 | { 61 | [self.dragAndDropManager stop]; 62 | [super viewWillDisappear:animated]; 63 | } 64 | 65 | - (void)didReceiveMemoryWarning 66 | { 67 | [super didReceiveMemoryWarning]; 68 | // Dispose of any resources that can be recreated. 69 | } 70 | 71 | /** 72 | * Finds the drag source. 73 | */ 74 | - (id)findDragSource:(AtkDragAndDropManager *)manager recognizer:(UIGestureRecognizer *)recognizer 75 | { 76 | BOOL dragStarted = NO; 77 | 78 | UIView *hitView = [manager.rootView hitTest:[recognizer locationInView:manager.rootView] withEvent:nil]; 79 | 80 | // Very simple find. Use any means you want to find the sources. 81 | if(hitView == _viewSource01 || hitView == _viewSource02) 82 | dragStarted = YES; 83 | 84 | AtkSampleTwoDragSourceWrapper * ret = nil; 85 | 86 | if(dragStarted) 87 | { 88 | ret = [[AtkSampleTwoDragSourceWrapper alloc] initWithView:hitView]; 89 | } 90 | 91 | return ret; 92 | } 93 | 94 | /** 95 | * Recursively finds any drop zones (id) in rootView and it's descendents that are interested in the gesture 96 | * recognizer and returns them. 97 | */ 98 | - (NSArray *)findDropZones:(AtkDragAndDropManager *)manager recognizer:(UIGestureRecognizer *)recognizer 99 | { 100 | NSMutableArray *ret = [NSMutableArray arrayWithCapacity:10]; 101 | AtkSampleTwoDropZoneScrollViewWrapper *scrollViewDropZone = [[AtkSampleTwoDropZoneScrollViewWrapper alloc] initWithScrollView:_scroller]; 102 | 103 | [ret addObject:scrollViewDropZone]; 104 | 105 | for(UIView *child in _viewParent.subviews) 106 | { 107 | AtkSampleTwoDropZoneWrapper *viewDropZone = [[AtkSampleTwoDropZoneWrapper alloc] initWithView:child]; 108 | [ret addObject:viewDropZone]; 109 | } 110 | 111 | return ret; 112 | } 113 | 114 | /** 115 | * Returns YES is the specified drop zone is active for the recognizer. Active means that if the 116 | * drop event were to occur immediately, that drop zone would be dropped upon. 117 | */ 118 | - (BOOL)isDropZoneActive:(AtkDragAndDropManager *)manager dropZone:(id)dropZone recognizer:(UIGestureRecognizer *)recognizer 119 | { 120 | BOOL ret = false; 121 | 122 | if([dropZone respondsToSelector:@selector(dropZoneIsActive:point:)]) 123 | { 124 | ret = [dropZone dropZoneIsActive:manager point:[recognizer locationInView:manager.rootView]]; 125 | } 126 | 127 | return ret; 128 | } 129 | 130 | @end 131 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | desc "Runs the specs [EMPTY]" 2 | task :spec do 3 | # Provide your own implementation 4 | end 5 | 6 | task :version do 7 | git_remotes = `git remote`.strip.split("\n") 8 | 9 | if git_remotes.count > 0 10 | puts "-- fetching version number from github" 11 | sh 'git fetch' 12 | 13 | remote_version = remote_spec_version 14 | end 15 | 16 | if remote_version.nil? 17 | puts "There is no current released version. You're about to release a new Pod." 18 | version = "0.0.1" 19 | else 20 | puts "The current released version of your pod is " + remote_spec_version.to_s() 21 | version = suggested_version_number 22 | end 23 | 24 | puts "Enter the version you want to release (" + version + ") " 25 | new_version_number = $stdin.gets.strip 26 | if new_version_number == "" 27 | new_version_number = version 28 | end 29 | 30 | replace_version_number(new_version_number) 31 | end 32 | 33 | desc "Release a new version of the Pod" 34 | task :release do 35 | 36 | puts "* Running version" 37 | sh "rake version" 38 | 39 | unless ENV['SKIP_CHECKS'] 40 | if `git symbolic-ref HEAD 2>/dev/null`.strip.split('/').last != 'master' 41 | $stderr.puts "[!] You need to be on the `master' branch in order to be able to do a release." 42 | exit 1 43 | end 44 | 45 | if `git tag`.strip.split("\n").include?(spec_version) 46 | $stderr.puts "[!] A tag for version `#{spec_version}' already exists. Change the version in the podspec" 47 | exit 1 48 | end 49 | 50 | puts "You are about to release `#{spec_version}`, is that correct? [y/n]" 51 | exit if $stdin.gets.strip.downcase != 'y' 52 | end 53 | 54 | puts "* Running specs" 55 | sh "rake spec" 56 | 57 | puts "* Linting the podspec" 58 | sh "pod lib lint" 59 | 60 | # Then release 61 | sh "git commit #{podspec_path} CHANGELOG.md -m 'Release #{spec_version}'" 62 | sh "git tag -a #{spec_version} -m 'Release #{spec_version}'" 63 | sh "git push origin master" 64 | sh "git push origin --tags" 65 | sh "pod push master #{podspec_path}" 66 | end 67 | 68 | # @return [Pod::Version] The version as reported by the Podspec. 69 | # 70 | def spec_version 71 | require 'cocoapods' 72 | spec = Pod::Specification.from_file(podspec_path) 73 | spec.version 74 | end 75 | 76 | # @return [Pod::Version] The version as reported by the Podspec from remote. 77 | # 78 | def remote_spec_version 79 | require 'cocoapods-core' 80 | 81 | if spec_file_exist_on_remote? 82 | remote_spec = eval(`git show origin/master:#{podspec_path}`) 83 | remote_spec.version 84 | else 85 | nil 86 | end 87 | end 88 | 89 | # @return [Bool] If the remote repository has a copy of the podpesc file or not. 90 | # 91 | def spec_file_exist_on_remote? 92 | test_condition = `if git rev-parse --verify --quiet origin/master:#{podspec_path} >/dev/null; 93 | then 94 | echo 'true' 95 | else 96 | echo 'false' 97 | fi` 98 | 99 | 'true' == test_condition.strip 100 | end 101 | 102 | # @return [String] The relative path of the Podspec. 103 | # 104 | def podspec_path 105 | podspecs = Dir.glob('*.podspec') 106 | if podspecs.count == 1 107 | podspecs.first 108 | else 109 | raise "Could not select a podspec" 110 | end 111 | end 112 | 113 | # @return [String] The suggested version number based on the local and remote version numbers. 114 | # 115 | def suggested_version_number 116 | if spec_version != remote_spec_version 117 | spec_version.to_s() 118 | else 119 | next_version(spec_version).to_s() 120 | end 121 | end 122 | 123 | # @param [Pod::Version] version 124 | # the version for which you need the next version 125 | # 126 | # @note It is computed by bumping the last component of the versino string by 1. 127 | # 128 | # @return [Pod::Version] The version that comes next after the version supplied. 129 | # 130 | def next_version(version) 131 | version_components = version.to_s().split("."); 132 | last = (version_components.last.to_i() + 1).to_s 133 | version_components[-1] = last 134 | Pod::Version.new(version_components.join(".")) 135 | end 136 | 137 | # @param [String] new_version_number 138 | # the new version number 139 | # 140 | # @note This methods replaces the version number in the podspec file with a new version number. 141 | # 142 | # @return void 143 | # 144 | def replace_version_number(new_version_number) 145 | text = File.read(podspec_path) 146 | text.gsub!(/(s.version( )*= ")#{spec_version}(")/, "\\1#{new_version_number}\\3") 147 | File.open(podspec_path, "w") { |file| file.puts text } 148 | end -------------------------------------------------------------------------------- /Classes/AtkDragAndDropManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // AtkDragAndDropManager.h 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/17/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AtkDragSourceProtocol.h" 11 | #import "AtkDragAndDropLifecycleProtocol.h" 12 | 13 | @class AtkDragAndDropManager; 14 | 15 | @protocol AtkDragAndDropManagerDelegate 16 | 17 | @optional 18 | 19 | /** 20 | * Finds the drag source based on the rootView and the recognizer. If not implemented the default is used. 21 | */ 22 | - (id)findDragSource:(AtkDragAndDropManager *)manager recognizer:(UIGestureRecognizer *)recognizer; 23 | 24 | /** 25 | * Recursively finds any drop zones (id) in rootView and it's descendents that are interested in the gesture 26 | * recognizer and returns them. In some cases the drag operation may include data set on the AtkDragAndDropManagers UIPasteboard. 27 | * It's up to this method to determine if the drop zone is interested in the content of that UIPasteboard. 28 | * 29 | * If not implemented the default is used. 30 | */ 31 | - (NSArray *)findDropZones:(AtkDragAndDropManager *)manager recognizer:(UIGestureRecognizer *)recognizer; 32 | 33 | /** 34 | * Returns YES is the specified drop zone is active for the recognizer. Active means that if the 35 | * drop event were to occur immediately, that drop zone would be dropped upon. For example, if the 36 | * current touch has dragged over the drop zone, the drop zone may then be active. 37 | * 38 | * If not implemented the default is used. 39 | */ 40 | - (BOOL)isDropZoneActive:(AtkDragAndDropManager *)manager dropZone:(id)dropZone recognizer:(UIGestureRecognizer *)recognizer; 41 | 42 | /** 43 | * Called when a drag source has been found, but before searching for drop zones. 44 | */ 45 | - (void)dragWillStart:(AtkDragAndDropManager *)manager; 46 | 47 | 48 | @end 49 | 50 | @interface AtkDragAndDropManager : NSObject 51 | 52 | extern NSString *const AtkPasteboardNameDragAndDrop; 53 | 54 | /** 55 | * The AtkDDragAndDropManager delegate. 56 | */ 57 | @property (nonatomic, weak) id delegate; 58 | 59 | /** 60 | * The pastbaord name. Defaults to AtkPasteboardNameDragAndDrop which creates 61 | * a pastebaord unique to drag and drop. This may be changed to any unique name, including 62 | * the shared pastebaord. 63 | */ 64 | @property (nonatomic, strong) NSString* pasteboardName; 65 | 66 | /** 67 | * Get the Drag and Drop pastebaord. The paasteboard is based on pasteboardName, which is configurable. 68 | */ 69 | @property (weak, nonatomic, readonly) UIPasteboard* pasteboard; 70 | 71 | /** 72 | * The root UIView as set by the call to start:(UIView *) or the UIApplication keyWindow 73 | * by default. All the players in the drag and drop scenerio must be descendants of rootView. 74 | */ 75 | - (UIView*)rootView; 76 | 77 | /** 78 | * Starts the drag and drop manager. This sets up the gesture recognizer and UIApplication keyWindow 79 | * as the rootView. 80 | */ 81 | - (void)start; 82 | 83 | /** 84 | * Starts the drag and drop manager. This sets up the rootView. 85 | */ 86 | - (void)start:(UIView *)rootView; 87 | 88 | /** 89 | * Starts the drag and drop manager. This sets up the gesture recognizer and the rootView. 90 | */ 91 | - (void)start:(UIView *)rootView recognizerClass:(Class)recognizerClass; 92 | 93 | /** 94 | * Stops the drag and drop manager. Any gesture recognizer is removed. Any drag operation in progress is ended. 95 | * The recognizer and rootViews are set to nil. 96 | */ 97 | - (void)stop; 98 | 99 | #pragma mark - Protected 100 | 101 | /** 102 | * Find the drag source by calling on the delegate. If the delegate does no implement findDragSource: then the default 103 | * delegate is used. 104 | */ 105 | - (id)findDragSource:(UIGestureRecognizer *)recognizer; 106 | 107 | /** 108 | * Find the drop zones by calling on the delegate. If the delegate does no implement findDropZones: then the default 109 | * delegate is used. 110 | */ 111 | - (NSArray *)findDropZones:(UIGestureRecognizer *)recognizer; 112 | 113 | /** 114 | * Determine if the drop zone is active. Typically active means that the touch point in the recognizer is over the drop zone. 115 | * Here (and/or in the delegate, it is possible to change that meaning) 116 | * If the delegate does no implement isDropZoneActive:recognizer: then the default delegate is used. 117 | */ 118 | - (BOOL)isDropZoneActive:(id)dropZone recognizer:(UIGestureRecognizer *)recognizer; 119 | 120 | // 121 | // Notifications for the drag and drop lifecycle. 122 | // 123 | 124 | /** 125 | * Called when a drag has started but before searching for drop zones. 126 | * If overriding in a subclass the super method should be called to ensure proper functionality. 127 | */ 128 | - (void)dragWillStart; 129 | 130 | /** 131 | * Called when a drag has started. 132 | * If overriding in a subclass the super method should be called to ensure proper functionality. 133 | */ 134 | - (void)dragStarted; 135 | 136 | /** 137 | * Called when a drag has ended. 138 | * If overriding in a subclass the super method should be called to ensure proper functionality. 139 | */ 140 | - (void)dragEnded; 141 | 142 | /** 143 | * Called when a drag has endtered a drop zone. 144 | * If overriding in a subclass the super method should be called to ensure proper functionality. 145 | */ 146 | - (void)dragEntered:(id) dropZone point:(CGPoint)point; 147 | 148 | /** 149 | * Called when a drag has exited a drop zone. 150 | * If overriding in a subclass the super method should be called to ensure proper functionality. 151 | */ 152 | - (void)dragExited:(id) dropZone point:(CGPoint)point; 153 | 154 | /** 155 | * Called when a drag has moved within a drop zone. Only called after dragEntered and before dragExited. 156 | * If overriding in a subclass the super method should be called to ensure proper functionality. 157 | */ 158 | - (void)dragMoved:(id) dropZone point:(CGPoint)point; 159 | 160 | /** 161 | * Called when a drag is dropped onto a drop zone. 162 | * If overriding in a subclass the super method should be called to ensure proper functionality. 163 | */ 164 | - (void)dragDropped:(id) dropZone point:(CGPoint)point; 165 | 166 | @end 167 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Asymptotik Drag and Drop 2 | ================= 3 | 4 | iOS drag and drop toolkit with support for: 5 | 6 | * Drag Source and Drop Zones by either subclassing or wrapping UIView and subclasses 7 | * Drag shadow generation for UIView 8 | * UIScrollView drag target auto scrolling 9 | * AtkDragAndDropManager uses the delegate pattern to allow a wide varienty of drag and drop scenarios 10 | * Accepts any continuous UIGestureRecognizer class for drag recognition 11 | * Works with the UIPasteboard as a means of data passing for the drag and drop operation. 12 | * Complete set of lifecycle handlers. 13 | 14 | The current limitation to the library is that drag and drop takes place for objects that are associated with a common root view. In practice this simply limits draging across UIWindows. This library does not currently use ARC. I know. I know. But my motivation was a much bigger project that has not yet been converted. 15 | 16 | I wrote this because I needed drag and drop support and didn't find something out there that met all my needs. Please try it out and give me your feedback. I'm interested in making this pretty robust and will accept reasonable pull requests. If you want to do big changes, I'm open, but lets talk. 17 | 18 | Example 19 | -------- 20 | 21 | The source base provides a few examples that use most of the features. Here is a simple example of setting up a scenario that uses most of the defaults. 22 | 23 | Here we have a UIView drag source. 24 | 25 | ```objective-c 26 | 27 | @interface AtkSampleOneDragSourceView 28 | 29 | @end 30 | 31 | @implementation AtkSampleOneDragSourceView 32 | 33 | - (BOOL)shouldDragStart:(AtkDragAndDropManager *)manager 34 | { 35 | return YES; 36 | } 37 | 38 | - (void)dragWillStart:(AtkDragAndDropManager *)manager 39 | { 40 | // This is called before any call to AtkDropZoneProtocol shouldDragStart. 41 | // It's a good place to setup data for that method to examine. 42 | manager.pasteboard.string = [NSString stringWithFormat:@"val-%ld", (long)self.tag]; 43 | } 44 | 45 | @end 46 | 47 | ``` 48 | 49 | Here we have a UIView drop zone. 50 | 51 | ```objective-c 52 | 53 | @interface AtkSampleOneDropZoneView 54 | 55 | @end 56 | 57 | @implementation AtkSampleOneDropZoneView 58 | 59 | - (BOOL)shouldDragStart:(AtkDragAndDropManager *)manager 60 | { 61 | // Yes, consider me for drags. Returning true here only 62 | // ensures that isInterested, dragStarted, and dragEnded will 63 | // be called. 64 | return YES; 65 | } 66 | 67 | - (BOOL)isInterested:(AtkDragAndDropManager *)manager 68 | { 69 | // If we return true here then dragEntered, dragExited, dragMoved and 70 | // dragDropped can be called. 71 | // So, let's see if we are interested in what's on the pasteboard. 72 | // For the example this is if the pastbaord string matches 73 | // a string made up from the views tag property. 74 | 75 | BOOL ret = NO; 76 | UIPasteboard *pastebaord = manager.pasteboard; 77 | NSString *interestedInString = 78 | [NSString stringWithFormat:@"val-%ld", (long)self.tag]; 79 | if([interestedInString isEqualToString:pastebaord.string]) 80 | ret = YES; 81 | 82 | return ret; 83 | } 84 | 85 | @end 86 | 87 | ``` 88 | 89 | And finally, we have our UIViewController. This assumes the drag source and drop zones were layed out on the MySampleOneViewController in Interface Builder or some other means. 90 | 91 | ```objective-c 92 | 93 | @interface AtkSampleOneViewController : UIViewController 94 | 95 | @property (nonatomic, retain) AtkDragAndDropManager *dragAndDropManager; 96 | 97 | @end 98 | 99 | @implementation AtkSampleOneViewController 100 | 101 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 102 | { 103 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 104 | if (self) { 105 | [self initialize]; 106 | } 107 | return self; 108 | } 109 | 110 | - (void)initialize 111 | { 112 | self.navigationItem.title = @"Sample One"; 113 | // 114 | // By default the AtkDragAndDropManager uses the UIApplication key windows as 115 | // the rootView and a UIPanGestureRecognizer. However, these are configurable. 116 | // Notice there is no need to register the drag sources or drop zones. The 117 | // AtkDragAndDropManager will by default traverse the view hierarch and find them. 118 | // This behavior is also configurable through the AtkDragAndDropManager delegate. 119 | // 120 | self.dragAndDropManager = [[[AtkDragAndDropManager alloc] init] autorelease]; 121 | // For the AtkDragAndDropManagerDelegate methods findDragSource: finrDropZones: and 122 | // isDropZoneActive:recognizer:, if we do not implement them here, the 123 | // relevant methods in AtkDefaultDragAndDropManagerDelegate will be called. 124 | // This gives us our reasonable defaults even if we want to capture drag and drop 125 | // events here. 126 | self.dragAndDropManager.delegate = self; 127 | } 128 | 129 | - (void)viewDidAppear:(BOOL)animated 130 | { 131 | [super viewDidAppear:animated]; 132 | [self.dragAndDropManager start]; 133 | } 134 | 135 | - (void)viewWillDisappear:(BOOL)animated 136 | { 137 | [self.dragAndDropManager stop]; 138 | [super viewWillDisappear:animated]; 139 | } 140 | 141 | /** 142 | * Called when a drag is dropped onto a drop zone. 143 | */ 144 | - (void)dragDropped:(AtkDragAndDropManager *)manager 145 | dropZone:(id)dropZone 146 | point:(CGPoint)point 147 | { 148 | // The drag was dropped onto an interested AtkDropZoneProtocol. Do something with it. 149 | } 150 | 151 | @end 152 | 153 | ``` 154 | 155 | 173 | 174 | ## Updates 175 | 176 | ### 0.2.1 -> 0.2.2 177 | 178 | * dragStarted lifecycle event is not called on DropZones that return YES to shouldDragStart. 179 | * Cleaned up examples. 180 | 181 | ### 0.2.0 -> 0.2.1 182 | 183 | * Fixed an issue in Sample 2 which caused a crash. This code was left in after the refactor from 0.1.0 -> 0.2.0 by mistake. 184 | 185 | ### 0.1.0 -> 0.2.0 186 | 187 | * added drag and drop handler methods to the AtkDragAndDropManagerDelegate. 188 | * added shouldDragStart to AtkDragSourceProtocol and AtkDropZoneProtocol. dragStarted no londer returns a boolean. 189 | * made all protocol methods optional. this allows for maximal flexability. 190 | * if a AtkDragAndDropManagerDelegate does not implement methods findDragSource: findDropZones: or isDropZoneActive:recognizer: we look to the AtkDefaultDragAndDropManagerDelegate. 191 | * added dragWillStart to AtkDragSourceProtocol. this is called before dragStarted and AtkDropZoneProtocol shouldDragStart and allows us to setup data for drop zones to look at in shouldDragStart so they can determine if they want to participate as a drop zone. 192 | * Updates to the examples and readme. 193 | 194 | ## Author 195 | 196 | Rick Boykin, rick.boykin@gmail.com 197 | 198 | ## License 199 | 200 | AtkDragAndDrop is available under the MIT license. See the LICENSE file for more info. 201 | 202 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Sample02/AtkSampleTwoViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 98 | 99 | 100 | 101 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples/Sample01/AtkSampleOneViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /Classes/UIScrollView+AtkDragAndDrop.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIScrollView+AtkDragAndDrop.m 3 | // Atkdrogen_DragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/21/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "UIScrollView+AtkDragAndDrop.h" 11 | #import "AtkDragAndDropManager.h" 12 | 13 | static const void *AtkDragAndDropScrollViewPropertyHolderKey; 14 | static const CGFloat kAtkAutoScrollEdgeTolleranceDefault = 80.0; 15 | static const CGFloat kAtkAutoScrollMaxVelocityDefault = 4.0; 16 | static const CGFloat kAtkAutoScrollVelocityDefault = 0.1; 17 | 18 | @interface AtkDragAndDropScrollViewPropertyHolder : NSObject 19 | @property (nonatomic, assign) CGFloat autoScrollEdgeTollerance; 20 | @property (nonatomic, assign) CGFloat autoScrollVelocity; 21 | @property (nonatomic, assign) CGFloat autoScrollMaxVelocity; 22 | @property (nonatomic, assign) CGPoint autoScrollDragPinnedPoint; 23 | @property (nonatomic, assign) CGPoint autoScrollLastDragPoint; 24 | @property (nonatomic, strong) NSTimer *autoScrollTimer; 25 | @end 26 | 27 | @implementation AtkDragAndDropScrollViewPropertyHolder 28 | 29 | - (id)init 30 | { 31 | self = [super init]; 32 | if(self) 33 | { 34 | self.autoScrollEdgeTollerance = kAtkAutoScrollEdgeTolleranceDefault; 35 | self.autoScrollVelocity = kAtkAutoScrollVelocityDefault; 36 | self.autoScrollMaxVelocity = kAtkAutoScrollMaxVelocityDefault; 37 | } 38 | 39 | return self; 40 | } 41 | 42 | @end 43 | 44 | @implementation UIScrollView (AtkDragAndDrop) 45 | 46 | - (CGFloat)autoScrollEdgeTollerance 47 | { 48 | CGFloat ret = kAtkAutoScrollEdgeTolleranceDefault; 49 | AtkDragAndDropScrollViewPropertyHolder *result = (AtkDragAndDropScrollViewPropertyHolder *)objc_getAssociatedObject(self, &AtkDragAndDropScrollViewPropertyHolderKey); 50 | if (result != nil) { 51 | ret = result.autoScrollEdgeTollerance; 52 | } 53 | return ret; 54 | } 55 | 56 | - (void)setAutoScrollEdgeTollerance:(CGFloat)autoScrollEdgeTollerance 57 | { 58 | AtkDragAndDropScrollViewPropertyHolder *result = (AtkDragAndDropScrollViewPropertyHolder *)objc_getAssociatedObject(self, &AtkDragAndDropScrollViewPropertyHolderKey); 59 | if (result == nil) { 60 | result = [[AtkDragAndDropScrollViewPropertyHolder alloc] init]; 61 | objc_setAssociatedObject(self, &AtkDragAndDropScrollViewPropertyHolderKey, result, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 62 | } 63 | 64 | result.autoScrollEdgeTollerance = autoScrollEdgeTollerance; 65 | } 66 | 67 | - (CGFloat)autoScrollVelocity 68 | { 69 | CGFloat ret = kAtkAutoScrollVelocityDefault; 70 | AtkDragAndDropScrollViewPropertyHolder *result = (AtkDragAndDropScrollViewPropertyHolder *)objc_getAssociatedObject(self, &AtkDragAndDropScrollViewPropertyHolderKey); 71 | if (result != nil) { 72 | ret = result.autoScrollVelocity; 73 | } 74 | return ret; 75 | } 76 | 77 | - (void)setAutoScrollVelocity:(CGFloat)autoScrollVelocity 78 | { 79 | AtkDragAndDropScrollViewPropertyHolder *result = (AtkDragAndDropScrollViewPropertyHolder *)objc_getAssociatedObject(self, &AtkDragAndDropScrollViewPropertyHolderKey); 80 | if (result == nil) { 81 | result = [[AtkDragAndDropScrollViewPropertyHolder alloc] init]; 82 | objc_setAssociatedObject(self, &AtkDragAndDropScrollViewPropertyHolderKey, result, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 83 | } 84 | 85 | result.autoScrollVelocity = autoScrollVelocity; 86 | } 87 | 88 | - (CGFloat)autoScrollMaxVelocity 89 | { 90 | CGFloat ret = kAtkAutoScrollMaxVelocityDefault; 91 | AtkDragAndDropScrollViewPropertyHolder *result = (AtkDragAndDropScrollViewPropertyHolder *)objc_getAssociatedObject(self, &AtkDragAndDropScrollViewPropertyHolderKey); 92 | if (result != nil) { 93 | ret = result.autoScrollMaxVelocity; 94 | } 95 | return ret; 96 | } 97 | 98 | - (void)setAutoScrollMaxVelocity:(CGFloat)autoScrollMaxVelocity 99 | { 100 | AtkDragAndDropScrollViewPropertyHolder *result = (AtkDragAndDropScrollViewPropertyHolder *)objc_getAssociatedObject(self, &AtkDragAndDropScrollViewPropertyHolderKey); 101 | if (result == nil) { 102 | result = [[AtkDragAndDropScrollViewPropertyHolder alloc] init]; 103 | objc_setAssociatedObject(self, &AtkDragAndDropScrollViewPropertyHolderKey, result, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 104 | } 105 | 106 | result.autoScrollMaxVelocity = autoScrollMaxVelocity; 107 | } 108 | 109 | - (CGPoint)autoScrollDragPinnedPoint 110 | { 111 | CGPoint ret = CGPointZero; 112 | AtkDragAndDropScrollViewPropertyHolder *result = (AtkDragAndDropScrollViewPropertyHolder *)objc_getAssociatedObject(self, &AtkDragAndDropScrollViewPropertyHolderKey); 113 | if (result != nil) { 114 | ret = result.autoScrollDragPinnedPoint; 115 | } 116 | return ret; 117 | } 118 | 119 | - (void)setAutoScrollDragPinnedPoint:(CGPoint)autoScrollDragPinnedPoint 120 | { 121 | AtkDragAndDropScrollViewPropertyHolder *result = (AtkDragAndDropScrollViewPropertyHolder *)objc_getAssociatedObject(self, &AtkDragAndDropScrollViewPropertyHolderKey); 122 | if (result == nil) { 123 | result = [[AtkDragAndDropScrollViewPropertyHolder alloc] init]; 124 | objc_setAssociatedObject(self, &AtkDragAndDropScrollViewPropertyHolderKey, result, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 125 | } 126 | 127 | result.autoScrollDragPinnedPoint = autoScrollDragPinnedPoint; 128 | } 129 | 130 | - (CGPoint)autoScrollLastDragPoint 131 | { 132 | CGPoint ret = CGPointZero; 133 | AtkDragAndDropScrollViewPropertyHolder *result = (AtkDragAndDropScrollViewPropertyHolder *)objc_getAssociatedObject(self, &AtkDragAndDropScrollViewPropertyHolderKey); 134 | if (result != nil) { 135 | ret = result.autoScrollLastDragPoint; 136 | } 137 | return ret; 138 | } 139 | 140 | - (void)setAutoScrollLastDragPoint:(CGPoint)autoScrollLastDragPoint 141 | { 142 | AtkDragAndDropScrollViewPropertyHolder *result = (AtkDragAndDropScrollViewPropertyHolder *)objc_getAssociatedObject(self, &AtkDragAndDropScrollViewPropertyHolderKey); 143 | if (result == nil) { 144 | result = [[AtkDragAndDropScrollViewPropertyHolder alloc] init]; 145 | objc_setAssociatedObject(self, &AtkDragAndDropScrollViewPropertyHolderKey, result, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 146 | } 147 | 148 | result.autoScrollLastDragPoint = autoScrollLastDragPoint; 149 | } 150 | 151 | - (NSTimer *)autoScrollTimer 152 | { 153 | NSTimer *ret = nil; 154 | AtkDragAndDropScrollViewPropertyHolder *result = (AtkDragAndDropScrollViewPropertyHolder *)objc_getAssociatedObject(self, &AtkDragAndDropScrollViewPropertyHolderKey); 155 | if (result != nil) { 156 | ret = result.autoScrollTimer; 157 | } 158 | return ret; 159 | } 160 | 161 | - (void)setAutoScrollTimer:(NSTimer *)timer 162 | { 163 | AtkDragAndDropScrollViewPropertyHolder *result = (AtkDragAndDropScrollViewPropertyHolder *)objc_getAssociatedObject(self, &AtkDragAndDropScrollViewPropertyHolderKey); 164 | if (result == nil) { 165 | result = [[AtkDragAndDropScrollViewPropertyHolder alloc] init]; 166 | objc_setAssociatedObject(self, &AtkDragAndDropScrollViewPropertyHolderKey, result, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 167 | } 168 | 169 | result.autoScrollTimer = timer; 170 | } 171 | 172 | /** 173 | * Given a point, this method calculates the scroll delta, or the amount the scroller should scroll 174 | * in both the x and y direction. 175 | */ 176 | - (CGPoint)autoScrollDelta:(CGPoint)point 177 | { 178 | CGPoint delta = CGPointZero; 179 | CGFloat autoScrollEdgeTollerance = self.autoScrollEdgeTollerance; 180 | CGFloat autoScrollVelocity = self.autoScrollVelocity; 181 | CGPoint autoScrollDragPinnedPoint = self.autoScrollDragPinnedPoint; 182 | CGFloat autoScrollMaxVelocity = self.autoScrollMaxVelocity; 183 | 184 | if(point.x < autoScrollEdgeTollerance) 185 | { 186 | // Our point is on the left edge of the scroller, within the given tolerance 187 | // We want to pin a point (autoScrollDragPinnedPoint) if that pin point is 0 or the 188 | // new point is to the right of the old point. When the new point is to the right 189 | // we do not scroll to the left. If we have a pin point and the new point is to the 190 | // left of that pin point, we then scroll left. This consideration of 191 | // where the new point is in relation to the pin point prevent us from scrolling 192 | // when we enter the UIScrollView with a drag operation. We actually have to 193 | // move in the direction we want to scroll. This makes a much more user friendly 194 | // drag/scroll operation. 195 | if(autoScrollDragPinnedPoint.x == 0.0 || point.x > autoScrollDragPinnedPoint.x) 196 | { 197 | autoScrollDragPinnedPoint = CGPointMake(point.x, autoScrollDragPinnedPoint.y); 198 | } 199 | else 200 | { 201 | delta.x = (point.x - autoScrollDragPinnedPoint.x) * autoScrollVelocity; 202 | if(delta.x < -autoScrollMaxVelocity) delta.x = -autoScrollMaxVelocity; 203 | } 204 | } 205 | else if(point.x > (self.frame.size.width - autoScrollEdgeTollerance)) 206 | { 207 | if(autoScrollDragPinnedPoint.x == 0.0 || point.x < autoScrollDragPinnedPoint.x) 208 | { 209 | autoScrollDragPinnedPoint = CGPointMake(point.x, autoScrollDragPinnedPoint.y); 210 | } 211 | else 212 | { 213 | delta.x = (point.x - autoScrollDragPinnedPoint.x) * autoScrollVelocity; 214 | if(delta.x > autoScrollMaxVelocity) delta.x = autoScrollMaxVelocity; 215 | } 216 | } 217 | else 218 | { 219 | // We are not in scroll teritory on the x axis. Reset the x pin to 0.0. 220 | autoScrollDragPinnedPoint = CGPointMake(0.0, autoScrollDragPinnedPoint.y); 221 | } 222 | 223 | if(delta.x != 0.0) 224 | { 225 | if(self.contentOffset.x + delta.x < 0.0) 226 | { 227 | delta.x = -self.contentOffset.x; 228 | } 229 | else 230 | { 231 | CGFloat maxOffset = self.contentSize.width - self.frame.size.width; 232 | if(maxOffset < 0.0) 233 | maxOffset = 0.0; 234 | 235 | if(self.contentOffset.x + delta.x > maxOffset) 236 | delta.x = maxOffset - self.contentOffset.x; 237 | } 238 | } 239 | 240 | if(point.y < autoScrollEdgeTollerance) 241 | { 242 | if(autoScrollDragPinnedPoint.y == 0.0 || point.y > autoScrollDragPinnedPoint.y) 243 | { 244 | autoScrollDragPinnedPoint = CGPointMake(autoScrollDragPinnedPoint.x, point.y); 245 | } 246 | else 247 | { 248 | delta.y = (point.y - autoScrollDragPinnedPoint.y) * autoScrollVelocity; 249 | if(delta.y < -autoScrollMaxVelocity) delta.y = -autoScrollMaxVelocity; 250 | } 251 | } 252 | else if(point.y > (self.frame.size.height - autoScrollEdgeTollerance)) 253 | { 254 | if(autoScrollDragPinnedPoint.y == 0.0 || point.y < autoScrollDragPinnedPoint.y) 255 | { 256 | autoScrollDragPinnedPoint = CGPointMake(autoScrollDragPinnedPoint.x, point.y); 257 | } 258 | else 259 | { 260 | delta.y = (point.y - autoScrollDragPinnedPoint.y) * autoScrollVelocity; 261 | if(delta.y > autoScrollMaxVelocity) delta.y = autoScrollMaxVelocity; 262 | } 263 | } 264 | else 265 | { 266 | autoScrollDragPinnedPoint = CGPointMake(autoScrollDragPinnedPoint.x, 0.0); 267 | } 268 | 269 | if(delta.y != 0.0) 270 | { 271 | if(self.contentOffset.y + delta.y < 0.0) 272 | { 273 | delta.y = -self.contentOffset.y; 274 | } 275 | else 276 | { 277 | CGFloat maxOffset = self.contentSize.height - self.frame.size.height; 278 | if(maxOffset < 0.0) 279 | maxOffset = 0.0; 280 | 281 | if(self.contentOffset.y + delta.y > maxOffset) 282 | delta.y = maxOffset - self.contentOffset.y; 283 | } 284 | } 285 | 286 | if(delta.x < 0.000001 && delta.x > -0.000001) 287 | delta.x = 0.0; 288 | 289 | if(delta.y < 0.000001 && delta.y > -0.000001) 290 | delta.y = 0.0; 291 | 292 | self.autoScrollDragPinnedPoint = autoScrollDragPinnedPoint; 293 | 294 | return delta; 295 | } 296 | 297 | - (void)autoScrollDragStarted 298 | { 299 | self.autoScrollDragPinnedPoint = CGPointZero; 300 | } 301 | 302 | - (void)autoScrollDragMoved:(CGPoint)point 303 | { 304 | //NSLog(@"AtkSampleOneDropZoneScrollView.dragMoved"); 305 | 306 | CGPoint offset = self.contentOffset; 307 | NSTimer *autoScrollTimer = self.autoScrollTimer; 308 | 309 | // 310 | // iOS wants to convert the point to the content and not the UIScrollView frame. This 311 | // converts to the UIScrollView frame. Silly iOS. 312 | // 313 | point = CGPointMake(point.x - offset.x, point.y - offset.y); 314 | self.autoScrollLastDragPoint = point; 315 | 316 | if(autoScrollTimer) 317 | return; 318 | 319 | CGPoint autoScrollDelta = [self autoScrollDelta:point]; 320 | 321 | if(!CGPointEqualToPoint(autoScrollDelta, CGPointZero)) 322 | { 323 | CGPoint p = self.contentOffset; 324 | p.x += autoScrollDelta.x; 325 | p.y += autoScrollDelta.y; 326 | 327 | [self setContentOffset:p animated:NO]; 328 | 329 | if(autoScrollTimer == nil) 330 | self.autoScrollTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(autoScrollTimerTick:) userInfo:nil repeats:YES]; 331 | } 332 | else if(autoScrollTimer) 333 | { 334 | [autoScrollTimer invalidate]; 335 | self.autoScrollTimer = nil; 336 | } 337 | } 338 | 339 | - (void)autoScrollDragEnded 340 | { 341 | if(self.autoScrollTimer) 342 | { 343 | [self.autoScrollTimer invalidate]; 344 | self.autoScrollTimer = nil; 345 | } 346 | } 347 | 348 | - (void)autoScrollTimerTick:(NSTimer *)timer 349 | { 350 | CGPoint autoScrollDelta = [self autoScrollDelta:self.autoScrollLastDragPoint]; 351 | 352 | if(!CGPointEqualToPoint(autoScrollDelta, CGPointZero)) 353 | { 354 | CGPoint p = self.contentOffset; 355 | p.x += autoScrollDelta.x; 356 | p.y += autoScrollDelta.y; 357 | 358 | [self setContentOffset:p animated:NO]; 359 | } 360 | else if(self.autoScrollTimer) 361 | { 362 | [self.autoScrollTimer invalidate]; 363 | self.autoScrollTimer = nil; 364 | } 365 | } 366 | 367 | @end 368 | -------------------------------------------------------------------------------- /Classes/AtkDragAndDropManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // AtkDragAndDropManager.m 3 | // AtkDragAndDrop 4 | // 5 | // Created by Rick Boykin on 1/17/14. 6 | // Copyright (c) 2014 Asymptotik Limited. All rights reserved. 7 | // 8 | 9 | #import "AtkDragAndDropManager.h" 10 | #import "UIView+AtkDragAndDrop.h" 11 | #import "AtkDropZoneProtocol.h" 12 | #import "AtkDropZoneWrapper.h" 13 | #import "AtkDefaultDragAndDropManagerDelegate.h" 14 | 15 | @interface AtkDragAndDropManager () 16 | 17 | @property (nonatomic, strong) UIView *rootView; 18 | @property (nonatomic, strong) id dragSource; 19 | @property (nonatomic, assign) CGPoint locationOffset; 20 | @property (nonatomic, strong) UIView *dragShadowView; 21 | @property (nonatomic, strong) UIPanGestureRecognizer *recognizer; 22 | @property (nonatomic, strong) NSArray *uninterestedDropZones; 23 | @property (nonatomic, strong) NSArray *interestedDropZones; 24 | @property (nonatomic, strong) id defaultDelegate; 25 | 26 | @end 27 | 28 | @implementation AtkDragAndDropManager 29 | 30 | NSString *const AtkPasteboardNameDragAndDrop = @"com.comcast.bcv.draganddrop.pasteboard"; 31 | 32 | - (id)init 33 | { 34 | if((self = [super init])) 35 | { 36 | self.pasteboardName = AtkPasteboardNameDragAndDrop; 37 | } 38 | 39 | return self; 40 | } 41 | 42 | - (void)dealloc 43 | { 44 | self.dragSource = nil; 45 | self.dragShadowView = nil; 46 | 47 | } 48 | 49 | - (void)start 50 | { 51 | //NSLog(@"AtkDragAndDropManager.start"); 52 | 53 | [self start:[[UIApplication sharedApplication] keyWindow]]; 54 | } 55 | 56 | - (void)start:(UIView *)rootView 57 | { 58 | //NSLog(@"AtkDragAndDropManager.start:"); 59 | [self start:rootView recognizerClass:[UIPanGestureRecognizer class]]; 60 | } 61 | 62 | - (void)start:(UIView *)rootView recognizerClass:(Class)recognizerClass 63 | { 64 | //NSLog(@"AtkDragAndDropManager.start:recognizerClass: %@", [recognizerClass description]); 65 | 66 | assert([recognizerClass isSubclassOfClass:[UIGestureRecognizer class]]); 67 | 68 | if(_rootView) 69 | [self stop]; 70 | 71 | if(rootView) 72 | { 73 | 74 | self.rootView = rootView; 75 | self.recognizer = [[recognizerClass alloc] initWithTarget:self action:@selector(handleGesture:)]; 76 | self.recognizer.delegate = self; 77 | [self.rootView addGestureRecognizer:self.recognizer]; 78 | } 79 | } 80 | 81 | - (void)stop 82 | { 83 | if(self.recognizer && self.rootView) 84 | { 85 | [self.rootView removeGestureRecognizer:self.recognizer]; 86 | } 87 | 88 | if(self.dragSource) 89 | { 90 | [self onDragEnded:nil]; 91 | } 92 | 93 | self.recognizer = nil; 94 | self.rootView = nil; 95 | } 96 | 97 | - (UIPasteboard *)pasteboard 98 | { 99 | return [UIPasteboard pasteboardWithName:self.pasteboardName create:YES]; 100 | } 101 | 102 | - (id)findDragSource:(UIGestureRecognizer *)recognizer 103 | { 104 | if(_delegate && [_delegate respondsToSelector:@selector(findDragSource:recognizer:)]) 105 | return [_delegate findDragSource:self recognizer:recognizer]; 106 | else 107 | return [self.defaultDelegate findDragSource:self recognizer:recognizer]; 108 | } 109 | 110 | - (NSArray *)findDropZones:(UIGestureRecognizer *)recognizer 111 | { 112 | if(_delegate && [_delegate respondsToSelector:@selector(findDropZones:recognizer:)]) 113 | return [_delegate findDropZones:self recognizer:recognizer]; 114 | else 115 | return [self.defaultDelegate findDropZones:self recognizer:recognizer]; 116 | } 117 | 118 | - (BOOL)isDropZoneActive:(id)dropZone recognizer:(UIGestureRecognizer *)recognizer 119 | { 120 | if(_delegate && [_delegate respondsToSelector:@selector(isDropZoneActive:dropZone:recognizer:)]) 121 | return [_delegate isDropZoneActive:self dropZone:dropZone recognizer:recognizer]; 122 | else 123 | return [self.defaultDelegate isDropZoneActive:self dropZone:dropZone recognizer:recognizer]; 124 | } 125 | 126 | - (void)dragWillStart 127 | { 128 | if([self.dragSource respondsToSelector:@selector(dragWillStart:)]) 129 | [self.dragSource dragWillStart:self]; 130 | 131 | if(_delegate && [_delegate respondsToSelector:@selector(dragWillStart:)]) 132 | [_delegate dragWillStart:self]; 133 | } 134 | 135 | - (void)dragStarted 136 | { 137 | for(AtkDropZoneWrapper *dropZone in self.uninterestedDropZones) 138 | { 139 | if([dropZone.dropZone respondsToSelector:@selector(dropZoneDragStarted:)]) 140 | [dropZone.dropZone dropZoneDragStarted:self]; 141 | } 142 | 143 | for(AtkDropZoneWrapper *dropZone in self.interestedDropZones) 144 | { 145 | if([dropZone.dropZone respondsToSelector:@selector(dropZoneDragStarted:)]) 146 | [dropZone.dropZone dropZoneDragStarted:self]; 147 | } 148 | 149 | if([self.dragSource respondsToSelector:@selector(dragStarted:)]) 150 | [self.dragSource dragStarted:self]; 151 | 152 | if(_delegate && [_delegate respondsToSelector:@selector(dragStarted:)]) 153 | [_delegate dragStarted:self]; 154 | } 155 | 156 | - (void)dragEnded 157 | { 158 | for(AtkDropZoneWrapper *dropZone in self.uninterestedDropZones) 159 | { 160 | if([dropZone.dropZone respondsToSelector:@selector(dropZoneDragEnded:)]) 161 | [dropZone.dropZone dropZoneDragEnded:self]; 162 | } 163 | 164 | for(AtkDropZoneWrapper *dropZone in self.interestedDropZones) 165 | { 166 | if([dropZone.dropZone respondsToSelector:@selector(dropZoneDragEnded:)]) 167 | [dropZone.dropZone dropZoneDragEnded:self]; 168 | } 169 | 170 | if([self.dragSource respondsToSelector:@selector(dragEnded:)]) 171 | [self.dragSource dragEnded:self]; 172 | 173 | if(_delegate && [_delegate respondsToSelector:@selector(dragEnded:)]) 174 | [_delegate dragEnded:self]; 175 | } 176 | 177 | - (void)dragEntered:(id)dropZone point:(CGPoint)point 178 | { 179 | if([dropZone respondsToSelector:@selector(dropZoneDragEntered:point:)]) 180 | [dropZone dropZoneDragEntered:self point:point]; 181 | 182 | if([self.dragSource respondsToSelector:@selector(dragEntered:dropZone:point:)]) 183 | [self.dragSource dragEntered:self dropZone:dropZone point:point]; 184 | 185 | if(_delegate && [_delegate respondsToSelector:@selector(dragEntered:dropZone:point:)]) 186 | [_delegate dragEntered:self dropZone:dropZone point:point]; 187 | } 188 | 189 | - (void)dragExited:(id)dropZone point:(CGPoint)point 190 | { 191 | if([dropZone respondsToSelector:@selector(dropZoneDragExited:point:)]) 192 | [dropZone dropZoneDragExited:self point:point]; 193 | 194 | if([self.dragSource respondsToSelector:@selector(dragExited:dropZone:point:)]) 195 | [self.dragSource dragExited:self dropZone:dropZone point:point]; 196 | 197 | if(_delegate && [_delegate respondsToSelector:@selector(dragExited:dropZone:point:)]) 198 | [_delegate dragExited:self dropZone:dropZone point:point]; 199 | } 200 | 201 | - (void)dragMoved:(id)dropZone point:(CGPoint)point 202 | { 203 | if([dropZone respondsToSelector:@selector(dropZoneDragMoved:point:)]) 204 | [dropZone dropZoneDragMoved:self point:point]; 205 | 206 | if([self.dragSource respondsToSelector:@selector(dragMoved:dropZone:point:)]) 207 | [self.dragSource dragMoved:self dropZone:dropZone point:point]; 208 | 209 | if(_delegate && [_delegate respondsToSelector:@selector(dragMoved:dropZone:point:)]) 210 | [_delegate dragMoved:self dropZone:dropZone point:point]; 211 | } 212 | 213 | - (void)dragDropped:(id)dropZone point:(CGPoint)point 214 | { 215 | if([dropZone respondsToSelector:@selector(dropZoneDragDropped:point:)]) 216 | [dropZone dropZoneDragDropped:self point:point]; 217 | 218 | if([self.dragSource respondsToSelector:@selector(dragDropped:dropZone:point:)]) 219 | [self.dragSource dragDropped:self dropZone:dropZone point:point]; 220 | 221 | if(_delegate && [_delegate respondsToSelector:@selector(dragDropped:dropZone:point:)]) 222 | [_delegate dragDropped:self dropZone:dropZone point:point]; 223 | } 224 | 225 | #pragma mark - private methods 226 | 227 | /** 228 | * Sets the drag source. 229 | */ 230 | - (void)setDragSource:(id)dragSource 231 | { 232 | if(_dragSource != dragSource) 233 | { 234 | _dragSource = dragSource; 235 | 236 | if(_dragSource) 237 | { 238 | if([_dragSource respondsToSelector:@selector(createDragShadowView:)]) 239 | self.dragShadowView = [_dragSource createDragShadowView:self]; 240 | else if([_dragSource respondsToSelector:@selector(createDefaultDragShadowView:)]) 241 | self.dragShadowView = [_dragSource performSelector:@selector(createDefaultDragShadowView:) withObject:self]; 242 | } 243 | else 244 | { 245 | self.dragShadowView = nil; 246 | } 247 | } 248 | } 249 | 250 | /** 251 | * Sets the drag shadow view. 252 | */ 253 | - (void)setDragShadowView:(UIView *)view 254 | { 255 | if(_dragShadowView != view) 256 | { 257 | if(_dragShadowView) 258 | { 259 | [_dragShadowView removeFromSuperview]; 260 | } 261 | 262 | _dragShadowView = view; 263 | 264 | if(_dragShadowView) 265 | { 266 | [self.rootView addSubview:_dragShadowView]; 267 | } 268 | } 269 | } 270 | 271 | - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)recognizer 272 | { 273 | //NSLog(@"AtkDragAndDropManager:gestureRecognizerShouldBegin"); 274 | // Only begin if we have a dragSource. 275 | return [self onDragStart:recognizer]; 276 | } 277 | 278 | /** 279 | * Handles the gesture. 280 | */ 281 | - (IBAction)handleGesture:(UIPanGestureRecognizer *)recognizer 282 | { 283 | switch(recognizer.state) 284 | { 285 | case UIGestureRecognizerStateBegan: 286 | break; 287 | case UIGestureRecognizerStateChanged: 288 | if(_dragSource) 289 | { 290 | [self onDragMoved:recognizer]; 291 | } 292 | break; 293 | case UIGestureRecognizerStateEnded: // same as UIGestureRecognizerStateRecognized 294 | if(_dragSource) 295 | { 296 | [self onDragDropped:recognizer]; 297 | [self onDragEnded:recognizer]; 298 | } 299 | break; 300 | case UIGestureRecognizerStateCancelled: 301 | if(_dragSource) 302 | { 303 | //NSLog(@"UIGestureRecognizerStateCancelled"); 304 | [self onDragEnded:recognizer]; 305 | } 306 | break; 307 | case UIGestureRecognizerStateFailed: 308 | if(_dragSource) 309 | { 310 | //NSLog(@"UIGestureRecognizerStateFailed"); 311 | [self onDragEnded:recognizer]; 312 | } 313 | break; 314 | case UIGestureRecognizerStatePossible: 315 | //NSLog(@"UIGestureRecognizerStatePossible"); 316 | break; 317 | } 318 | } 319 | 320 | /** 321 | * Checks the movement of the recognizer and determines wheather and dropZones change their active status. 322 | */ 323 | - (void)checkMovement:(UIGestureRecognizer *)recognizer 324 | { 325 | CGPoint pointInRootView = [recognizer locationInView:self.rootView]; 326 | 327 | for(AtkDropZoneWrapper *dropZone in self.interestedDropZones) 328 | { 329 | if([self isDropZoneActive:dropZone.dropZone recognizer:recognizer]) 330 | { 331 | if(!dropZone.isActive) 332 | { 333 | // transitioned to inside 334 | dropZone.isActive = YES; 335 | 336 | [self dragEntered:dropZone.dropZone point:pointInRootView]; 337 | } 338 | else 339 | { 340 | [self dragMoved:dropZone.dropZone point:pointInRootView]; 341 | } 342 | } 343 | else if(dropZone.isActive) 344 | { 345 | // transitioned to outside 346 | dropZone.isActive = NO; 347 | [self dragExited:dropZone.dropZone point:pointInRootView]; 348 | } 349 | } 350 | } 351 | 352 | /** 353 | * Called when a drag operation starts. Returns true if a self.dragSource was set indicating 354 | * that a drag source was found and dragging will commence. 355 | */ 356 | - (BOOL)onDragStart:(UIGestureRecognizer *)recognizer 357 | { 358 | //NSLog(@"AtkDragAndDropManager.dragStart"); 359 | 360 | self.dragShadowView = nil; 361 | self.interestedDropZones = nil; 362 | self.uninterestedDropZones = nil; 363 | 364 | if((self.dragSource = [self findDragSource:recognizer])) 365 | { 366 | [self dragWillStart]; 367 | 368 | NSArray *dropZones = [self findDropZones:recognizer]; 369 | 370 | // Wrap the drop zones with AtkDropZoneWrapper to track it's state. 371 | NSMutableArray *interestedDropZones = nil; 372 | NSMutableArray *uninterestedDropZones = nil; 373 | 374 | if(dropZones) 375 | { 376 | for(id dropZone in dropZones) 377 | { 378 | if([dropZone respondsToSelector:@selector(dropZoneIsInterested:)] && [dropZone dropZoneIsInterested:self]) 379 | { 380 | if(!interestedDropZones) 381 | interestedDropZones = [NSMutableArray arrayWithCapacity:[dropZones count]]; 382 | [interestedDropZones addObject:[[AtkDropZoneWrapper alloc] initWithDropZone:dropZone interested:YES]]; 383 | } 384 | else 385 | { 386 | if(!uninterestedDropZones) 387 | uninterestedDropZones = [NSMutableArray arrayWithCapacity:[dropZones count]]; 388 | [uninterestedDropZones addObject:[[AtkDropZoneWrapper alloc] initWithDropZone:dropZone interested:NO]]; 389 | } 390 | } 391 | } 392 | 393 | self.interestedDropZones = interestedDropZones; 394 | self.uninterestedDropZones = uninterestedDropZones; 395 | 396 | [self dragStarted]; 397 | self.locationOffset = [recognizer locationInView:self.rootView]; 398 | [self positionDragShadow:recognizer]; 399 | } 400 | 401 | return _dragSource == nil ? NO : YES; 402 | } 403 | 404 | /** 405 | * Called when a drag operation ends. 406 | */ 407 | - (void)onDragEnded:(UIGestureRecognizer *)recognizer 408 | { 409 | //NSLog(@"AtkDragAndDropManager.dragEnded"); 410 | 411 | [self dragEnded]; 412 | 413 | self.dragShadowView = nil; 414 | self.dragSource = nil; 415 | self.interestedDropZones = nil; 416 | self.uninterestedDropZones = nil; 417 | } 418 | 419 | /** 420 | * Called when a drag moves. 421 | */ 422 | - (void)onDragMoved:(UIGestureRecognizer *)recognizer 423 | { 424 | //NSLog(@"AtkDragAndDropManager.dragMoved"); 425 | 426 | [self checkMovement:recognizer]; 427 | [self positionDragShadow:recognizer]; 428 | } 429 | 430 | /** 431 | * Called when a drag is dropped. 432 | */ 433 | - (void)onDragDropped:(UIGestureRecognizer *)recognizer 434 | { 435 | //NSLog(@"AtkDragAndDropManager.dragDropped"); 436 | 437 | for(NSInteger n = [self.interestedDropZones count] - 1; n >= 0; n--) 438 | { 439 | AtkDropZoneWrapper *interestedDropZone = [self.interestedDropZones objectAtIndex:n]; 440 | if(interestedDropZone.isActive) 441 | [self dragDropped:interestedDropZone.dropZone point:[recognizer locationInView:self.rootView]]; 442 | } 443 | } 444 | 445 | /** 446 | * Positions the drag shadow. 447 | */ 448 | - (void)positionDragShadow:(UIGestureRecognizer *)recognizer 449 | { 450 | if(_dragShadowView) 451 | { 452 | CGPoint point = [recognizer locationInView:self.rootView]; 453 | CGRect frame = _dragShadowView.frame; 454 | 455 | CGPoint offset = CGPointMake(point.x - self.locationOffset.x, point.y - self.locationOffset.y); 456 | //NSLog(@"offset %f %f frame %f %f", offset.x, offset.y, frame.origin.x, frame.origin.y); 457 | 458 | frame.origin = CGPointMake(offset.x + frame.origin.x, offset.y + frame.origin.y); 459 | self.locationOffset = point; 460 | _dragShadowView.frame = frame; 461 | } 462 | } 463 | 464 | - (id)defaultDelegate 465 | { 466 | if(!_defaultDelegate) 467 | { 468 | self.defaultDelegate = [[AtkDefaultDragAndDropManagerDelegate alloc] init]; 469 | } 470 | 471 | return _defaultDelegate; 472 | } 473 | 474 | - (void)setDelegate:(id)delegate 475 | { 476 | if(_delegate != delegate) 477 | { 478 | _delegate = delegate; 479 | } 480 | 481 | if(_delegate) 482 | self.defaultDelegate = nil; 483 | } 484 | 485 | @end 486 | -------------------------------------------------------------------------------- /Examples/AtkDragAndDrop_Examples.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1D0A2DA5189848D000175F59 /* AtkSampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D0A2D8F189848D000175F59 /* AtkSampleViewController.m */; }; 11 | 1D0A2DA6189848D000175F59 /* AtkSampleViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1D0A2D90189848D000175F59 /* AtkSampleViewController.xib */; }; 12 | 1D0A2DA7189848D000175F59 /* AtkSampleOneDragSourceView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D0A2D93189848D000175F59 /* AtkSampleOneDragSourceView.m */; }; 13 | 1D0A2DA8189848D000175F59 /* AtkSampleOneDropZoneScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D0A2D95189848D000175F59 /* AtkSampleOneDropZoneScrollView.m */; }; 14 | 1D0A2DA9189848D000175F59 /* AtkSampleOneDropZoneView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D0A2D97189848D000175F59 /* AtkSampleOneDropZoneView.m */; }; 15 | 1D0A2DAA189848D000175F59 /* AtkSampleOneViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D0A2D99189848D000175F59 /* AtkSampleOneViewController.m */; }; 16 | 1D0A2DAB189848D000175F59 /* AtkSampleOneViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1D0A2D9A189848D000175F59 /* AtkSampleOneViewController.xib */; }; 17 | 1D0A2DAC189848D000175F59 /* AtkSampleTwoDragSourceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D0A2D9D189848D000175F59 /* AtkSampleTwoDragSourceWrapper.m */; }; 18 | 1D0A2DAD189848D000175F59 /* AtkSampleTwoDropZoneScrollViewWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D0A2D9F189848D000175F59 /* AtkSampleTwoDropZoneScrollViewWrapper.m */; }; 19 | 1D0A2DAE189848D000175F59 /* AtkSampleTwoDropZoneWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D0A2DA1189848D000175F59 /* AtkSampleTwoDropZoneWrapper.m */; }; 20 | 1D0A2DAF189848D000175F59 /* AtkSampleTwoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D0A2DA3189848D000175F59 /* AtkSampleTwoViewController.m */; }; 21 | 1D0A2DB0189848D000175F59 /* AtkSampleTwoViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1D0A2DA4189848D000175F59 /* AtkSampleTwoViewController.xib */; }; 22 | 1D847C3A1898471E00F419F6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D847C391898471E00F419F6 /* Foundation.framework */; }; 23 | 1D847C3C1898471E00F419F6 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D847C3B1898471E00F419F6 /* CoreGraphics.framework */; }; 24 | 1D847C3E1898471E00F419F6 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D847C3D1898471E00F419F6 /* UIKit.framework */; }; 25 | 1D847C441898471E00F419F6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1D847C421898471E00F419F6 /* InfoPlist.strings */; }; 26 | 1D847C461898471E00F419F6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D847C451898471E00F419F6 /* main.m */; }; 27 | 1D847C4A1898471E00F419F6 /* AtkAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D847C491898471E00F419F6 /* AtkAppDelegate.m */; }; 28 | 1D847C4C1898471E00F419F6 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1D847C4B1898471E00F419F6 /* Images.xcassets */; }; 29 | 1DE3C72118988AD2002C1C4E /* AtkDefaultDragAndDropManagerDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1DE3C71318988AD2002C1C4E /* AtkDefaultDragAndDropManagerDelegate.m */; }; 30 | 1DE3C72218988AD2002C1C4E /* AtkDragAndDropManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1DE3C71618988AD2002C1C4E /* AtkDragAndDropManager.m */; }; 31 | 1DE3C72318988AD2002C1C4E /* AtkDropZoneWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 1DE3C71A18988AD2002C1C4E /* AtkDropZoneWrapper.m */; }; 32 | 1DE3C72418988AD2002C1C4E /* UIScrollView+AtkDragAndDrop.m in Sources */ = {isa = PBXBuildFile; fileRef = 1DE3C71C18988AD2002C1C4E /* UIScrollView+AtkDragAndDrop.m */; }; 33 | 1DE3C72518988AD2002C1C4E /* UIView+AtkDragAndDrop.m in Sources */ = {isa = PBXBuildFile; fileRef = 1DE3C71E18988AD2002C1C4E /* UIView+AtkDragAndDrop.m */; }; 34 | 1DE3C72618988AD2002C1C4E /* UIView+AtkImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 1DE3C72018988AD2002C1C4E /* UIView+AtkImage.m */; }; 35 | /* End PBXBuildFile section */ 36 | 37 | /* Begin PBXFileReference section */ 38 | 1D0928B418B0827B00ACDAE7 /* AtkDragAndDrop.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; name = AtkDragAndDrop.podspec; path = ../AtkDragAndDrop.podspec; sourceTree = ""; }; 39 | 1D0A2D8E189848D000175F59 /* AtkSampleViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtkSampleViewController.h; sourceTree = ""; }; 40 | 1D0A2D8F189848D000175F59 /* AtkSampleViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AtkSampleViewController.m; sourceTree = ""; }; 41 | 1D0A2D90189848D000175F59 /* AtkSampleViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AtkSampleViewController.xib; sourceTree = ""; }; 42 | 1D0A2D92189848D000175F59 /* AtkSampleOneDragSourceView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtkSampleOneDragSourceView.h; sourceTree = ""; }; 43 | 1D0A2D93189848D000175F59 /* AtkSampleOneDragSourceView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AtkSampleOneDragSourceView.m; sourceTree = ""; }; 44 | 1D0A2D94189848D000175F59 /* AtkSampleOneDropZoneScrollView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtkSampleOneDropZoneScrollView.h; sourceTree = ""; }; 45 | 1D0A2D95189848D000175F59 /* AtkSampleOneDropZoneScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AtkSampleOneDropZoneScrollView.m; sourceTree = ""; }; 46 | 1D0A2D96189848D000175F59 /* AtkSampleOneDropZoneView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtkSampleOneDropZoneView.h; sourceTree = ""; }; 47 | 1D0A2D97189848D000175F59 /* AtkSampleOneDropZoneView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AtkSampleOneDropZoneView.m; sourceTree = ""; }; 48 | 1D0A2D98189848D000175F59 /* AtkSampleOneViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtkSampleOneViewController.h; sourceTree = ""; }; 49 | 1D0A2D99189848D000175F59 /* AtkSampleOneViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AtkSampleOneViewController.m; sourceTree = ""; }; 50 | 1D0A2D9A189848D000175F59 /* AtkSampleOneViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AtkSampleOneViewController.xib; sourceTree = ""; }; 51 | 1D0A2D9C189848D000175F59 /* AtkSampleTwoDragSourceWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtkSampleTwoDragSourceWrapper.h; sourceTree = ""; }; 52 | 1D0A2D9D189848D000175F59 /* AtkSampleTwoDragSourceWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AtkSampleTwoDragSourceWrapper.m; sourceTree = ""; }; 53 | 1D0A2D9E189848D000175F59 /* AtkSampleTwoDropZoneScrollViewWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtkSampleTwoDropZoneScrollViewWrapper.h; sourceTree = ""; }; 54 | 1D0A2D9F189848D000175F59 /* AtkSampleTwoDropZoneScrollViewWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AtkSampleTwoDropZoneScrollViewWrapper.m; sourceTree = ""; }; 55 | 1D0A2DA0189848D000175F59 /* AtkSampleTwoDropZoneWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtkSampleTwoDropZoneWrapper.h; sourceTree = ""; }; 56 | 1D0A2DA1189848D000175F59 /* AtkSampleTwoDropZoneWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AtkSampleTwoDropZoneWrapper.m; sourceTree = ""; }; 57 | 1D0A2DA2189848D000175F59 /* AtkSampleTwoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtkSampleTwoViewController.h; sourceTree = ""; }; 58 | 1D0A2DA3189848D000175F59 /* AtkSampleTwoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AtkSampleTwoViewController.m; sourceTree = ""; }; 59 | 1D0A2DA4189848D000175F59 /* AtkSampleTwoViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AtkSampleTwoViewController.xib; sourceTree = ""; }; 60 | 1D29A2861910639D0053E0F4 /* AtkDragAndDropLifecycleProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AtkDragAndDropLifecycleProtocol.h; sourceTree = ""; }; 61 | 1D847C361898471E00F419F6 /* AtkDragAndDrop_Examples.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AtkDragAndDrop_Examples.app; sourceTree = BUILT_PRODUCTS_DIR; }; 62 | 1D847C391898471E00F419F6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 63 | 1D847C3B1898471E00F419F6 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 64 | 1D847C3D1898471E00F419F6 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 65 | 1D847C411898471E00F419F6 /* AtkDragAndDrop_Examples-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "AtkDragAndDrop_Examples-Info.plist"; sourceTree = ""; }; 66 | 1D847C431898471E00F419F6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 67 | 1D847C451898471E00F419F6 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 68 | 1D847C471898471E00F419F6 /* AtkDragAndDrop_Examples-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AtkDragAndDrop_Examples-Prefix.pch"; sourceTree = ""; }; 69 | 1D847C481898471E00F419F6 /* AtkAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AtkAppDelegate.h; sourceTree = ""; }; 70 | 1D847C491898471E00F419F6 /* AtkAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AtkAppDelegate.m; sourceTree = ""; }; 71 | 1D847C4B1898471E00F419F6 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 72 | 1DE3C71218988AD2002C1C4E /* AtkDefaultDragAndDropManagerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtkDefaultDragAndDropManagerDelegate.h; sourceTree = ""; }; 73 | 1DE3C71318988AD2002C1C4E /* AtkDefaultDragAndDropManagerDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AtkDefaultDragAndDropManagerDelegate.m; sourceTree = ""; }; 74 | 1DE3C71418988AD2002C1C4E /* AtkDragAndDrop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtkDragAndDrop.h; sourceTree = ""; }; 75 | 1DE3C71518988AD2002C1C4E /* AtkDragAndDropManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtkDragAndDropManager.h; sourceTree = ""; }; 76 | 1DE3C71618988AD2002C1C4E /* AtkDragAndDropManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AtkDragAndDropManager.m; sourceTree = ""; }; 77 | 1DE3C71718988AD2002C1C4E /* AtkDragSourceProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtkDragSourceProtocol.h; sourceTree = ""; }; 78 | 1DE3C71818988AD2002C1C4E /* AtkDropZoneProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtkDropZoneProtocol.h; sourceTree = ""; }; 79 | 1DE3C71918988AD2002C1C4E /* AtkDropZoneWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtkDropZoneWrapper.h; sourceTree = ""; }; 80 | 1DE3C71A18988AD2002C1C4E /* AtkDropZoneWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AtkDropZoneWrapper.m; sourceTree = ""; }; 81 | 1DE3C71B18988AD2002C1C4E /* UIScrollView+AtkDragAndDrop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIScrollView+AtkDragAndDrop.h"; sourceTree = ""; }; 82 | 1DE3C71C18988AD2002C1C4E /* UIScrollView+AtkDragAndDrop.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+AtkDragAndDrop.m"; sourceTree = ""; }; 83 | 1DE3C71D18988AD2002C1C4E /* UIView+AtkDragAndDrop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+AtkDragAndDrop.h"; sourceTree = ""; }; 84 | 1DE3C71E18988AD2002C1C4E /* UIView+AtkDragAndDrop.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+AtkDragAndDrop.m"; sourceTree = ""; }; 85 | 1DE3C71F18988AD2002C1C4E /* UIView+AtkImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+AtkImage.h"; sourceTree = ""; }; 86 | 1DE3C72018988AD2002C1C4E /* UIView+AtkImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+AtkImage.m"; sourceTree = ""; }; 87 | 586968C86D4546FF8BBDD1E5 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 88 | /* End PBXFileReference section */ 89 | 90 | /* Begin PBXFrameworksBuildPhase section */ 91 | 1D847C331898471E00F419F6 /* Frameworks */ = { 92 | isa = PBXFrameworksBuildPhase; 93 | buildActionMask = 2147483647; 94 | files = ( 95 | 1D847C3C1898471E00F419F6 /* CoreGraphics.framework in Frameworks */, 96 | 1D847C3E1898471E00F419F6 /* UIKit.framework in Frameworks */, 97 | 1D847C3A1898471E00F419F6 /* Foundation.framework in Frameworks */, 98 | ); 99 | runOnlyForDeploymentPostprocessing = 0; 100 | }; 101 | /* End PBXFrameworksBuildPhase section */ 102 | 103 | /* Begin PBXGroup section */ 104 | 1D0A2D91189848D000175F59 /* Sample01 */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | 1D0A2D92189848D000175F59 /* AtkSampleOneDragSourceView.h */, 108 | 1D0A2D93189848D000175F59 /* AtkSampleOneDragSourceView.m */, 109 | 1D0A2D94189848D000175F59 /* AtkSampleOneDropZoneScrollView.h */, 110 | 1D0A2D95189848D000175F59 /* AtkSampleOneDropZoneScrollView.m */, 111 | 1D0A2D96189848D000175F59 /* AtkSampleOneDropZoneView.h */, 112 | 1D0A2D97189848D000175F59 /* AtkSampleOneDropZoneView.m */, 113 | 1D0A2D98189848D000175F59 /* AtkSampleOneViewController.h */, 114 | 1D0A2D99189848D000175F59 /* AtkSampleOneViewController.m */, 115 | 1D0A2D9A189848D000175F59 /* AtkSampleOneViewController.xib */, 116 | ); 117 | path = Sample01; 118 | sourceTree = ""; 119 | }; 120 | 1D0A2D9B189848D000175F59 /* Sample02 */ = { 121 | isa = PBXGroup; 122 | children = ( 123 | 1D0A2D9C189848D000175F59 /* AtkSampleTwoDragSourceWrapper.h */, 124 | 1D0A2D9D189848D000175F59 /* AtkSampleTwoDragSourceWrapper.m */, 125 | 1D0A2D9E189848D000175F59 /* AtkSampleTwoDropZoneScrollViewWrapper.h */, 126 | 1D0A2D9F189848D000175F59 /* AtkSampleTwoDropZoneScrollViewWrapper.m */, 127 | 1D0A2DA0189848D000175F59 /* AtkSampleTwoDropZoneWrapper.h */, 128 | 1D0A2DA1189848D000175F59 /* AtkSampleTwoDropZoneWrapper.m */, 129 | 1D0A2DA2189848D000175F59 /* AtkSampleTwoViewController.h */, 130 | 1D0A2DA3189848D000175F59 /* AtkSampleTwoViewController.m */, 131 | 1D0A2DA4189848D000175F59 /* AtkSampleTwoViewController.xib */, 132 | ); 133 | path = Sample02; 134 | sourceTree = ""; 135 | }; 136 | 1D847C2D1898471E00F419F6 = { 137 | isa = PBXGroup; 138 | children = ( 139 | 1D0928B418B0827B00ACDAE7 /* AtkDragAndDrop.podspec */, 140 | 1DE3C71118988AD2002C1C4E /* Classes */, 141 | 1D847C3F1898471E00F419F6 /* AtkDragAndDrop_Examples */, 142 | 1D847C381898471E00F419F6 /* Frameworks */, 143 | 1D847C371898471E00F419F6 /* Products */, 144 | ); 145 | sourceTree = ""; 146 | }; 147 | 1D847C371898471E00F419F6 /* Products */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | 1D847C361898471E00F419F6 /* AtkDragAndDrop_Examples.app */, 151 | ); 152 | name = Products; 153 | sourceTree = ""; 154 | }; 155 | 1D847C381898471E00F419F6 /* Frameworks */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | 1D847C391898471E00F419F6 /* Foundation.framework */, 159 | 1D847C3B1898471E00F419F6 /* CoreGraphics.framework */, 160 | 1D847C3D1898471E00F419F6 /* UIKit.framework */, 161 | 586968C86D4546FF8BBDD1E5 /* libPods.a */, 162 | ); 163 | name = Frameworks; 164 | sourceTree = ""; 165 | }; 166 | 1D847C3F1898471E00F419F6 /* AtkDragAndDrop_Examples */ = { 167 | isa = PBXGroup; 168 | children = ( 169 | 1D847C401898471E00F419F6 /* Supporting Files */, 170 | 1D0A2D91189848D000175F59 /* Sample01 */, 171 | 1D0A2D9B189848D000175F59 /* Sample02 */, 172 | 1D0A2D8E189848D000175F59 /* AtkSampleViewController.h */, 173 | 1D0A2D8F189848D000175F59 /* AtkSampleViewController.m */, 174 | 1D0A2D90189848D000175F59 /* AtkSampleViewController.xib */, 175 | 1D847C481898471E00F419F6 /* AtkAppDelegate.h */, 176 | 1D847C491898471E00F419F6 /* AtkAppDelegate.m */, 177 | 1D847C4B1898471E00F419F6 /* Images.xcassets */, 178 | ); 179 | path = AtkDragAndDrop_Examples; 180 | sourceTree = ""; 181 | }; 182 | 1D847C401898471E00F419F6 /* Supporting Files */ = { 183 | isa = PBXGroup; 184 | children = ( 185 | 1D847C411898471E00F419F6 /* AtkDragAndDrop_Examples-Info.plist */, 186 | 1D847C421898471E00F419F6 /* InfoPlist.strings */, 187 | 1D847C451898471E00F419F6 /* main.m */, 188 | 1D847C471898471E00F419F6 /* AtkDragAndDrop_Examples-Prefix.pch */, 189 | ); 190 | name = "Supporting Files"; 191 | sourceTree = ""; 192 | }; 193 | 1DE3C71118988AD2002C1C4E /* Classes */ = { 194 | isa = PBXGroup; 195 | children = ( 196 | 1DE3C71218988AD2002C1C4E /* AtkDefaultDragAndDropManagerDelegate.h */, 197 | 1DE3C71318988AD2002C1C4E /* AtkDefaultDragAndDropManagerDelegate.m */, 198 | 1DE3C71418988AD2002C1C4E /* AtkDragAndDrop.h */, 199 | 1D29A2861910639D0053E0F4 /* AtkDragAndDropLifecycleProtocol.h */, 200 | 1DE3C71518988AD2002C1C4E /* AtkDragAndDropManager.h */, 201 | 1DE3C71618988AD2002C1C4E /* AtkDragAndDropManager.m */, 202 | 1DE3C71718988AD2002C1C4E /* AtkDragSourceProtocol.h */, 203 | 1DE3C71818988AD2002C1C4E /* AtkDropZoneProtocol.h */, 204 | 1DE3C71918988AD2002C1C4E /* AtkDropZoneWrapper.h */, 205 | 1DE3C71A18988AD2002C1C4E /* AtkDropZoneWrapper.m */, 206 | 1DE3C71B18988AD2002C1C4E /* UIScrollView+AtkDragAndDrop.h */, 207 | 1DE3C71C18988AD2002C1C4E /* UIScrollView+AtkDragAndDrop.m */, 208 | 1DE3C71D18988AD2002C1C4E /* UIView+AtkDragAndDrop.h */, 209 | 1DE3C71E18988AD2002C1C4E /* UIView+AtkDragAndDrop.m */, 210 | 1DE3C71F18988AD2002C1C4E /* UIView+AtkImage.h */, 211 | 1DE3C72018988AD2002C1C4E /* UIView+AtkImage.m */, 212 | ); 213 | name = Classes; 214 | path = ../Classes; 215 | sourceTree = ""; 216 | }; 217 | /* End PBXGroup section */ 218 | 219 | /* Begin PBXNativeTarget section */ 220 | 1D847C351898471E00F419F6 /* AtkDragAndDrop_Examples */ = { 221 | isa = PBXNativeTarget; 222 | buildConfigurationList = 1D847C621898471F00F419F6 /* Build configuration list for PBXNativeTarget "AtkDragAndDrop_Examples" */; 223 | buildPhases = ( 224 | 1D847C321898471E00F419F6 /* Sources */, 225 | 1D847C331898471E00F419F6 /* Frameworks */, 226 | 1D847C341898471E00F419F6 /* Resources */, 227 | ); 228 | buildRules = ( 229 | ); 230 | dependencies = ( 231 | ); 232 | name = AtkDragAndDrop_Examples; 233 | productName = AtkDragAndDrop_Examples; 234 | productReference = 1D847C361898471E00F419F6 /* AtkDragAndDrop_Examples.app */; 235 | productType = "com.apple.product-type.application"; 236 | }; 237 | /* End PBXNativeTarget section */ 238 | 239 | /* Begin PBXProject section */ 240 | 1D847C2E1898471E00F419F6 /* Project object */ = { 241 | isa = PBXProject; 242 | attributes = { 243 | CLASSPREFIX = Atk; 244 | LastUpgradeCheck = 0510; 245 | ORGANIZATIONNAME = "Asymptotik Limited"; 246 | }; 247 | buildConfigurationList = 1D847C311898471E00F419F6 /* Build configuration list for PBXProject "AtkDragAndDrop_Examples" */; 248 | compatibilityVersion = "Xcode 3.2"; 249 | developmentRegion = English; 250 | hasScannedForEncodings = 0; 251 | knownRegions = ( 252 | en, 253 | ); 254 | mainGroup = 1D847C2D1898471E00F419F6; 255 | productRefGroup = 1D847C371898471E00F419F6 /* Products */; 256 | projectDirPath = ""; 257 | projectRoot = ""; 258 | targets = ( 259 | 1D847C351898471E00F419F6 /* AtkDragAndDrop_Examples */, 260 | ); 261 | }; 262 | /* End PBXProject section */ 263 | 264 | /* Begin PBXResourcesBuildPhase section */ 265 | 1D847C341898471E00F419F6 /* Resources */ = { 266 | isa = PBXResourcesBuildPhase; 267 | buildActionMask = 2147483647; 268 | files = ( 269 | 1D0A2DA6189848D000175F59 /* AtkSampleViewController.xib in Resources */, 270 | 1D847C441898471E00F419F6 /* InfoPlist.strings in Resources */, 271 | 1D0A2DB0189848D000175F59 /* AtkSampleTwoViewController.xib in Resources */, 272 | 1D0A2DAB189848D000175F59 /* AtkSampleOneViewController.xib in Resources */, 273 | 1D847C4C1898471E00F419F6 /* Images.xcassets in Resources */, 274 | ); 275 | runOnlyForDeploymentPostprocessing = 0; 276 | }; 277 | /* End PBXResourcesBuildPhase section */ 278 | 279 | /* Begin PBXSourcesBuildPhase section */ 280 | 1D847C321898471E00F419F6 /* Sources */ = { 281 | isa = PBXSourcesBuildPhase; 282 | buildActionMask = 2147483647; 283 | files = ( 284 | 1D0A2DA5189848D000175F59 /* AtkSampleViewController.m in Sources */, 285 | 1DE3C72418988AD2002C1C4E /* UIScrollView+AtkDragAndDrop.m in Sources */, 286 | 1DE3C72618988AD2002C1C4E /* UIView+AtkImage.m in Sources */, 287 | 1D0A2DA7189848D000175F59 /* AtkSampleOneDragSourceView.m in Sources */, 288 | 1D847C461898471E00F419F6 /* main.m in Sources */, 289 | 1D0A2DAA189848D000175F59 /* AtkSampleOneViewController.m in Sources */, 290 | 1D0A2DAE189848D000175F59 /* AtkSampleTwoDropZoneWrapper.m in Sources */, 291 | 1D0A2DAD189848D000175F59 /* AtkSampleTwoDropZoneScrollViewWrapper.m in Sources */, 292 | 1D0A2DA8189848D000175F59 /* AtkSampleOneDropZoneScrollView.m in Sources */, 293 | 1D0A2DAF189848D000175F59 /* AtkSampleTwoViewController.m in Sources */, 294 | 1D847C4A1898471E00F419F6 /* AtkAppDelegate.m in Sources */, 295 | 1DE3C72218988AD2002C1C4E /* AtkDragAndDropManager.m in Sources */, 296 | 1D0A2DAC189848D000175F59 /* AtkSampleTwoDragSourceWrapper.m in Sources */, 297 | 1DE3C72518988AD2002C1C4E /* UIView+AtkDragAndDrop.m in Sources */, 298 | 1DE3C72118988AD2002C1C4E /* AtkDefaultDragAndDropManagerDelegate.m in Sources */, 299 | 1D0A2DA9189848D000175F59 /* AtkSampleOneDropZoneView.m in Sources */, 300 | 1DE3C72318988AD2002C1C4E /* AtkDropZoneWrapper.m in Sources */, 301 | ); 302 | runOnlyForDeploymentPostprocessing = 0; 303 | }; 304 | /* End PBXSourcesBuildPhase section */ 305 | 306 | /* Begin PBXVariantGroup section */ 307 | 1D847C421898471E00F419F6 /* InfoPlist.strings */ = { 308 | isa = PBXVariantGroup; 309 | children = ( 310 | 1D847C431898471E00F419F6 /* en */, 311 | ); 312 | name = InfoPlist.strings; 313 | sourceTree = ""; 314 | }; 315 | /* End PBXVariantGroup section */ 316 | 317 | /* Begin XCBuildConfiguration section */ 318 | 1D847C601898471F00F419F6 /* Debug */ = { 319 | isa = XCBuildConfiguration; 320 | buildSettings = { 321 | ALWAYS_SEARCH_USER_PATHS = NO; 322 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 323 | CLANG_CXX_LIBRARY = "libc++"; 324 | CLANG_ENABLE_MODULES = YES; 325 | CLANG_ENABLE_OBJC_ARC = YES; 326 | CLANG_WARN_BOOL_CONVERSION = YES; 327 | CLANG_WARN_CONSTANT_CONVERSION = YES; 328 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 329 | CLANG_WARN_EMPTY_BODY = YES; 330 | CLANG_WARN_ENUM_CONVERSION = YES; 331 | CLANG_WARN_INT_CONVERSION = YES; 332 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 333 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 334 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 335 | COPY_PHASE_STRIP = NO; 336 | GCC_C_LANGUAGE_STANDARD = gnu99; 337 | GCC_DYNAMIC_NO_PIC = NO; 338 | GCC_OPTIMIZATION_LEVEL = 0; 339 | GCC_PREPROCESSOR_DEFINITIONS = ( 340 | "DEBUG=1", 341 | "$(inherited)", 342 | ); 343 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 344 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 345 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 346 | GCC_WARN_UNDECLARED_SELECTOR = YES; 347 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 348 | GCC_WARN_UNUSED_FUNCTION = YES; 349 | GCC_WARN_UNUSED_VARIABLE = YES; 350 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 351 | ONLY_ACTIVE_ARCH = YES; 352 | SDKROOT = iphoneos; 353 | }; 354 | name = Debug; 355 | }; 356 | 1D847C611898471F00F419F6 /* Release */ = { 357 | isa = XCBuildConfiguration; 358 | buildSettings = { 359 | ALWAYS_SEARCH_USER_PATHS = NO; 360 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 361 | CLANG_CXX_LIBRARY = "libc++"; 362 | CLANG_ENABLE_MODULES = YES; 363 | CLANG_ENABLE_OBJC_ARC = YES; 364 | CLANG_WARN_BOOL_CONVERSION = YES; 365 | CLANG_WARN_CONSTANT_CONVERSION = YES; 366 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 367 | CLANG_WARN_EMPTY_BODY = YES; 368 | CLANG_WARN_ENUM_CONVERSION = YES; 369 | CLANG_WARN_INT_CONVERSION = YES; 370 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 371 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 372 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 373 | COPY_PHASE_STRIP = YES; 374 | ENABLE_NS_ASSERTIONS = NO; 375 | GCC_C_LANGUAGE_STANDARD = gnu99; 376 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 377 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 378 | GCC_WARN_UNDECLARED_SELECTOR = YES; 379 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 380 | GCC_WARN_UNUSED_FUNCTION = YES; 381 | GCC_WARN_UNUSED_VARIABLE = YES; 382 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 383 | SDKROOT = iphoneos; 384 | VALIDATE_PRODUCT = YES; 385 | }; 386 | name = Release; 387 | }; 388 | 1D847C631898471F00F419F6 /* Debug */ = { 389 | isa = XCBuildConfiguration; 390 | buildSettings = { 391 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 392 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 393 | CLANG_ENABLE_OBJC_ARC = YES; 394 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 395 | GCC_PREFIX_HEADER = "AtkDragAndDrop_Examples/AtkDragAndDrop_Examples-Prefix.pch"; 396 | INFOPLIST_FILE = "AtkDragAndDrop_Examples/AtkDragAndDrop_Examples-Info.plist"; 397 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 398 | PRODUCT_NAME = "$(TARGET_NAME)"; 399 | TARGETED_DEVICE_FAMILY = 1; 400 | WRAPPER_EXTENSION = app; 401 | }; 402 | name = Debug; 403 | }; 404 | 1D847C641898471F00F419F6 /* Release */ = { 405 | isa = XCBuildConfiguration; 406 | buildSettings = { 407 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 408 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 409 | CLANG_ENABLE_OBJC_ARC = YES; 410 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 411 | GCC_PREFIX_HEADER = "AtkDragAndDrop_Examples/AtkDragAndDrop_Examples-Prefix.pch"; 412 | INFOPLIST_FILE = "AtkDragAndDrop_Examples/AtkDragAndDrop_Examples-Info.plist"; 413 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 414 | PRODUCT_NAME = "$(TARGET_NAME)"; 415 | TARGETED_DEVICE_FAMILY = 1; 416 | WRAPPER_EXTENSION = app; 417 | }; 418 | name = Release; 419 | }; 420 | /* End XCBuildConfiguration section */ 421 | 422 | /* Begin XCConfigurationList section */ 423 | 1D847C311898471E00F419F6 /* Build configuration list for PBXProject "AtkDragAndDrop_Examples" */ = { 424 | isa = XCConfigurationList; 425 | buildConfigurations = ( 426 | 1D847C601898471F00F419F6 /* Debug */, 427 | 1D847C611898471F00F419F6 /* Release */, 428 | ); 429 | defaultConfigurationIsVisible = 0; 430 | defaultConfigurationName = Release; 431 | }; 432 | 1D847C621898471F00F419F6 /* Build configuration list for PBXNativeTarget "AtkDragAndDrop_Examples" */ = { 433 | isa = XCConfigurationList; 434 | buildConfigurations = ( 435 | 1D847C631898471F00F419F6 /* Debug */, 436 | 1D847C641898471F00F419F6 /* Release */, 437 | ); 438 | defaultConfigurationIsVisible = 0; 439 | defaultConfigurationName = Release; 440 | }; 441 | /* End XCConfigurationList section */ 442 | }; 443 | rootObject = 1D847C2E1898471E00F419F6 /* Project object */; 444 | } 445 | --------------------------------------------------------------------------------