00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 @import <AppKit/CPView.j>
00024 @import <AppKit/CPEvent.j>
00025 @import <AppKit/CPPasteboard.j>
00026 @import <AppKit/CPImageView.j>
00027
00028 #import "CoreGraphics/CGGeometry.h"
00029
00030
00031 #define DRAGGING_WINDOW(anObject) ([anObject isKindOfClass:[CPWindow class]] ? anObject : [anObject window])
00032
00033 var CPSharedDragServer = nil;
00034
00035 var CPDragServerView = nil,
00036 CPDragServerSource = nil,
00037 CPDragServerWindow = nil,
00038 CPDragServerOffset = nil,
00039 CPDragServerLocation = nil,
00040 CPDragServerPasteboard = nil,
00041 CPDragServerDestination = nil,
00042 CPDragServerDraggingInfo = nil,
00043 CPDragServerPreviousEvent = nil,
00044 CPDragServerAutoscrollInterval = nil;
00045
00046 var CPDragServerIsDraggingImage = NO,
00047
00048 CPDragServerShouldSendDraggedViewMovedTo = NO,
00049 CPDragServerShouldSendDraggedImageMovedTo = NO,
00050
00051 CPDragServerShouldSendDraggedViewEndedAtOperation = NO,
00052 CPDragServerShouldSendDraggedImageEndedAtOperation = NO;
00053
00054 var CPDragServerAutoscroll = function()
00055 {
00056 [CPDragServerSource autoscroll:CPDragServerPreviousEvent];
00057 }
00058
00059 var CPDragServerStartDragging = function(anEvent)
00060 {
00061 CPDragServerUpdateDragging(anEvent);
00062 }
00063
00064 var CPDragServerUpdateDragging = function(anEvent)
00065 {
00066
00067 if([anEvent type] == CPLeftMouseUp)
00068 {
00069 if (CPDragServerAutoscrollInterval !== nil)
00070 clearInterval(CPDragServerAutoscrollInterval);
00071
00072 CPDragServerAutoscrollInterval = nil;
00073
00074 CPDragServerLocation = [DRAGGING_WINDOW(CPDragServerDestination) convertBridgeToBase:[[anEvent window] convertBaseToBridge:[anEvent locationInWindow]]];
00075
00076 [CPDragServerView removeFromSuperview];
00077 [CPSharedDragServer._dragWindow orderOut:nil];
00078
00079 if (CPDragServerDestination &&
00080 (![CPDragServerDestination respondsToSelector:@selector(prepareForDragOperation:)] || [CPDragServerDestination prepareForDragOperation:CPDragServerDraggingInfo]) &&
00081 (![CPDragServerDestination respondsToSelector:@selector(performDragOperation:)] || [CPDragServerDestination performDragOperation:CPDragServerDraggingInfo]) &&
00082 [CPDragServerDestination respondsToSelector:@selector(concludeDragOperation:)])
00083 [CPDragServerDestination concludeDragOperation:CPDragServerDraggingInfo];
00084
00085 if (CPDragServerShouldSendDraggedImageEndedAtOperation)
00086 [CPDragServerSource draggedImage:[CPDragServerView image] endedAt:CPDragServerLocation operation:NO];
00087 else if (CPDragServerShouldSendDraggedViewEndedAtOperation)
00088 [CPDragServerSource draggedView:CPDragServerView endedAt:CPDragServerLocation operation:NO];
00089
00090 CPDragServerIsDraggingImage = NO;
00091 CPDragServerDestination = nil;
00092
00093 return;
00094 }
00095
00096 if (CPDragServerAutoscrollInterval === nil)
00097 {
00098 if ([CPDragServerSource respondsToSelector:@selector(autoscroll:)])
00099 CPDragServerAutoscrollInterval = setInterval(CPDragServerAutoscroll, 100);
00100 }
00101
00102 CPDragServerPreviousEvent = anEvent;
00103
00104
00105 [CPApp setCallback:CPDragServerUpdateDragging
00106 forNextEventMatchingMask:CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask
00107 untilDate:nil inMode:0 dequeue:NO];
00108
00109 var location = [anEvent locationInWindow],
00110 operation =
00111 bridgeLocation = [[anEvent window] convertBaseToBridge:location];
00112
00113
00114 var draggingDestination = [[CPDOMWindowBridge sharedDOMWindowBridge] _dragHitTest:bridgeLocation pasteboard:CPDragServerPasteboard];
00115
00116 CPDragServerLocation = [DRAGGING_WINDOW(draggingDestination) convertBridgeToBase:bridgeLocation];
00117
00118 if(draggingDestination != CPDragServerDestination)
00119 {
00120 if (CPDragServerDestination && [CPDragServerDestination respondsToSelector:@selector(draggingExited:)])
00121 [CPDragServerDestination draggingExited:CPDragServerDraggingInfo];
00122
00123 CPDragServerDestination = draggingDestination;
00124
00125 if (CPDragServerDestination && [CPDragServerDestination respondsToSelector:@selector(draggingEntered:)])
00126 [CPDragServerDestination draggingEntered:CPDragServerDraggingInfo];
00127 }
00128 else if (CPDragServerDestination && [CPDragServerDestination respondsToSelector:@selector(draggingUpdated:)])
00129 [CPDragServerDestination draggingUpdated:CPDragServerDraggingInfo];
00130
00131 location.x -= CPDragServerOffset.x;
00132 location.y -= CPDragServerOffset.y;
00133
00134 [CPDragServerView setFrameOrigin:location];
00135
00136 if (CPDragServerShouldSendDraggedImageMovedTo)
00137 [CPDragServerSource draggedImage:[CPDragServerView image] movedTo:location];
00138 else if (CPDragServerShouldSendDraggedViewMovedTo)
00139 [CPDragServerSource draggedView:CPDragServerView movedTo:location];
00140 }
00141
00142
00143
00144
00145
00146 @implementation CPDraggingInfo : CPObject
00147 {
00148 }
00149
00150 - (id)draggingSource
00151 {
00152 return CPDragServerSource;
00153 }
00154
00155 - (CPPoint)draggingLocation
00156 {
00157 return CPDragServerLocation;
00158 }
00159
00160 - (CPPasteboard)draggingPasteboard
00161 {
00162 return CPDragServerPasteboard;
00163 }
00164
00165 - (CPImage)draggedImage
00166 {
00167 return [CPDragServerView image];
00168 }
00169
00170 - (CGPoint)draggedImageLocation
00171 {
00172 return [self draggedViewLocation];
00173 }
00174
00175 - (CGPoint)draggedViewLocation
00176 {
00177 return [DRAGGING_WINDOW(CPDragServerDestination) convertBridgeToBase:[CPDragServerView frame].origin];
00178 }
00179
00180 - (CPView)draggedView
00181 {
00182 return CPDragServerView;
00183 }
00184
00185 @end
00186
00187 @implementation CPDragServer : CPObject
00188 {
00189 CPWindow _dragWindow;
00190 CPImageView _imageView;
00191 }
00192
00193
00194
00195
00196
00197 + (void)initialize
00198 {
00199 if (self != [CPDragServer class])
00200 return;
00201
00202 CPDragServerDraggingInfo = [[CPDraggingInfo alloc] init];
00203 }
00204
00205 + (CPDragServer)sharedDragServer
00206 {
00207 if (!CPSharedDragServer)
00208 CPSharedDragServer = [[CPDragServer alloc] init];
00209
00210 return CPSharedDragServer;
00211 }
00212
00213
00214
00215
00216 - (id)init
00217 {
00218 self = [super init];
00219
00220 if (self)
00221 {
00222 _dragWindow = [[CPWindow alloc] initWithContentRect:CPRectMakeZero() styleMask:CPBorderlessWindowMask];
00223 [_dragWindow setLevel:CPDraggingWindowLevel];
00224 }
00225
00226 return self;
00227 }
00228
00241 - (void)dragView:(CPView)aView fromWindow:(CPWindow)aWindow at:(CGPoint)viewLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack
00242 {
00243 var eventLocation = [anEvent locationInWindow];
00244
00245 CPDragServerView = aView;
00246 CPDragServerSource = aSourceObject;
00247 CPDragServerWindow = aWindow;
00248 CPDragServerOffset = CPPointMake(eventLocation.x - viewLocation.x, eventLocation.y - viewLocation.y);
00249 CPDragServerPasteboard = [CPPasteboard pasteboardWithName:CPDragPboard];
00250
00251 [_dragWindow setFrameSize:CGSizeMakeCopy([[CPDOMWindowBridge sharedDOMWindowBridge] frame].size)];
00252 [_dragWindow orderFront:self];
00253
00254 [aView setFrameOrigin:viewLocation];
00255 [[_dragWindow contentView] addSubview:aView];
00256
00257 if (CPDragServerIsDraggingImage)
00258 {
00259 if ([CPDragServerSource respondsToSelector:@selector(draggedImage:beganAt:)])
00260 [CPDragServerSource draggedImage:[aView image] beganAt:viewLocation];
00261
00262 CPDragServerShouldSendDraggedImageMovedTo = [CPDragServerSource respondsToSelector:@selector(draggedImage:movedTo:)];
00263 CPDragServerShouldSendDraggedImageEndedAtOperation = [CPDragServerSource respondsToSelector:@selector(draggedImage:endAt:operation:)];
00264
00265 CPDragServerShouldSendDraggedViewMovedTo = NO;
00266 CPDragServerShouldSendDraggedViewEndedAtOperation = NO;
00267 }
00268 else
00269 {
00270 if ([CPDragServerSource respondsToSelector:@selector(draggedView:beganAt:)])
00271 [CPDragServerSource draggedView:aView beganAt:viewLocation];
00272
00273 CPDragServerShouldSendDraggedViewMovedTo = [CPDragServerSource respondsToSelector:@selector(draggedView:movedTo:)];
00274 CPDragServerShouldSendDraggedViewEndedAtOperation = [CPDragServerSource respondsToSelector:@selector(draggedView:endedAt:operation:)];
00275
00276
00277 CPDragServerShouldSendDraggedImageMovedTo = NO;
00278 CPDragServerShouldSendDraggedImageEndedAtOperation = NO;
00279 }
00280
00281 CPDragServerStartDragging(anEvent);
00282 }
00283
00296 - (void)dragImage:(CPImage)anImage fromWindow:(CPWindow)aWindow at:(CGPoint)imageLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack
00297 {
00298 CPDragServerIsDraggingImage = YES;
00299
00300 if (!_imageView)
00301 _imageView = [[CPImageView alloc] initWithFrame:CPRectMakeZero()];
00302
00303 [_imageView setImage:anImage];
00304 [_imageView setFrameSize:CGSizeMakeCopy([anImage size])];
00305
00306 [self dragView:_imageView fromWindow:aWindow at:imageLocation offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack];
00307 }
00308
00309 @end
00310
00311 @implementation CPWindow (CPDraggingAdditions)
00312
00313
00314 - (id)_dragHitTest:(CGPoint)aPoint pasteboard:(CPPasteboard)aPasteboard
00315 {
00316
00317 if (!_inclusiveRegisteredDraggedTypes)
00318 return nil;
00319
00320
00321
00322
00323
00324
00325
00326 var adjustedPoint = _CGPointMake(aPoint.x - _CGRectGetMinX(_frame), aPoint.y - _CGRectGetMinY(_frame)),
00327 hitView = [_windowView hitTest:adjustedPoint];
00328
00329 while (hitView && ![aPasteboard availableTypeFromArray:[hitView registeredDraggedTypes]])
00330 hitView = [hitView superview];
00331
00332 if (hitView)
00333 return hitView;
00334
00335 if ([aPasteboard availableTypeFromArray:[self registeredDraggedTypes]])
00336 return self;
00337
00338 return nil;
00339 }
00340
00341 @end