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 #import "Platform/Platform.h"
00030
00031
00032 CPDragOperationNone = 0,
00033 CPDragOperationCopy = 1 << 1,
00034 CPDragOperationLink = 1 << 1,
00035 CPDragOperationGeneric = 1 << 2,
00036 CPDragOperationPrivate = 1 << 3,
00037 CPDragOperationMove = 1 << 4,
00038 CPDragOperationDelete = 1 << 5,
00039 CPDragOperationEvery = -1;
00040
00041 #define DRAGGING_WINDOW(anObject) ([anObject isKindOfClass:[CPWindow class]] ? anObject : [anObject window])
00042
00043 var CPDragServerPreviousEvent = nil,
00044 CPDragServerAutoscrollInterval = nil;
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 var CPSharedDragServer = nil;
00066
00067 var CPDragServerSource = nil;
00068 var CPDragServerDraggingInfo = nil;
00069
00070
00071
00072
00073
00074 @implementation CPDraggingInfo : CPObject
00075 {
00076 }
00077
00078 - (CPPasteboard)draggingPasteboard
00079 {
00080 if ([CPPlatform supportsDragAndDrop])
00081 return [_CPDOMDataTransferPasteboard DOMDataTransferPasteboard];
00082
00083 return [[CPDragServer sharedDragServer] draggingPasteboard];
00084 }
00085
00086 - (id)draggingSource
00087 {
00088 return [[CPDragServer sharedDragServer] draggingSource];
00089 }
00090
00091
00092
00093
00094
00095 - (CPPoint)draggingLocation
00096 {
00097 return [[CPDragServer sharedDragServer] draggingLocation];
00098 }
00099
00100 - (CPWindow)draggingDestinationWindow
00101 {
00102 return DRAGGING_WINDOW([[CPDragServer sharedDragServer] draggingDestination]);
00103 }
00104
00105 - (CPImage)draggedImage
00106 {
00107 return [[self draggedView] image];
00108 }
00109
00110 - (CGPoint)draggedImageLocation
00111 {
00112 return [self draggedViewLocation];
00113 }
00114
00115 - (CPView)draggedView
00116 {
00117 return [[CPDragServer sharedDragServer] draggedView];
00118 }
00119
00120 - (CGPoint)draggedViewLocation
00121 {
00122 var dragServer = [CPDragServer sharedDragServer];
00123
00124 return [DRAGGING_WINDOW([dragServer draggingDestination]) convertPlatformWindowToBase:[[dragServer draggedView] frame].origin];
00125 }
00126
00127 @end
00128
00129 var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
00130 CPDraggingSource_draggedImage_endAt_operation_ = 1 << 1,
00131 CPDraggingSource_draggedView_movedTo_ = 1 << 2,
00132 CPDraggingSource_draggedView_endedAt_operation_ = 1 << 3;
00133
00134 @implementation CPDragServer : CPObject
00135 {
00136 BOOL _isDragging @accessors(readonly, getter=isDragging);
00137
00138 CPWindow _draggedWindow @accessors(readonly, getter=draggedWindow);
00139 CPView _draggedView @accessors(readonly, getter=draggedView);
00140 CPImageView _imageView;
00141
00142 BOOL _isDraggingImage;
00143
00144 CGSize _draggingOffset @accessors(readonly, getter=draggingOffset);
00145
00146 CPPasteboard _draggingPasteboard @accessors(readonly, getter=draggingPasteboard);
00147
00148 id _draggingSource @accessors(readonly, getter=draggingSource);
00149 unsigned _implementedDraggingSourceMethods;
00150
00151 CGPoint _draggingLocation;
00152 id _draggingDestination;
00153
00154 CGPoint _startDragLocation;
00155 BOOL _shouldSlideBack;
00156 unsigned _dragOperation;
00157 }
00158
00159
00160
00161
00162
00163 + (void)initialize
00164 {
00165 if (self !== [CPDragServer class])
00166 return;
00167
00168 CPDragServerDraggingInfo = [[CPDraggingInfo alloc] init];
00169 }
00170
00171 + (CPDragServer)sharedDragServer
00172 {
00173 if (!CPSharedDragServer)
00174 CPSharedDragServer = [[CPDragServer alloc] init];
00175
00176 return CPSharedDragServer;
00177 }
00178
00179
00180
00181
00182 - (id)init
00183 {
00184 self = [super init];
00185
00186 if (self)
00187 {
00188 _draggedWindow = [[CPWindow alloc] initWithContentRect:_CGRectMakeZero() styleMask:CPBorderlessWindowMask];
00189
00190 [_draggedWindow setLevel:CPDraggingWindowLevel];
00191 }
00192
00193 return self;
00194 }
00195
00196 - (id)draggingDestination
00197 {
00198 return _draggingDestination;
00199 }
00200
00201 - (CGPoint)draggingLocation
00202 {
00203 return _draggingLocation
00204 }
00205
00206 - (void)draggingStartedInPlatformWindow:(CPPlatformWindow)aPlatformWindow globalLocation:(CGPoint)aLocation
00207 {
00208 if (_isDraggingImage)
00209 {
00210 if ([_draggingSource respondsToSelector:@selector(draggedImage:beganAt:)])
00211 [_draggingSource draggedImage:[_draggedView image] beganAt:aLocation];
00212 }
00213 else
00214 {
00215 if ([_draggingSource respondsToSelector:@selector(draggedView:beganAt:)])
00216 [_draggingSource draggedView:_draggedView beganAt:aLocation];
00217 }
00218
00219 if (![CPPlatform supportsDragAndDrop])
00220 [_draggedWindow orderFront:self];
00221 }
00222
00223 - (void)draggingSourceUpdatedWithGlobalLocation:(CGPoint)aGlobalLocation
00224 {
00225 if (![CPPlatform supportsDragAndDrop])
00226 [_draggedWindow setFrameOrigin:_CGPointMake(aGlobalLocation.x - _draggingOffset.width, aGlobalLocation.y - _draggingOffset.height)];
00227
00228 if (_implementedDraggingSourceMethods & CPDraggingSource_draggedImage_movedTo_)
00229 [_draggingSource draggedImage:[_draggedView image] movedTo:aGlobalLocation];
00230
00231 else if (_implementedDraggingSourceMethods & CPDraggingSource_draggedView_movedTo_)
00232 [_draggingSource draggedView:_draggedView movedTo:aGlobalLocation];
00233 }
00234
00235 - (CPDragOperation)draggingUpdatedInPlatformWindow:(CPPlatformWindow)aPlatformWindow location:(CGPoint)aLocation
00236 {
00237 var dragOperation = CPDragOperationCopy;
00238
00239 var draggingDestination = [aPlatformWindow _dragHitTest:aLocation pasteboard:[CPDragServerDraggingInfo draggingPasteboard]];
00240
00241 if (draggingDestination)
00242 _draggingLocation = [DRAGGING_WINDOW(draggingDestination) convertPlatformWindowToBase:aLocation];
00243
00244 if(draggingDestination !== _draggingDestination)
00245 {
00246 if (_draggingDestination && [_draggingDestination respondsToSelector:@selector(draggingExited:)])
00247 [_draggingDestination draggingExited:CPDragServerDraggingInfo];
00248
00249 _draggingDestination = draggingDestination;
00250
00251 if (_draggingDestination && [_draggingDestination respondsToSelector:@selector(draggingEntered:)])
00252 dragOperation = [_draggingDestination draggingEntered:CPDragServerDraggingInfo];
00253 }
00254 else if (_draggingDestination && [_draggingDestination respondsToSelector:@selector(draggingUpdated:)])
00255 dragOperation = [_draggingDestination draggingUpdated:CPDragServerDraggingInfo];
00256
00257 if (!_draggingDestination)
00258 dragOperation = CPDragOperationNone;
00259
00260 return dragOperation;
00261 }
00262
00263 - (void)draggingEndedInPlatformWindow:(CPPlatformWindow)aPlatformWindow globalLocation:(CGPoint)aLocation operation:(CPDragOperation)anOperation
00264 {
00265 [_draggedView removeFromSuperview];
00266
00267 if (![CPPlatform supportsDragAndDrop])
00268 [_draggedWindow orderOut:self];
00269
00270 if (_implementedDraggingSourceMethods & CPDraggingSource_draggedImage_endAt_operation_)
00271 [_draggingSource draggedImage:[_draggedView image] endedAt:aLocation operation:anOperation];
00272 else if (_implementedDraggingSourceMethods & CPDraggingSource_draggedView_endedAt_operation_)
00273 [_draggingSource draggedView:_draggedView endedAt:aLocation operation:anOperation];
00274
00275 _isDragging = NO;
00276 }
00277
00278 - (void)performDragOperationInPlatformWindow:(CPPlatformWindow)aPlatformWindow
00279 {
00280 if (_draggingDestination &&
00281 (![_draggingDestination respondsToSelector:@selector(prepareForDragOperation:)] || [_draggingDestination prepareForDragOperation:CPDragServerDraggingInfo]) &&
00282 (![_draggingDestination respondsToSelector:@selector(performDragOperation:)] || [_draggingDestination performDragOperation:CPDragServerDraggingInfo]) &&
00283 [_draggingDestination respondsToSelector:@selector(concludeDragOperation:)])
00284 [_draggingDestination concludeDragOperation:CPDragServerDraggingInfo];
00285 }
00286
00299 - (void)dragView:(CPView)aView fromWindow:(CPWindow)aWindow at:(CGPoint)viewLocation offset:(CGSize)mouseOffset event:(CPEvent)mouseDownEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack
00300 {
00301 _isDragging = YES;
00302
00303 _draggedView = aView;
00304 _draggingPasteboard = aPasteboard || [CPPasteboard pasteboardWithName:CPDragPboard];
00305 _draggingSource = aSourceObject;
00306 _draggingDestination = nil;
00307 _shouldSlideBack = slideBack;
00308
00309
00310
00311 var mouseDownWindow = [mouseDownEvent window],
00312 mouseDownEventLocation = [mouseDownEvent locationInWindow];
00313
00314 if (mouseDownEventLocation)
00315 {
00316 if (mouseDownWindow)
00317 mouseDownEventLocation = [mouseDownWindow convertBaseToGlobal:mouseDownEventLocation];
00318
00319 _draggingOffset = _CGSizeMake(mouseDownEventLocation.x - viewLocation.x, mouseDownEventLocation.y - viewLocation.y);
00320 }
00321 else
00322 _draggingOffset = _CGSizeMakeZero();
00323
00324 if ([CPPlatform isBrowser])
00325 [_draggedWindow setPlatformWindow:[aWindow platformWindow]];
00326
00327 [aView setFrameOrigin:_CGPointMakeZero()];
00328
00329 var mouseLocation = [CPEvent mouseLocation];
00330
00331
00332 _startDragLocation = _CGPointMake(mouseLocation.x - _draggingOffset.width, mouseLocation.y - _draggingOffset.height);
00333 [_draggedWindow setFrameOrigin:_startDragLocation];
00334 [_draggedWindow setFrameSize:[aView frame].size];
00335
00336 [[_draggedWindow contentView] addSubview:aView];
00337
00338 _implementedDraggingSourceMethods = 0;
00339
00340 if (_draggedView === _imageView)
00341 {
00342 if ([_draggingSource respondsToSelector:@selector(draggedImage:movedTo:)])
00343 _implementedDraggingSourceMethods |= CPDraggingSource_draggedImage_movedTo_;
00344
00345 if ([_draggingSource respondsToSelector:@selector(draggedImage:endAt:operation:)])
00346 _implementedDraggingSourceMethods |= CPDraggingSource_draggedImage_endAt_operation_;
00347 }
00348 else
00349 {
00350 if ([_draggingSource respondsToSelector:@selector(draggedView:movedTo:)])
00351 _implementedDraggingSourceMethods |= CPDraggingSource_draggedView_movedTo_;
00352
00353 if ([_draggingSource respondsToSelector:@selector(draggedView:endedAt:operation:)])
00354 _implementedDraggingSourceMethods |= CPDraggingSource_draggedView_endedAt_operation_;
00355 }
00356
00357 if (![CPPlatform supportsDragAndDrop])
00358 {
00359 [self draggingStartedInPlatformWindow:[aWindow platformWindow] globalLocation:mouseLocation];
00360 [self trackDragging:mouseDownEvent];
00361 }
00362 }
00363
00376 - (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
00377 {
00378 _isDraggingImage = YES;
00379
00380 var imageSize = [anImage size];
00381
00382 if (!_imageView)
00383 _imageView = [[CPImageView alloc] initWithFrame:_CGRectMake(0.0, 0.0, imageSize.width, imageSize.height)];
00384
00385 [_imageView setImage:anImage];
00386
00387 [self dragView:_imageView fromWindow:aWindow at:imageLocation offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack];
00388 }
00389
00390 - (void)trackDragging:(CPEvent)anEvent
00391 {
00392 var type = [anEvent type],
00393 platformWindow = [_draggedWindow platformWindow],
00394 platformWindowLocation = [[anEvent window] convertBaseToPlatformWindow:[anEvent locationInWindow]];
00395
00396 if (type === CPLeftMouseUp)
00397 {
00398
00399 if (_dragOperation !== CPDragOperationNone)
00400 [self performDragOperationInPlatformWindow:platformWindow];
00401
00402 [self draggingEndedInPlatformWindow:platformWindow globalLocation:platformWindowLocation operation:_dragOperation];
00403
00404
00405 return;
00406 }
00407
00408 [self draggingSourceUpdatedWithGlobalLocation:platformWindowLocation];
00409 _dragOperation = [self draggingUpdatedInPlatformWindow:platformWindow location:platformWindowLocation];
00410
00411
00412 [CPApp setTarget:self selector:@selector(trackDragging:)
00413 forNextEventMatchingMask:CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask
00414 untilDate:nil inMode:0 dequeue:NO];
00415 }
00416
00417 @end
00418
00419 @implementation CPWindow (CPDraggingAdditions)
00420
00421
00422 - (id)_dragHitTest:(CGPoint)aPoint pasteboard:(CPPasteboard)aPasteboard
00423 {
00424
00425 if (!_inclusiveRegisteredDraggedTypes)
00426 return nil;
00427
00428
00429
00430
00431
00432
00433
00434 var adjustedPoint = [self convertPlatformWindowToBase:aPoint],
00435 hitView = [_windowView hitTest:adjustedPoint];
00436
00437 while (hitView && ![aPasteboard availableTypeFromArray:[hitView registeredDraggedTypes]])
00438 hitView = [hitView superview];
00439
00440 if (hitView)
00441 return hitView;
00442
00443 if ([aPasteboard availableTypeFromArray:[self registeredDraggedTypes]])
00444 return self;
00445
00446 return nil;
00447 }
00448
00449 @end