This is DragView.m in view mode; [Download] [Up]
// Copyright H. Giesen, University of Koblenz-Landau 1996 #import "Controller.h" #import "DragView.h" #import "BibTeXObject.h" #import "MyBrowserCell.h" #import "Shelf.h" #import "Preferences.h" #import "BufferClass.h" #import "BibliographicFile.h" #import "BrowserController.h" static const char * dragTypes[3]; NXAtom MyListPboardType; NXImage *entryImage = nil; NXImage *entryImageH; NXImage *entryImageMulti; NXImage *entryImageMultiH; NXImage *fileImage = nil; NXImage *fileImageH; NXImage *fileImageMulti; NXImage *fileImageMultiH; NXImage *alertImage; NXImage *closedBag; NXImage *smallImage; #define ENTRY 1 #define BIBOBJECT 2 #define BIBFILE 3 #define TXTOBJECT 4 #define NAMETEXTTAG 6 #define DRAGVIEWTAG 7 static BufferClass *globalBuffer; @implementation DragView - initialize { if( entryImage==nil ){ // set class variables MyListPboardType = NXUniqueString( "My List Pboard Type" ); entryImage = [NXImage findImageNamed:"Images/text"]; entryImageH = [NXImage findImageNamed:"Images/text"]; entryImageMulti = [NXImage findImageNamed:"Images/multiEntries"]; entryImageMultiH = [NXImage findImageNamed:"Images/multiEntries"]; fileImage = [NXImage findImageNamed:"Images/bibA"]; fileImageH = [NXImage findImageNamed:"Images/bibB"]; fileImageMulti = [NXImage findImageNamed:"Images/multiBook"]; fileImageMultiH = [NXImage findImageNamed:"Images/multiBook"]; smallImage = [NXImage findImageNamed:"Images/smallIcon"]; alertImage = [NXImage findImageNamed:"Images/bibAlert"]; closedBag = [NXImage findImageNamed:"Images/closedBag"]; globalBuffer = [[BufferClass alloc] initBufferSize:128]; } theObject = [[List alloc] init]; theCell = [[MyBrowserCell alloc] initTextCell:"empty"]; preferences = [Preferences new]; oldMask = 0xafffe; return self; } - initFrame:(const NXRect *)frameRect { [super initFrame:frameRect]; isSelected = NO; return [self initialize]; } - setShelf:(View *)theShelf { shelf = theShelf; return self; } - awake // called when unarchived { return [self initialize]; } - free { [self clear]; [theObject free]; [theCell free]; if( fileName ) free( fileName ); return [super free]; } - display { char locBuf[64]; char *fName; TextField *titleField = [[self superview] findViewWithTag:NAMETEXTTAG]; if( titleField==nil ) return [super display]; if( theType == BIBFILE ){ fName = rindex( fileName, '/' ); if( fName ) [titleField setStringValue:fName+1]; else [titleField setStringValue:fileName]; return [super display]; } if( theImage==nil ) [titleField setStringValue:NULL]; else if( [theObject count]>1 ){ sprintf( locBuf, "%d selected", [theObject count] ); [titleField setStringValue:locBuf]; } else if( theType ){ [titleField setStringValue: [[theObject objectAt:0] stringValue]]; } [super display]; return self; } - (void) setFilename:(const char *)fName { if( fileName ) free( fileName ); fileName = NXCopyStringBuffer( fName ); [theCell setObject:nil inFile:nil]; theImage = anImage = fileImage; anImageH = fileImageH; anImageMulti = fileImageMulti; anImageMultiH = fileImageMultiH; theType = BIBFILE; [theObject empty]; theImage = closedBag; if( access( fName, R_OK)<0 ){ // cannot read from file theImage = alertImage; } [self display]; } - (char *) fileName { if( theType==BIBFILE) return fileName; if( (theType==BIBOBJECT) && ([theObject count]==1) ) return [[[theObject objectAt:0] fileObject] fullPath]; return NULL; } - (void) setList:(List *)aList // aList is a list of NXBrowsercells { int newType; if( aList!=theObject ){ [theObject empty]; [theObject appendList:aList]; } if( aList==nil ){ [self clear]; return; } if( [[aList objectAt:0] object] ){ // bib_entry exist newType = ENTRY; } else newType = BIBOBJECT; if( newType!=theType ){ switch( newType ){ case ENTRY : anImage = entryImage; anImageH = entryImageH; anImageMulti = entryImageMulti; anImageMultiH = entryImageMultiH; break; case BIBOBJECT: anImage = fileImage; anImageH = fileImageH; anImageMulti = fileImageMulti; anImageMultiH = fileImageMultiH; break; default: break; } theType = newType; } if( [theObject count]==1 ) theImage = anImage; else theImage = anImageMulti; [self display]; } - getList // returns a list of NXBrowsercells { return theObject; } - (unsigned int) count { return [theObject count]; } - (void) setTextObject:(Text *)aText { [theObject empty]; [theObject addObject:aText]; theType = TXTOBJECT; theImage = smallImage; anImage = theImage; anImageH = theImage; anImageMulti = theImage; anImageMultiH = theImage; [self display]; } - (void )setFileObject:(BibliographicFile *)aFile { // use a NXBrowserCell for compatibility [theCell setObject:nil inFile:aFile]; [theCell setStringValue:[aFile fileName]]; [theObject empty]; [theObject addObject:theCell]; [self setList:theObject]; } - (int)tag { return DRAGVIEWTAG; } - drawSelf:(const NXRect *)rects :(int)rectCount { if( isSelected ) PSsetgray( NX_WHITE ); else PSsetgray( NX_LTGRAY ); NXRectFill( &bounds ); if( theImage ){ [theImage composite:NX_SOVER toPoint:&bounds.origin]; // was &r.org } return self; } - (void) clear { theImage = nil; [theObject empty]; if( shelf ) [[NXApp delegate] shelfText:NULL]; [self display]; } - unregister { if( theType!=BIBOBJECT ) return self; theType = BIBFILE; theImage = closedBag; [self unregisterDraggedTypes]; [self display]; return self; } //vvvvvvvvvvvvvvvvv receiving dragging // includesType() returns YES if type is included within types. static BOOL includesType (const NXAtom *types, NXAtom type) { if (types) while (*types){ //fprintf( stderr, "%s\n", *types ); if (*types++ == type) return YES; } return NO; } - (NXDragOperation)draggingEntered:(id <NXDraggingInfo>)sender { NXDragOperation rtn = [self draggingUpdated:sender]; if( (rtn==NX_DragOperationGeneric) || (rtn==NX_DragOperationCopy) ){ // change the Image theImage = anImageH; [self display]; } return rtn; } - (NXDragOperation)draggingUpdated:(id <NXDraggingInfo>)sender { Pasteboard *pboard = [sender draggingPasteboard]; char *data, *lastDot, *file, *tab; int length; if( [theObject count]!=1 ) return NX_DragOperationNone; if( [sender draggingSource]==self ){ fprintf( stderr, "it's me\n" ); return NX_DragOperationNone; } if( ([sender draggingSourceOperationMask] & NX_DragOperationGeneric) ||([sender draggingSourceOperationMask] & NX_DragOperationCopy) ){ if( includesType([pboard types], MyListPboardType) ){ //fprintf( stderr, "MyListPboardType in fileDragView\n" ); return NX_DragOperationCopy; } else if( includesType([pboard types], NXAsciiPboardType) ){ //fprintf( stderr, "NXAsciiPboardType in fileDragView\n" ); return NX_DragOperationCopy; } else if( includesType([pboard types], NXFilenamePboardType) ){ //fprintf( stderr, "NXFilenamePboardType in fileDragView\n" ); [pboard readType:NXFilenamePboardType data:&data length:&length]; // is it a list of files ? file = data; while (file) { if( tab = strchr(file, '\t') ) { *tab = '\0'; } lastDot = rindex( file, '.' ); if( lastDot ){ if( strcmp( lastDot, ".bib" ) ) { // only .bib allowed return NX_DragOperationNone; } } else return NX_DragOperationNone; // no suffix -> invalid file = (tab) ? ++tab : NULL; } return NX_DragOperationGeneric; } } fprintf( stderr, "komisch\n" ); return NX_DragOperationNone; } - draggingExited:sender { //fprintf( stderr, "DragView draggingExited\n" ); if( [theObject count]!=1 ) return self; theImage = anImage; [self display]; return self; } - (BOOL)performDragOperation:(id <NXDraggingInfo>)sender { char *data; id *aList; int length; BOOL rtn = NO; Pasteboard *pboard = [sender draggingPasteboard]; if (includesType([pboard types], MyListPboardType)) { [pboard readType:MyListPboardType data:&data length:&length]; aList = (id *)data; // theObject is a list of one NXBrowsercell // we extract the fileObject from the first NXBrowserCell // send a list of entryObjects to the fileObject [[[theObject objectAt:0] fileObject] addObjects:*aList]; rtn = YES; } else if (includesType([pboard types], NXAsciiPboardType)) { [pboard readType:NXAsciiPboardType data:&data length:&length]; // theObject is a list of one NXBrowsercell // we extract the fileObject from the first NXBrowserCell // we send the ASCII - text to the fileObject [[[theObject objectAt:0] fileObject] appendNewText:length :data]; [pboard deallocatePasteboardData:data length:length]; rtn = YES; } // change the Image theImage = anImage; [self display]; return rtn; } //^^^^^^^^^^^^^^^^^ end of receiving dragging // | | | active dragging // V V V - (NXDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal { return NX_DragOperationGeneric | NX_DragOperationCopy; } - (void) convertBoundsToScreen:(NXRect *)screenRect { NXRect theRect; theRect = bounds; [self convertRect:&theRect toView:nil]; [[self window] convertBaseToScreen:&theRect.origin]; *screenRect = theRect; } - mouseDown:(NXEvent *)e { NXPoint startPoint = e->location; int nrOfClicks = e->data.mouse.click; savedEvent = *e; oldMask = [[self window] addToEventMask:NX_MOUSEDRAGGEDMASK]; [self convertPoint:&startPoint fromView:nil]; if( theType == TXTOBJECT ){ //fprintf( stderr, "mouse down for text\n" ); return self; } if( nrOfClicks==12345 ){ isSelected = YES; [self display]; return self; } if( isSelected ){ isSelected = NO; [self display]; } return self; } - mouseUp:(NXEvent *)e { int nrOfClicks = e->data.mouse.click; // 'help' = '?' sends mouseUp but no mouseDown --> error: // "Assertion failed: // setting NX_KEYDOWN mask while window is visible is illegal" // we avoid this situation by looking for (mouseDown-mouseUp) pair if( oldMask == 0xafffe ) return self; // something is wrong, no mouseDown if( nrOfClicks==1 ){ char *theName; isSelected = NO; //YES; if( shelf==nil ) return self; if( theType == BIBFILE ) theName = fileName; else theName = [[[theObject objectAt:0] fileObject] fullPath]; [[NXApp delegate] shelfText:theName]; if( theType == BIBFILE ){ int okFlag; [NXApp openFile:fileName ok:&okFlag]; } // start animation { NXRect sourceRect; NXRect destRect; id theView = [[NXApp delegate] fileDragView]; [self convertBoundsToScreen:&sourceRect]; [theView convertBoundsToScreen:&destRect]; [[Application workspace] slideImage:theImage from:&sourceRect.origin to:&destRect.origin]; } [[[NXApp delegate] browserController] selectFile:[[theObject objectAt:0] fileObject]]; } [[self window] setEventMask:oldMask]; oldMask = 0xafffe; return self; } - citation { int i; int mode = [preferences citeMode]; char buffer[1024]; BibTeXObject *texObj; // theObject is a list of browsercells of Class MyBrowserCell // [theObject objectAt:i] is a cell (odf class MyBrowserCell) if( mode==1 ) // cite{..} cite{..} cite{..} . . . for( i=0; i<[theObject count]; i++ ){ texObj = [[theObject objectAt:i] object]; NXPrintf( dragStream, [preferences citeText] ); NXPrintf( dragStream, "%c", LBRACE ); [texObj copyRange:[texObj key] toBuffer:buffer]; NXPrintf( dragStream, "%s", buffer ); NXPrintf( dragStream, "%c", RBRACE ); if( i!=([theObject count]-1) ) NXPrintf( dragStream, "%s", ", " ); } if( mode==2 ){ // cite{ .., .., . . . } NXPrintf( dragStream, [preferences citeText] ); NXPrintf( dragStream, "%c", LBRACE ); for( i=0; i<[theObject count]; i++ ){ texObj = [[theObject objectAt:i] object]; [texObj copyRange:[texObj key] toBuffer:buffer]; NXPrintf( dragStream, "%s", buffer ); if( i!=([theObject count]-1) ) NXPrintf( dragStream, "%s", "," ); // no space allowed!! } NXPrintf( dragStream, "%c", RBRACE ); } if( mode==3 ){ // drag the text of the selected entries NXPrintf( dragStream, "\n" ); for( i=0; i<[theObject count]; i++ ){ texObj = [[theObject objectAt:i] object]; [texObj copyRange:[texObj range] toStream:dragStream]; NXPrintf( dragStream, "\n\n" ); } NXPrintf( dragStream, "\n\n" ); } return self; } - copyCitation:sender { Pasteboard *pboard = [Pasteboard newName:NXGeneralPboard]; if( !dragStream ) dragStream = NXOpenMemory(NULL, 0, NX_READWRITE); NXSeek(dragStream, 0, NX_FROMSTART); // prepare the citation text [self citation]; /* place the citation-text on the ascii-pasteboard. */ [pboard declareTypes:&NXAsciiPboardType num:1 owner:nil]; [pboard writeType:NXAsciiPboardType fromStream:dragStream]; NXCloseMemory( dragStream, NX_FREEBUFFER ); dragStream = NULL; return self; } - mouseDragged:(NXEvent *)theEvent { int i; NXPoint point = theEvent->location; NXPoint origin = {0.0, 0.0}; char fName[128]; Pasteboard *pboard; if( !theObject ) return self; [NXApp preventWindowOrdering]; [self convertPoint:&point fromView:nil]; //[super mouseDown:&savedEvent]; /* You always use the NXDragPboard pasteboard when dragging. */ pboard = [Pasteboard newName:NXDragPboard]; switch( theType ){ case 0: return self; case BIBOBJECT: /* place the name of the file on the pasteboard. */ [pboard declareTypes:&NXFilenamePboardType num:1 owner:nil]; // theObject is a list of one NXBrowsercell // first we write the names into a stream if( !dragStream ) dragStream = NXOpenMemory(NULL, 0, NX_READWRITE); NXSeek(dragStream, 0, NX_FROMSTART); for( i=0; i<[theObject count]; i++ ){ NXPrintf( dragStream, "%s", [[[theObject objectAt:i] fileObject] fullPath] ); if( i==[theObject count]-1 ) NXPutc(dragStream, '\0'); else NXPutc(dragStream, '\t'); } [pboard writeType:NXFilenamePboardType fromStream:dragStream]; NXCloseMemory( dragStream, NX_FREEBUFFER ); dragStream = NULL; break; case ENTRY: { if( !dragStream ) dragStream = NXOpenMemory(NULL, 0, NX_READWRITE); NXSeek(dragStream, 0, NX_FROMSTART); // prepare the citation text [self citation]; if( strcmp( [preferences theEditor], "Edit" )==0 ){ //Edit.app /* place the citation-text on the ascii-pasteboard. */ [pboard declareTypes:&NXAsciiPboardType num:1 owner:nil]; [pboard writeType:NXAsciiPboardType fromStream:dragStream]; } else{ // emacs or so sprintf( fName, "%s/citeFile", [preferences tempDirectory] ); // copy the text to a file NXSaveToFile( dragStream, fName ); /* place the filename on the filename-pasteboard. */ [pboard declareTypes:&NXFilenamePboardType num:1 owner:nil]; sprintf( [globalBuffer buffer], fName ); [pboard writeType:NXFilenamePboardType data:[globalBuffer buffer] length:strlen( [globalBuffer buffer] )+1]; } /* place also the list of entries on my private pasteboard. */ [pboard addTypes:&MyListPboardType num:1 owner:self]; [pboard writeType:MyListPboardType data:(const char *)(&theObject) length:sizeof(id) ]; NXCloseMemory( dragStream, NX_FREEBUFFER ); dragStream = NULL; break; } case BIBFILE: /* place the name of the file on the pasteboard. */ [pboard declareTypes:&NXFilenamePboardType num:1 owner:nil]; [pboard writeType:NXFilenamePboardType data:fileName length:strlen( fileName )+1]; break; case TXTOBJECT:{ int length; Text *theText = [theObject objectAt:0]; NXSelPt start, end; if( theText==nil ) return self; [theText getSel:&start :&end]; if( start.cp<0 ){ // text is not first responder return self; } length = end.cp - start.cp; if( length<=0 ){ [theText selectAll:self]; } /* place the selected text on the pasteboard. */ dragTypes[0] = NXAsciiPboardType; dragTypes[1] = NULL; [pboard declareTypes:dragTypes num:1 owner:nil]; if( [theText writeSelectionToPasteboard:pboard types:dragTypes] ){ break; } NXRunAlertPanel("Bibliography", "could not write to pasteboard", " OK ", // 1: default button NULL, // 0: alternate NULL //-1: other ); break; } default : fprintf( stderr, "unknown case %d\n", theType ); } /* Now invoke dragImage: */ [self dragImage:theImage at:&origin offset:NULL event:&savedEvent pasteboard:pboard source:self slideBack:NO]; return self; } - draggedImage : (NXImage *)image endedAt : (NXPoint *)screenPoint deposited : (BOOL)didDeposit { NXRect winRect; if( didDeposit ) return self; if( shelf==nil ) return self; // shall not remove [[self window] getFrame:&winRect]; if( NXPointInRect(screenPoint,&winRect) ){ return self; } if(0)fprintf( stderr, "x=%d y=%d %d\n", (int)screenPoint->x, (int)screenPoint->y, didDeposit ); theType = 0; [shelf removeBoxWithIcon:self]; return self; } - (BOOL)shouldDelayWindowOrderingForEvent:(NXEvent *)theEvent { // This is the other portion of the new appkit functionality // which allows you to drag a partially obscure object without // making the source window become main, and without making the // source application the current app. return YES; } - (BOOL)acceptsFirstMouse { return YES; } //^^^^^^^^^^^^^^^^^ end of active dragging @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.