home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / YellowBox / Kits / MiscTableScroll-138.1 / Palettes / MiscTableScroll / Framework / MiscTableViewDrag.M < prev    next >
Encoding:
Text File  |  1998-03-31  |  9.6 KB  |  273 lines

  1. //=============================================================================
  2. //
  3. //  Copyright (C) 1995,1996,1997,1998 by Paul S. McCarthy and Eric Sunshine.
  4. //        Written by Paul S. McCarthy and Eric Sunshine.
  5. //                All Rights Reserved.
  6. //
  7. //    This notice may not be removed from this source code.
  8. //
  9. //    This object is included in the MiscKit by permission from the authors
  10. //    and its use is governed by the MiscKit license, found in the file
  11. //    "License.rtf" in the MiscKit distribution.  Please refer to that file
  12. //    for a list of all applicable permissions and restrictions.
  13. //
  14. //=============================================================================
  15. //-----------------------------------------------------------------------------
  16. // MiscTableViewDrag.M
  17. //
  18. //    Image dragging methods for MiscTableView.
  19. //
  20. //-----------------------------------------------------------------------------
  21. //-----------------------------------------------------------------------------
  22. // $Id: MiscTableViewDrag.M,v 1.2 98/03/29 23:59:48 sunshine Exp $
  23. // $Log:    MiscTableViewDrag.M,v $
  24. // Revision 1.2  98/03/29  23:59:48  sunshine
  25. // v138.1: #import was missing "MiscTableScroll/" for public header.
  26. // Implemented -shouldDelayWindowOrderingForEvent:
  27. // 
  28. // Revision 1.1  97/11/23  07:41:42  sunshine
  29. // v130.1: Image dragging methods.
  30. //-----------------------------------------------------------------------------
  31. #import "MiscTableViewPrivate.h"
  32. #import "MiscTableScrollPrivate.h"
  33. #import <MiscTableScroll/MiscTableCell.h>
  34. extern "Objective-C" {
  35. #import <AppKit/NSApplication.h>
  36. #import <AppKit/NSImage.h>
  37. #import <AppKit/NSPasteboard.h>
  38. #import <AppKit/NSWindow.h>
  39. }
  40. extern "C" {
  41. #import <math.h>    // floor()
  42. }
  43.  
  44. typedef MiscDelegateFlags DF;
  45.  
  46. @implementation MiscTableView(Drag)
  47.  
  48. //=============================================================================
  49. // IMAGE DRAGGING
  50. //=============================================================================
  51. static inline float absval( float x ) { return (x < 0 ? -x : x ); }
  52. static inline BOOL isSlop( NSEvent* e1, NSEvent* e2, float const slop )
  53.     {
  54.     NSPoint const p1 = [e1 locationInWindow];
  55.     NSPoint const p2 = [e2 locationInWindow];
  56.     return (absval(p1.x - p2.x) <= slop && absval(p1.y - p2.y) <= slop);
  57.     }
  58.  
  59.  
  60. //-----------------------------------------------------------------------------
  61. // draggingSourceOperationMaskForLocal:
  62. //-----------------------------------------------------------------------------
  63. - (unsigned int)draggingSourceOperationMaskForLocal:(BOOL)flag
  64.     {
  65.     id const scroll = [self scroll];
  66.     id const d = [scroll responsibleDelegate:DF::DEL_DRAG_OP_MASK];
  67.     if (d != 0)
  68.     return [d tableScroll:scroll draggingSourceOperationMaskForLocal:flag];
  69.     return NSDragOperationGeneric;
  70.     }
  71.  
  72.  
  73. //-----------------------------------------------------------------------------
  74. // ignoreModifierKeysWhileDragging
  75. //-----------------------------------------------------------------------------
  76. - (BOOL)ignoreModifierKeysWhileDragging
  77.     {
  78.     id const scroll = [self scroll];
  79.     id const d = [scroll responsibleDelegate:DF::DEL_DRAG_IGNORE_MODIFIERS];
  80.     if (d != 0)
  81.     return [d tableScrollIgnoreModifierKeysWhileDragging:scroll];
  82.     return YES;
  83.     }
  84.  
  85.  
  86. //-----------------------------------------------------------------------------
  87. // shouldDelayWindowOrderingForEvent:
  88. //-----------------------------------------------------------------------------
  89. - (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent*)e
  90.     {
  91.     BOOL delay = NO;
  92.     NSPoint const p = [self convertPoint:[e locationInWindow] fromView:0];
  93.     MiscCoord_P r,c;
  94.     if ([self getRow:&r column:&c forPoint:p] &&
  95.     [self canPerformDragAtRow:r column:c withEvent:e])
  96.     {
  97.     id const scroll = [self scroll];
  98.     id d = [scroll responsibleDelegate:DF::DEL_DRAG_DELAY_WIN_ORDERING];
  99.     if (d != 0)
  100.         delay = [d tableScroll:scroll shouldDelayWindowOrderingForEvent:e];
  101.     else
  102.         delay = YES;
  103.     }
  104.     return delay;
  105.     }
  106.  
  107.  
  108. //-----------------------------------------------------------------------------
  109. // getDragImageAtRow:column:
  110. //-----------------------------------------------------------------------------
  111. - (NSImage*)getDragImageAtRow:(MiscCoord_P)row column:(MiscCoord_P)col
  112.     {
  113.     NSImage* i = 0;
  114.     id const scroll = [self scroll];
  115.     id const d = [scroll responsibleDelegate:DF::DEL_IMAGE_FOR_DRAG];
  116.     if (d != 0)
  117.     i = [d tableScroll:scroll imageForDragOperationAtRow:row column:col];
  118.     if (i == 0)
  119.     {
  120.     NSCell* cell = (NSCell*)[scroll cellAtRow:row column:col];
  121.     if ([cell type] == NSImageCellType)
  122.         i = [cell image];
  123.     }
  124.     return i;
  125.     }
  126.  
  127.  
  128. //-----------------------------------------------------------------------------
  129. // calcOrigin:andOffset:forImage:inRect:atRow:column:downEvent:dragEvent:
  130. //
  131. // Compute the origin of the image and the offset of the mouse for dragging 
  132. // via NSView's -dragImage:at:offset:... method.  There are two cases: 
  133. //
  134. // CASE *1*: The image being dragged fits exactly in the cell's image area.  
  135. //    In this case drag from the point where the mouse went down inside the 
  136. //    image's boundry.  This give the visual impression of lifting the image 
  137. //    exactly from where it is sitting; without it jumping to some other 
  138. //    location.  
  139. // CASE *2*: The image is a different size than the cell's image area.  In 
  140. //    this case just center the image under the mouse.  
  141. //-----------------------------------------------------------------------------
  142. - (void)calcOrigin:(NSPoint*)origin
  143.     andOffset:(NSSize*)offset
  144.     forImage:(NSImage*)image
  145.     inRect:(NSRect)rect
  146.     atRow:(MiscCoord_P)row
  147.     column:(MiscCoord_P)col
  148.     downEvent:(NSEvent*)downEvent
  149.     dragEvent:(NSEvent*)dragEvent
  150.     {
  151.     offset->width = 0;
  152.     offset->height = 0;
  153.  
  154.     NSSize image_s = [image size];
  155.  
  156.     id cell = [[self scroll] cellAtRow:row column:col];
  157.     NSRect image_r = [cell imageRectForBounds:rect];
  158.  
  159.     if (image_s.width  == image_r.size.width &&            // CASE *1*
  160.     image_s.height == image_r.size.height)
  161.     {
  162.     *origin = image_r.origin;
  163.     if ([self isFlipped])
  164.         origin->y += image_r.size.height;
  165.  
  166.     if (dragEvent != 0 && [dragEvent type] == NSLeftMouseDragged)
  167.         {
  168.         NSPoint ptDrag = [dragEvent locationInWindow];
  169.         NSPoint ptDown = [downEvent locationInWindow];
  170.         offset->width = ptDrag.x - ptDown.x;
  171.         offset->height = ptDrag.y - ptDown.y;
  172.         }
  173.     }
  174.     else                            // CASE *2*
  175.     {
  176.     *origin = [self convertPoint:[downEvent locationInWindow] fromView:0];
  177.     origin->x -= floor( image_s.width / 2 );
  178.     origin->y -= floor( image_s.height / 2 ) * ([self isFlipped] ? -1 : 1);
  179.     }
  180.     }
  181.  
  182.  
  183. //-----------------------------------------------------------------------------
  184. // prepareDragPasteboard:atRow:column:
  185. //-----------------------------------------------------------------------------
  186. - (void)prepareDragPasteboard:(NSPasteboard*)pb
  187.     atRow:(MiscCoord_P)row column:(MiscCoord_P)col
  188.     {
  189.     id const scroll = [self scroll];
  190.     id const d = [scroll responsibleDelegate:DF::DEL_PREPARE_PB_FOR_DRAG];
  191.     if (d != 0)
  192.     [d tableScroll:scroll preparePasteboard:pb
  193.             forDragOperationAtRow:row column:col];
  194.     }
  195.  
  196.  
  197. //-----------------------------------------------------------------------------
  198. // performDrag:atRow:column:inRect:dragEvent:
  199. //-----------------------------------------------------------------------------
  200. - (BOOL)performDrag:(NSEvent*)mouseDown
  201.     atRow:(MiscCoord_P)row
  202.     column:(MiscCoord_P)col
  203.     inRect:(NSRect)r
  204.     dragEvent:(NSEvent*)dragEvent
  205.     {
  206.     BOOL ret = NO;
  207.  
  208.     NSImage* i = [self getDragImageAtRow:row column:col];
  209.     if (i != 0)
  210.     {
  211.     NSPoint origin;
  212.     NSSize offset;
  213.     [self calcOrigin:&origin andOffset:&offset forImage:i inRect:r
  214.         atRow:row column:col downEvent:mouseDown dragEvent:dragEvent];
  215.     
  216.     NSPasteboard* pb = [NSPasteboard pasteboardWithName:NSDragPboard];
  217.     [self prepareDragPasteboard:pb atRow:row column:col];
  218.     
  219.     [self dragImage:i at:origin offset:offset
  220.         event:mouseDown pasteboard:pb source:self slideBack:YES];
  221.     ret = YES;
  222.     }
  223.     return ret;
  224.     }
  225.  
  226.  
  227. //-----------------------------------------------------------------------------
  228. // awaitDragEvent:atRow:column:
  229. //-----------------------------------------------------------------------------
  230. - (BOOL)awaitDragEvent:(NSEvent*)mouseDown
  231.     atRow:(MiscCoord_P)row column:(MiscCoord_P)col inRect:(NSRect)rect
  232.     {
  233.     float const DELAY = 0.25;
  234.     float const SLOP = 4.0;
  235.     unsigned int const WANTED = (NSLeftMouseUpMask | NSLeftMouseDraggedMask);
  236.  
  237.     BOOL ret = NO;
  238.     NSEvent* event;
  239.     NSWindow* win = [self window];
  240.  
  241.     do    {
  242.     event = [win nextEventMatchingMask:WANTED
  243.         untilDate:[NSDate dateWithTimeIntervalSinceNow:DELAY]
  244.         inMode:NSEventTrackingRunLoopMode dequeue:NO];
  245.     if (event != 0 && [event type] == NSLeftMouseDragged)
  246.         event = [win nextEventMatchingMask:NSLeftMouseDraggedMask];
  247.     } while (event != 0 && [event type] == NSLeftMouseDragged && 
  248.         isSlop( event, mouseDown, SLOP ));
  249.  
  250.     if (event == 0 || [event type] == NSLeftMouseDragged)
  251.     ret = [self performDrag:mouseDown atRow:row column:col inRect:rect
  252.             dragEvent:event];
  253.     return ret;
  254.     }
  255.  
  256.  
  257. //-----------------------------------------------------------------------------
  258. // canPerformDragAtRow:column:withEvent:
  259. //-----------------------------------------------------------------------------
  260. - (BOOL)canPerformDragAtRow:(MiscCoord_P)r column:(MiscCoord_P)c
  261.     withEvent:(NSEvent*)p
  262.     {
  263.     id const scroll = [self scroll];
  264.     id const d = [scroll responsibleDelegate:DF::DEL_ALLOW_DRAG];
  265.     return (d != 0 && 
  266.         [d tableScroll:scroll allowDragOperationAtRow:r column:c] &&
  267.         [scroll responsibleDelegate:DF::DEL_PREPARE_PB_FOR_DRAG] != 0 &&
  268.        ([(NSCell*)[scroll cellAtRow:r column:c] type] == NSImageCellType ||
  269.         [scroll responsibleDelegate:DF::DEL_IMAGE_FOR_DRAG] != 0));
  270.     }
  271.  
  272. @end
  273.