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.