home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************
- * CLASS: MiscDragView
- *
- * See the header file for more information on this class.
- *
- * This object is included in the MiscKit by permission from the author
- * 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.
- **************************************************************************/
-
- //#import <misckit/MiscString.h>
- #import <misckit/MiscDragView.h>
-
-
- @implementation MiscDragView
-
- - initFrame: (const NXRect *)frameRect
- {
- [super initFrame: frameRect];
-
- [self setAllowSourceDragging: YES];
- [self setAllowDestinationDragging: YES];
- [self setAcceptForeignDrag: YES];
- [self setAcceptLocalDrag: YES];
- [self setAcceptSelfDrag: YES];
- [self setRetainData: YES];
-
- [self setBorderType: NX_BEZEL];
- dragImage = nil;
- theImage = nil;
- [self setDelegate: nil];
-
- return self;
- }
-
-
-
- - awake
- {
- [super awake];
-
- dragImage = nil;
-
- return self;
- }
-
-
-
- - free
- {
- if (theImage != nil)
- [theImage free];
-
- return [super free];
- }
-
-
-
- - setImage: (NXImage *)anImage
- {
- if ([self image] != nil)
- [theImage free];
- theImage = anImage;
-
- [theImage getSize: &imageSize];
- [theImage setScalable: YES];
- [theImage setDataRetained: YES];
-
- [self display];
- return self;
- }
-
-
-
- // Though the docs for NXImage say that initFromFile: does not need an
- // absolute pathname, I would recommend it. I had problems with it not
- // finding images even when they were in the app wrapper
-
- - setImageByFilename: (char *)aFilename
- {
- [self setImage: [ [NXImage alloc] initFromFile: aFilename] ];
- return self;
- }
-
-
-
- - (NXImage *)image
- {
- return theImage;
- }
-
-
-
-
- // Border Type can be one of NX_BEZEL, NX_GROOVE, NX_LINE, or NX_NOBORDER,
- // same as the appkit's Box.
-
- - setBorderType: (int)aType
- {
- border = aType;
- [self display];
- return self;
- }
-
-
-
- - (int)borderType
- {
- return border;
- }
-
-
-
- // Options that could apply to any subclassed DragView
-
- - setAllowSourceDragging: (BOOL)aBool
- {
- allowSourceDragging = aBool;
-
- return self;
- }
-
-
-
- - (BOOL)allowSourceDragging
- {
- return allowSourceDragging;
- }
-
-
-
- - setAllowDestinationDragging: (BOOL)aBool
- {
- allowDestinationDragging = aBool;
- return self;
- }
-
-
-
- - (BOOL)allowDestinationDragging
- {
- return allowDestinationDragging;
- }
-
-
-
- - setAcceptForeignDrag: (BOOL)aBool
- {
- acceptForeignDrag = aBool;
- return self;
- }
-
-
-
- - (BOOL)acceptForeignDrag
- {
- return acceptForeignDrag;
- }
-
-
-
- - setAcceptLocalDrag: (BOOL)aBool
- {
- acceptLocalDrag = aBool;
- return self;
- }
-
-
-
- - (BOOL)acceptLocalDrag
- {
- return acceptLocalDrag;
- }
-
-
-
- - setAcceptSelfDrag: (BOOL)aBool
- {
- acceptSelfDrag = aBool;
- return self;
- }
-
-
-
- - (BOOL)acceptSelfDrag
- {
- return acceptSelfDrag;
- }
-
-
-
- - setRetainData: (BOOL)aBool
- {
- retainData = aBool;
- return self;
- }
-
-
-
- - (BOOL)retainData
- {
- return retainData;
- }
-
-
-
- /*-------------------- methods to be the source of a dragging operation */
-
- - mouseDown: (NXEvent *)theEvent
- {
- NXPoint zero = {0.0, 0.0};
- NXPoint offset = theEvent->location;
- BOOL slide = YES;
- id dragPB = [Pasteboard newName: NXDragPboard];
-
- if ([self allowSourceDragging] == NO)
- return [super mouseDown: theEvent];
-
- // if the overridden setupForSourceDrag returns yes continue
-
- if ([self setupForSourceDrag])
- {
- [self convertPoint: &offset fromView: nil];
-
- // give the chance to change the offset and dragImage start point
-
- [self calculateDragPoint: &offset andOffset: &zero];
-
- if (dragImage != nil)
- {
- if (![self retainData])
- {
- slide = NO;
-
- // setting theImage to nil will make it disappear, giving
- // the impression that the data was not retained
-
- if (dragImage == theImage)
- theImage = nil;
- else
- [theImage free];
-
- [self display];
- }
-
- // send out the delegate message
-
- [self sourceDragInitiated: self];
-
- // begin the drag session
-
- [NXApp preventWindowOrdering];
-
- [self dragImage: dragImage at: &offset offset: &zero
- event: theEvent pasteboard: dragPB
- source: self slideBack: slide];
- }
- }
-
- return self;
- }
-
-
-
- // This method should be overridden if you want to have some control
- // on where the dragged image is first placed, and how far it is offset
- // from the original mousedown (dragPoint).
-
- - calculateDragPoint: (NXPoint *)dragPoint andOffset: (NXPoint *)offset
- {
- return self;
- }
-
-
-
- // A method that should be overridden in the subclass to put the information
- // on the desired pasteboard and select an image to drag.
-
- - (BOOL)setupForSourceDrag
- {
- return NO;
- }
-
-
-
- // The following are methods from the NXSourceDraggingProtocol that are
- // here so they are easy to lookup.
-
- - (NXDragOperation)draggingSourceOperationMaskForLocal:(BOOL)flag
- {
- return NX_DragOperationAll;
- }
-
-
-
- - draggedImage:(NXImage *)image beganAt:(NXPoint *)screenPoint
- {
- return self;
- }
-
-
-
- // Sends a "sourceDragFinished:" to the delegate if it responds.
-
- - draggedImage:(NXImage *)image endedAt:(NXPoint *)screenPoint
- deposited:(BOOL)flag
- {
- [self sourceDragFinished: flag];
-
- // clean up a little. Since the drag is done, free the dragImage
- // unless it is just a pointer to theImage (the image in the view).
-
- if (![self retainData])
- [dragImage free];
- else
- if (theImage == dragImage)
- dragImage = nil;
- else
- [dragImage free];
-
- return self;
- }
-
-
-
- /*-------------------- methods to be the destination of a dragging operation */
-
- - (NXDragOperation)draggingEntered: sender
- {
- if ([self allowDestinationDragging] == NO)
- return NX_DragOperationNone;
-
- if ([self acceptSelfDrag] == NO && [sender draggingSource] == self)
- return NX_DragOperationNone;
-
- if ([self acceptForeignDrag] == NO && [sender isDraggingSourceLocal] == NO)
- return NX_DragOperationNone;
-
- if ([self acceptLocalDrag] == NO && [sender isDraggingSourceLocal] == YES)
- return NX_DragOperationNone;
-
- // Send a "destinationDragInitiated:" to the delegate
-
- [self destinationDragInitiated: self];
-
- return NX_DragOperationCopy;
- }
-
-
-
- - (NXDragOperation)draggingUpdated: sender
- {
- return [super draggingUpdated: sender];
- }
-
-
-
- // Destination drag came to an end, but was not successful, so send a NO
- // to the delegate
-
- - draggingExited:sender
- {
- [self destinationDragFinished: NO];
- return self;
- }
-
-
-
- - (BOOL)prepareForDragOperation:sender
- {
- return YES;
- }
-
-
-
- - (BOOL)performDragOperation:sender
- {
- return YES;
- }
-
-
-
- // Send the delegate a "destinationDragFinished" message
-
- - concludeDragOperation:sender
- {
- [self destinationDragFinished: YES];
- return self;
- }
-
-
-
- /*-------------------- methods to display, and other useful stuff */
-
- - (BOOL)acceptsFirstMouse
- {
- return YES;
- }
-
-
-
- - (BOOL)shouldDelayWindowOrderingForEvent:(NXEvent *)theEvent
- {
- return YES;
- }
-
-
-
- // delegate methods
-
- - delegate
- {
- return delegate;
- }
-
-
-
- - setDelegate: (id)theDelegate
- {
- delegate = theDelegate;
- return self;
- }
-
-
-
- // Sent from "mouseDown" just before the dragging starts to take place
-
- - sourceDragInitiated: view
- {
- if ([delegate respondsTo: @selector(sourceDragInitiated:)])
- [delegate sourceDragInitiated: view];
- return self;
- }
-
-
-
- // Sent when "draggedImage: endedAt: screenPoint: deposited:" is given
- // control and success is whether the image was deposited in another
- // view somewhere
-
- - sourceDragFinished: (BOOL)success
- {
- if ([delegate respondsTo: @selector(sourceDragFinished:)])
- [delegate sourceDragFinished: success];
- return self;
- }
-
-
-
- // Sent when "draggingEntered:" is given control
-
- - destinationDragInitiated: view
- {
- if ([delegate respondsTo: @selector(destinationDragInitiated:)])
- [delegate destinationDragInitiated: view];
- return self;
- }
-
-
-
- // Sent when "concludeDragOperation:" is given control
-
- - destinationDragFinished: (BOOL)success
- {
- if ([delegate respondsTo: @selector(destinationDragFinished:)])
- [delegate destinationDragFinished: success];
- return self;
- }
-
-
-
- // Draw the border, background color and the image if there is one.
- // I tried to add the scaling code to sizeTo:: but it did not seem
- // that it was called every time the view was resized (almost all the
- // time, but not good enough). So to be safe for now I lumped it all together.
-
- - drawSelf: (const NXRect *)rects :(int)rectCount;
- {
- NXPoint offset;
- NXRect imageRect;
-
-
- switch (border)
- {
- case NX_GROOVE:
- NXDrawGroove (&bounds, rects);
- break;
- case NX_BEZEL:
- NXDrawGrayBezel(&bounds, rects);
- break;
- case NX_LINE:
- NXSetColor (NX_COLORBLACK);
- NXFrameRect (&bounds);
- break;
- case NX_NOBORDER:
- NXSetColor (NX_COLORLTGRAY);
- NXRectFill (&bounds);
- break;
- }
-
- // set so the background color will not wipe the border
-
- imageRect.origin.x = bounds.origin.x + 2;
- imageRect.origin.y = bounds.origin.y + 2;
- imageRect.size.width = bounds.size.width - 4;
- imageRect.size.height = bounds.size.height - 4;
-
- // if there is no image, then no reason to continue
-
- if ([self image] == nil)
- return self;
-
- // use different offsets depending on if image scaled or not
-
- if (imageSize.width > bounds.size.width ||
- imageSize.height > bounds.size.height)
- {
- NXSize scaledSize;
- double xscale, yscale, scale;
-
- // scale the image and keep aspect ratio
-
- xscale = bounds.size.width / imageSize.width;
- yscale = bounds.size.height / imageSize.height;
- scale = ((xscale < yscale) ? xscale : yscale);
- scaledSize.width = (imageSize.width * scale) - 2.0;
- scaledSize.height = (imageSize.height * scale) - 2.0;
-
- offset.x = (bounds.size.width - scaledSize.width) / 2;
- offset.y = (bounds.size.height - scaledSize.height) / 2;
-
- if (xscale < yscale) // so the image is not right on the edge
- offset.x+=2.0;
- else
- offset.y+=1.0;
-
- scaledSize.width -= 3.0; // so when we move the offset,..
- scaledSize.height -= 3.0; // image will be basically centered
-
- [theImage setSize: &scaledSize];
- }
- else
- {
- // no scaling needed
-
- offset = imageRect.origin;
- offset.x += (imageRect.size.width - imageSize.width) / 2.0;
- offset.y += (imageRect.size.height - imageSize.height) / 2.0;
- [theImage setSize: &imageSize];
- }
-
- [theImage composite: NX_SOVER toPoint: &offset];
- return self;
- }
-
-
-
- // Archiving methods
-
- - read: (NXTypedStream *)stream
- {
- [super read: stream];
-
- theImage = NXReadObject (stream);
- NXReadSize (stream, &imageSize);
- NXReadTypes (stream, "i", &border);
-
- delegate = NXReadObject (stream);
- NXReadTypes (stream, "c", &allowSourceDragging);
- NXReadTypes (stream, "c", &allowDestinationDragging);
- NXReadTypes (stream, "cc", &acceptForeignDrag, &acceptLocalDrag);
- NXReadTypes (stream, "cc", &acceptSelfDrag, &retainData);
-
- return self;
- }
-
-
-
- - write: (NXTypedStream *)stream
- {
- [super write: stream];
-
- NXWriteObject (stream, theImage);
- NXWriteSize (stream, &imageSize);
- NXWriteTypes (stream, "i", &border);
-
- NXWriteObjectReference (stream, delegate);
- NXWriteTypes (stream, "c", &allowSourceDragging);
- NXWriteTypes (stream, "c", &allowDestinationDragging);
- NXWriteTypes (stream, "cc", &acceptForeignDrag, &acceptLocalDrag);
- NXWriteTypes (stream, "cc", &acceptSelfDrag, &retainData);
-
- return self;
- }
-
-
-
- - (const char *)getInspectorClassName
- {
- return "MiscDVInspector";
- }
-
-
- @end
-