home *** CD-ROM | disk | FTP | other *** search
- //=============================================================================
- //
- // Copyright (C) 1995,1996,1997,1998 by Paul S. McCarthy and Eric Sunshine.
- // Written by Paul S. McCarthy and Eric Sunshine.
- // All Rights Reserved.
- //
- // This notice may not be removed from this source code.
- //
- // This object is included in the MiscKit by permission from the authors
- // and its use is governed by the MiscKit license, found in the file
- // "License.rtf" in the MiscKit distribution. Please refer to that file
- // for a list of all applicable permissions and restrictions.
- //
- //=============================================================================
- //-----------------------------------------------------------------------------
- // MiscTableViewDrag.M
- //
- // Image dragging methods for MiscTableView.
- //
- //-----------------------------------------------------------------------------
- //-----------------------------------------------------------------------------
- // $Id: MiscTableViewDrag.M,v 1.2 98/03/29 23:59:48 sunshine Exp $
- // $Log: MiscTableViewDrag.M,v $
- // Revision 1.2 98/03/29 23:59:48 sunshine
- // v138.1: #import was missing "MiscTableScroll/" for public header.
- // Implemented -shouldDelayWindowOrderingForEvent:
- //
- // Revision 1.1 97/11/23 07:41:42 sunshine
- // v130.1: Image dragging methods.
- //-----------------------------------------------------------------------------
- #import "MiscTableViewPrivate.h"
- #import "MiscTableScrollPrivate.h"
- #import <MiscTableScroll/MiscTableCell.h>
- extern "Objective-C" {
- #import <AppKit/NSApplication.h>
- #import <AppKit/NSImage.h>
- #import <AppKit/NSPasteboard.h>
- #import <AppKit/NSWindow.h>
- }
- extern "C" {
- #import <math.h> // floor()
- }
-
- typedef MiscDelegateFlags DF;
-
- @implementation MiscTableView(Drag)
-
- //=============================================================================
- // IMAGE DRAGGING
- //=============================================================================
- static inline float absval( float x ) { return (x < 0 ? -x : x ); }
- static inline BOOL isSlop( NSEvent* e1, NSEvent* e2, float const slop )
- {
- NSPoint const p1 = [e1 locationInWindow];
- NSPoint const p2 = [e2 locationInWindow];
- return (absval(p1.x - p2.x) <= slop && absval(p1.y - p2.y) <= slop);
- }
-
-
- //-----------------------------------------------------------------------------
- // draggingSourceOperationMaskForLocal:
- //-----------------------------------------------------------------------------
- - (unsigned int)draggingSourceOperationMaskForLocal:(BOOL)flag
- {
- id const scroll = [self scroll];
- id const d = [scroll responsibleDelegate:DF::DEL_DRAG_OP_MASK];
- if (d != 0)
- return [d tableScroll:scroll draggingSourceOperationMaskForLocal:flag];
- return NSDragOperationGeneric;
- }
-
-
- //-----------------------------------------------------------------------------
- // ignoreModifierKeysWhileDragging
- //-----------------------------------------------------------------------------
- - (BOOL)ignoreModifierKeysWhileDragging
- {
- id const scroll = [self scroll];
- id const d = [scroll responsibleDelegate:DF::DEL_DRAG_IGNORE_MODIFIERS];
- if (d != 0)
- return [d tableScrollIgnoreModifierKeysWhileDragging:scroll];
- return YES;
- }
-
-
- //-----------------------------------------------------------------------------
- // shouldDelayWindowOrderingForEvent:
- //-----------------------------------------------------------------------------
- - (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent*)e
- {
- BOOL delay = NO;
- NSPoint const p = [self convertPoint:[e locationInWindow] fromView:0];
- MiscCoord_P r,c;
- if ([self getRow:&r column:&c forPoint:p] &&
- [self canPerformDragAtRow:r column:c withEvent:e])
- {
- id const scroll = [self scroll];
- id d = [scroll responsibleDelegate:DF::DEL_DRAG_DELAY_WIN_ORDERING];
- if (d != 0)
- delay = [d tableScroll:scroll shouldDelayWindowOrderingForEvent:e];
- else
- delay = YES;
- }
- return delay;
- }
-
-
- //-----------------------------------------------------------------------------
- // getDragImageAtRow:column:
- //-----------------------------------------------------------------------------
- - (NSImage*)getDragImageAtRow:(MiscCoord_P)row column:(MiscCoord_P)col
- {
- NSImage* i = 0;
- id const scroll = [self scroll];
- id const d = [scroll responsibleDelegate:DF::DEL_IMAGE_FOR_DRAG];
- if (d != 0)
- i = [d tableScroll:scroll imageForDragOperationAtRow:row column:col];
- if (i == 0)
- {
- NSCell* cell = (NSCell*)[scroll cellAtRow:row column:col];
- if ([cell type] == NSImageCellType)
- i = [cell image];
- }
- return i;
- }
-
-
- //-----------------------------------------------------------------------------
- // calcOrigin:andOffset:forImage:inRect:atRow:column:downEvent:dragEvent:
- //
- // Compute the origin of the image and the offset of the mouse for dragging
- // via NSView's -dragImage:at:offset:... method. There are two cases:
- //
- // CASE *1*: The image being dragged fits exactly in the cell's image area.
- // In this case drag from the point where the mouse went down inside the
- // image's boundry. This give the visual impression of lifting the image
- // exactly from where it is sitting; without it jumping to some other
- // location.
- // CASE *2*: The image is a different size than the cell's image area. In
- // this case just center the image under the mouse.
- //-----------------------------------------------------------------------------
- - (void)calcOrigin:(NSPoint*)origin
- andOffset:(NSSize*)offset
- forImage:(NSImage*)image
- inRect:(NSRect)rect
- atRow:(MiscCoord_P)row
- column:(MiscCoord_P)col
- downEvent:(NSEvent*)downEvent
- dragEvent:(NSEvent*)dragEvent
- {
- offset->width = 0;
- offset->height = 0;
-
- NSSize image_s = [image size];
-
- id cell = [[self scroll] cellAtRow:row column:col];
- NSRect image_r = [cell imageRectForBounds:rect];
-
- if (image_s.width == image_r.size.width && // CASE *1*
- image_s.height == image_r.size.height)
- {
- *origin = image_r.origin;
- if ([self isFlipped])
- origin->y += image_r.size.height;
-
- if (dragEvent != 0 && [dragEvent type] == NSLeftMouseDragged)
- {
- NSPoint ptDrag = [dragEvent locationInWindow];
- NSPoint ptDown = [downEvent locationInWindow];
- offset->width = ptDrag.x - ptDown.x;
- offset->height = ptDrag.y - ptDown.y;
- }
- }
- else // CASE *2*
- {
- *origin = [self convertPoint:[downEvent locationInWindow] fromView:0];
- origin->x -= floor( image_s.width / 2 );
- origin->y -= floor( image_s.height / 2 ) * ([self isFlipped] ? -1 : 1);
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // prepareDragPasteboard:atRow:column:
- //-----------------------------------------------------------------------------
- - (void)prepareDragPasteboard:(NSPasteboard*)pb
- atRow:(MiscCoord_P)row column:(MiscCoord_P)col
- {
- id const scroll = [self scroll];
- id const d = [scroll responsibleDelegate:DF::DEL_PREPARE_PB_FOR_DRAG];
- if (d != 0)
- [d tableScroll:scroll preparePasteboard:pb
- forDragOperationAtRow:row column:col];
- }
-
-
- //-----------------------------------------------------------------------------
- // performDrag:atRow:column:inRect:dragEvent:
- //-----------------------------------------------------------------------------
- - (BOOL)performDrag:(NSEvent*)mouseDown
- atRow:(MiscCoord_P)row
- column:(MiscCoord_P)col
- inRect:(NSRect)r
- dragEvent:(NSEvent*)dragEvent
- {
- BOOL ret = NO;
-
- NSImage* i = [self getDragImageAtRow:row column:col];
- if (i != 0)
- {
- NSPoint origin;
- NSSize offset;
- [self calcOrigin:&origin andOffset:&offset forImage:i inRect:r
- atRow:row column:col downEvent:mouseDown dragEvent:dragEvent];
-
- NSPasteboard* pb = [NSPasteboard pasteboardWithName:NSDragPboard];
- [self prepareDragPasteboard:pb atRow:row column:col];
-
- [self dragImage:i at:origin offset:offset
- event:mouseDown pasteboard:pb source:self slideBack:YES];
- ret = YES;
- }
- return ret;
- }
-
-
- //-----------------------------------------------------------------------------
- // awaitDragEvent:atRow:column:
- //-----------------------------------------------------------------------------
- - (BOOL)awaitDragEvent:(NSEvent*)mouseDown
- atRow:(MiscCoord_P)row column:(MiscCoord_P)col inRect:(NSRect)rect
- {
- float const DELAY = 0.25;
- float const SLOP = 4.0;
- unsigned int const WANTED = (NSLeftMouseUpMask | NSLeftMouseDraggedMask);
-
- BOOL ret = NO;
- NSEvent* event;
- NSWindow* win = [self window];
-
- do {
- event = [win nextEventMatchingMask:WANTED
- untilDate:[NSDate dateWithTimeIntervalSinceNow:DELAY]
- inMode:NSEventTrackingRunLoopMode dequeue:NO];
- if (event != 0 && [event type] == NSLeftMouseDragged)
- event = [win nextEventMatchingMask:NSLeftMouseDraggedMask];
- } while (event != 0 && [event type] == NSLeftMouseDragged &&
- isSlop( event, mouseDown, SLOP ));
-
- if (event == 0 || [event type] == NSLeftMouseDragged)
- ret = [self performDrag:mouseDown atRow:row column:col inRect:rect
- dragEvent:event];
- return ret;
- }
-
-
- //-----------------------------------------------------------------------------
- // canPerformDragAtRow:column:withEvent:
- //-----------------------------------------------------------------------------
- - (BOOL)canPerformDragAtRow:(MiscCoord_P)r column:(MiscCoord_P)c
- withEvent:(NSEvent*)p
- {
- id const scroll = [self scroll];
- id const d = [scroll responsibleDelegate:DF::DEL_ALLOW_DRAG];
- return (d != 0 &&
- [d tableScroll:scroll allowDragOperationAtRow:r column:c] &&
- [scroll responsibleDelegate:DF::DEL_PREPARE_PB_FOR_DRAG] != 0 &&
- ([(NSCell*)[scroll cellAtRow:r column:c] type] == NSImageCellType ||
- [scroll responsibleDelegate:DF::DEL_IMAGE_FOR_DRAG] != 0));
- }
-
- @end
-