This is BrowserController.m in view mode; [Download] [Up]
// Copyright H. Giesen, University of Koblenz-Landau 1996
#import "BrowserController.h"
#import "Controller.h"
#import "MyBrowserCell.h"
#import "BibliographicFile.h"
#import "BibTeXObject.h"
#import "DragView.h"
#import "Preferences.h"
#define NORMAL
// #define LAZY
// #define VERY_LAZY
@implementation BrowserController
- (void) setUpPopUpListAt:(int)inx
{
NXRect titleFrame;
if( [theBrowser getTitleFrame:&titleFrame ofColumn:inx]==NULL )
if( [theBrowser getTitleFrame:&titleFrame ofColumn:0]==NULL ) return;
titleFrame.W -= 4;
titleFrame.H -= 4;
titleFrame.X += 2;
titleFrame.Y += 2;
if( popUpMatrix[inx].button ) return; // already defined
popUpMatrix[inx].button = [[Button alloc] initFrame:&titleFrame];
// the tag of this button is the selected (default) popUpType
popUpMatrix[inx].list = [[PopUpList alloc] init];
// the tag of listitems (MenuCells) is the corresponding popUpType
// the tag of list's Matrix is the corresponding browser column
[[popUpMatrix[inx].list setAction:@selector(bibPopup:)] setTarget:self];
NXAttachPopUpList( popUpMatrix[inx].button, popUpMatrix[inx].list );
// fill the popUpMenu and set the initial text
// addItem creates and returns a MenuCell
//
if( inx==0 ){
[[popUpMatrix[inx].list addItem:"file"] setTag:D_FILE];
[popUpMatrix[inx].button setTitle:"file"];
[popUpMatrix[inx].button setTag:D_FILE];
}
if( inx==1 ){
[[popUpMatrix[inx].list addItem:"keys (sorted)"] setTag:D_KEY_SORTED];
[[popUpMatrix[inx].list addItem:"keys (as read)"] setTag:D_KEY_AS_READ];
[[popUpMatrix[inx].list addItem:"entries"] setTag:D_ENTRY];
[popUpMatrix[inx].button setTitle:"keys (sorted)"];
[popUpMatrix[inx].button setTag:D_KEY_SORTED];
}
if( inx>1 ){
[[popUpMatrix[inx].list addItem:"keys (sorted)"] setTag:D_KEY_SORTED];
[[popUpMatrix[inx].list addItem:"keys (as read)"] setTag:D_KEY_AS_READ];
[popUpMatrix[inx].button setTitle:"keys (sorted)"];
[popUpMatrix[inx].button setTag:D_KEY_SORTED];
}
[popUpMatrix[inx].list sizeToFit];
[theBrowser addSubview:popUpMatrix[inx].button];
// itemlist is the matrix of MenuCells used by the Menu
[[popUpMatrix[inx].list itemList] setTag:inx];
[popUpMatrix[inx].button display];
}
- (void) setUp
{
int i;
preferences = [Preferences new];
[theBrowser setCellClass:[MyBrowserCell class]];
[theBrowser setTitle:"bibFile" ofColumn:0];
[theBrowser setAction:@selector(singleClick:)];
[theBrowser setDoubleAction:@selector(doubleClick:)];
[theBrowser reuseColumns:YES];
[theBrowser setMultipleSelectionEnabled:YES];
[theBrowser setBranchSelectionEnabled:YES];
[theBrowser useScrollBars:YES];
[theBrowser useScrollButtons:YES];
// the theBrowser must be the first responder :
[theBrowser acceptArrowKeys:YES andSendActionMessages:YES];
[theBrowser setTarget:self];
[theBrowser setAutodisplay:NO];
[theBrowser setMaxVisibleColumns:3];
for(i=0; i<2; i++){
[self setUpPopUpListAt:i];
}
}
// both "icons" are of class DragView
- (void) setUpIcons:fIcon :eIcon
{
entryIcon = eIcon;
fileIcon = fIcon;
[fileIcon clear];
[entryIcon clear];
}
- (NXBrowser *) theBrowser
{
return theBrowser;
}
// return a list of NXBrowserCells
- (List *)selectedFiles
{
if( tempList ) [tempList empty];
else tempList = [[List alloc] initCount:10];
[[theBrowser matrixInColumn:0] getSelectedCells:tempList];
return tempList;
}
- (BibliographicFile *)selectedFile
{
List *aList = [self selectedFiles];
if( [aList count]==0 ) return nil;
return [[aList objectAt:0] fileObject];
}
- bibPopup:sender // sender is matrix of a popUpList
{
int col = [sender tag]; // tag is the browsercolumn
if( col<0 ) return self;
[popUpMatrix[col].button setTag:[[sender selectedCell] tag]];
[theBrowser doClick:[theBrowser matrixInColumn:(col>0)?col-1:0]];
return self;
}
- singleClick:sender // sender is BibBrowser
{
int i = 0;
int selCol = [sender selectedColumn];
Matrix *matrix;
List *selList;
char locBuffer[256];
if( selCol<0 ) return self;
matrix = [sender matrixInColumn:selCol];
selList = [matrix getSelectedCells:nil];
if( [selList count]==0 ){ // nothing selected
[sender getPath:locBuffer toColumn:selCol];
if( locBuffer[0] == '\0' ){
locBuffer[0] = '/';
locBuffer[1] = '\0';
}
[sender setPath:locBuffer];
[entryIcon clear];
if( [self displayTypeInCol:selCol]==D_FILE ) [fileIcon clear];
[[NXApp delegate] browserDidChange:sender];
[[[bibWindow reenableDisplay] displayIfNeeded] reenableFlushWindow];
[sender displayColumn:selCol];
[selList free];
return self;
}
if( [self displayTypeInCol:selCol]==D_FILE ){
[[NXApp delegate] P:self];
[fileIcon setList:selList];
[entryIcon clear];
[selList free];
[[NXApp delegate] browserDidChange:sender];
[[[bibWindow reenableDisplay] displayIfNeeded] reenableFlushWindow];
[[NXApp delegate] V:self];
return self;
}
// show column entrytypes ?
if( [self displayTypeInCol:selCol]==D_ENTRY ){
[entryIcon clear];
[selList free];
[[NXApp delegate] browserDidChange:sender];
[[[bibWindow reenableDisplay] displayIfNeeded] reenableFlushWindow];
return self;
}
// [self displayTypeInCol:selCol]==D_KEY_SORTED
[entryIcon setList:selList];
[selList free];
[[NXApp delegate] browserDidChange:sender];
//[selectionButton display];
while( popUpMatrix[i].button ){
[popUpMatrix[i++].button display];
}
[[[bibWindow reenableDisplay] displayIfNeeded] reenableFlushWindow];
return self;
}
- doubleClick:sender
{
NXTextStyle *theStyle;
int selCol;
Matrix *matrix;
BibliographicFile *fileObj;
char locBuffer[1024];
selCol = [sender selectedColumn];
matrix = [sender matrixInColumn:selCol];
fileObj = [[matrix selectedCell] fileObject];
switch( [self displayTypeInCol:selCol] ){
case D_FILE :
{
if( BIBTEST==NO ) return self;
[fileObj showFile];
return self;
}
case D_KEY_SORTED :
case D_KEY_AS_READ :
{
BibTeXObject *obj = [[matrix selectedCell] object]; // ?????
locType theRange = [obj range];
char *buf = [obj buffer];
[testDocView setSel:0 :[testDocView textLength]];
theStyle = [testDocView defaultParaStyle];
[testDocView setParaStyle:theStyle];
[testDocView replaceSel:&buf[theRange.start]
length:theRange.length];
[testDocView setSel:0 :0];
[testDocView scrollSelToVisible];
[testPanel setDelegate:self];
sprintf( locBuffer, "%s in %s",
[[matrix selectedCell] stringValue], [fileObj fileName] );
[testPanel setTitle:locBuffer];
[testPanel orderFront:self];
[asciiDragView setTextObject:testDocView];
[testDocView addText:"\n"];
if(0)[obj callTheEditorForFile:[fileObj fullPath]
inLine:[obj line]];
return self;
}
case D_ENTRY : return self;
default : return self;
}
return self;
}
- entryObjectChanged:(BibTeXObject *)obj
{
int pos;
int lastCol = [theBrowser lastColumn];
int dspType = [self displayTypeInCol:lastCol];
List *objList;
Matrix *matrix = [theBrowser matrixInColumn:lastCol];
int selRow = [matrix selectedRow];
MyBrowserCell *selCell = [theBrowser selectedCell];
MyBrowserCell *newCell;
if( dspType!=D_KEY_SORTED )
if( dspType!=D_KEY_AS_READ ) return self;
if( [self displayTypeInCol:lastCol-1]!=D_FILE ){
objList = [[selCell fileObject]
listForType:[[theBrowser matrixInColumn:lastCol-1] selectedRow]
sorted:dspType==D_KEY_SORTED];
}
else
if( [self displayTypeInCol:[theBrowser lastColumn]]==D_KEY_AS_READ )
objList = [[selCell fileObject] listOfBibObjects];
else objList = [[selCell fileObject] listOfSortedBibObjects];
usedEntryList = objList;
if( obj==[selCell object] ){
[[matrix removeRowAt:selRow andFree:NO] sizeToCells];
}
pos = [objList indexOf:obj];
if( pos<0 ){
newCell = nil;
}
else{ //NORMALBROWSER
[matrix insertRowAt:pos];
//newCell = [matrix cellAt:pos :0];
newCell = [theBrowser getLoadedCellAtRow:pos inColumn:lastCol];
[newCell setEnabled:YES];
[obj setStringOf:[obj key] to:newCell];
[newCell setLeaf:YES];
[newCell setObject:obj inFile:[selCell fileObject]];
[newCell setLoaded:YES];
}
[matrix sizeToCells];
[matrix selectCell:newCell];
{
List *selList = [matrix getSelectedCells:nil];
[entryIcon setList:selList];
[selList free];
}
[matrix scrollCellToVisible:pos :0];
[theBrowser displayColumn:[theBrowser lastColumn]];
return self;
}
// includesType() returns YES if type is included within types.
BOOL includesType (const NXAtom *types, NXAtom type)
{
if (types)
while (*types){
//fprintf( stderr, "%s\n", *types );
if (*types++ == type) return YES;
}
return NO;
}
- getBibdata:(id)pasteboard
userData:(const char *)serviceArgs
error:(char **)errorMessage
{
int length;
const char *data;
if( includesType([pasteboard types], NXAsciiPboardType) ){
[pasteboard readType:NXAsciiPboardType data:&data length:&length];
[testDocView setSel:0 :[testDocView textLength]];
[testDocView setParaStyle:[testDocView defaultParaStyle]];
[testDocView replaceSel:data length:length];
[testDocView setSel:0 :0];
[testDocView scrollSelToVisible];
[testPanel setDelegate:self];
[testPanel orderFront:self];
[asciiDragView setTextObject:testDocView];
}
else *errorMessage = "could not copy selection";
return self;
}
- selectFile:(BibliographicFile *)aFile
{
Matrix *matZero = [theBrowser matrixInColumn:0];
int rowCount, colCount, i;
[matZero getNumRows:&rowCount numCols:&colCount];
[matZero selectCellAt:-1 :-1]; // deselect
for( i=0; i<rowCount; i++ ){
if( [[theBrowser getLoadedCellAtRow:i inColumn:0] fileObject]==aFile ){
[[matZero selectCellAt:i :0] scrollCellToVisible:i :0];
[matZero sendAction]; // calls - singleClick:
[theBrowser displayColumn:0];
//[theBrowser loadColumnZero];
return self;
}
}
return self;
}
- (int) fillMatrix:locMatrix withFiles:(List *)listOfFiles
{
int i;
// listOfFiles is the sorted list of all loaded files
if( (listOfFiles==nil) || ([listOfFiles count]==0) ){
[fileIcon clear]; // no file selected
[entryIcon clear];
return 0;
}
for( i=0; i<[listOfFiles count]; i++ ){
NXBrowserCell *newCell;
BibliographicFile *fileObj = [listOfFiles objectAt:i];
[locMatrix addRow];
newCell = [locMatrix cellAt:i :0];
[newCell setEnabled:YES];
[[[[newCell setStringValue:[fileObj fileName]]
setLeaf:NO]
setLoaded:YES]
setObject:nil inFile:fileObj];
}
[fileIcon clear]; // no file selected
[entryIcon clear];
return [listOfFiles count];
}
- resetBrowser:sender
{
[theBrowser loadColumnZero];
[[[bibWindow reenableDisplay] displayIfNeeded] reenableFlushWindow];
return self;
}
- (int) fillMatrix:locMatrix withKeysForFile:(BibliographicFile *)file
display:(int)dspType
{
int i;
MyBrowserCell *newCell;
BibTeXObject *litObj;
List *theList;
[[bibWindow disableDisplay] disableFlushWindow];// enabled in singleClick
[entryIcon clear];
if( dspType==D_KEY_AS_READ ) theList = [file listOfBibObjects];
else theList = [file listOfSortedBibObjects];
usedEntryList = theList;
litObj = [theList objectAt:0];
for( i=0; litObj; i++ ) {
[locMatrix addRow];
newCell = [locMatrix cellAt:i :0];
[newCell setEnabled:YES];
[litObj setStringOf:[litObj key] to:newCell];
[newCell setLeaf:YES];
[newCell setObject:litObj inFile:file];
[newCell setLoaded:YES];
litObj = [theList objectAt:i+1];
}
return i;
}
- (int) fillMatrix:locMatrix withKeysForFile:(BibliographicFile *)file
andEntryType:(int)entryType display:(int)dspType
{
int i;
BibTeXObject *litObj;
List *typedList;
NXBrowserCell *newCell;
[[bibWindow disableDisplay] disableFlushWindow];// enabled in singleClick
[entryIcon clear];
typedList = [file listForType:entryType sorted:dspType==D_KEY_SORTED];
usedEntryList = typedList;
for( i=0; i<[typedList count]; i++ ){
litObj = [typedList objectAt:i];
[locMatrix addRow];
newCell = [locMatrix cellAt:i :0];
[newCell setEnabled:YES];
[litObj setStringOf:[litObj key] to:newCell];
[[newCell setLeaf:YES]
setObject:litObj inFile:file];
[newCell setLoaded:YES];
}
return [typedList count];
}
- (int) fillMatrix:locMatrix withEntryTypesForFile:(BibliographicFile *)file
{
int i;
NXBrowserCell *newCell;
List *entryNameList = [preferences entryNameList];
[[bibWindow disableDisplay] disableFlushWindow];// enabled in singleClick
for( i=0; i<[entryNameList count]; i++ ){
[locMatrix addRow];
newCell = [locMatrix cellAt:i :0];
[newCell setStringValue:(const char *)[entryNameList objectAt:i]];
[[newCell setLeaf:NO] setObject:nil inFile:file];
[newCell setLoaded:YES];
[newCell setEnabled:([file countForType:i]!=0)];
}
return [entryNameList count];
}
- (Matrix *) matrixInColumn:(int) col
{
return [theBrowser matrixInColumn:col];
}
- (void) entryListDidChange:(int)row to:(int)nr
{
int lastColumn = [theBrowser lastColumn];
Matrix *matrix;
if( lastColumn==0 ) return;
if( [self displayTypeInCol:lastColumn-1]!=D_ENTRY ) return;
matrix = [theBrowser matrixInColumn:lastColumn-1];
[[theBrowser getLoadedCellAtRow:row inColumn:lastColumn-1] setEnabled:nr>0];
if( nr==0 ) [matrix selectCellAt:-1 :-1]; // deselect
[matrix display];
}
- (void) deselectColumn:(int)col
{
if( col<0 ) col = [theBrowser lastColumn];
[entryIcon setList:nil];
[[theBrowser matrixInColumn:col] selectCellAt:-1 :-1]; // deselect
}
- (void) selectList:(List *)aList inColumn:(int)column
{
int i, row=0;
Matrix *matrix = [theBrowser matrixInColumn:column];
[matrix selectCellAt:-1 :-1]; // deselect all
for( i= [aList count]-1; i>=0; i-- ){
row = [usedEntryList indexOf:[aList objectAt:i]];
if( row>=0 )
[matrix setSelectionFrom:row to:row anchor:row lit:YES];
}
[matrix scrollCellToVisible:row :0]; // scroll to last row
}
- (void) selectEntryObjects:(List *)aList
{
int i, row=0;
int column = [theBrowser lastColumn];
int dspType = [self displayTypeInCol:column];
Matrix *matrix = [theBrowser matrixInColumn:column];
List *selList;
[matrix selectCellAt:-1 :-1]; // deselect all
if( (dspType!=D_KEY_SORTED) )
if( (dspType!=D_KEY_AS_READ) ) return;
for( i= [aList count]-1; i>=0; i-- ){
row = [usedEntryList indexOf:[aList objectAt:i]];
if( row>=0 )
[matrix setSelectionFrom:row to:row anchor:row lit:YES];
}
selList = [matrix getSelectedCells:nil];
[entryIcon setList:selList];
[selList free];
[matrix scrollCellToVisible:row :0]; // scroll to last row
[[NXApp delegate] browserDidChange:self];
}
- (int)displayTypeInCol:(int)col
{
return [popUpMatrix[col].button tag];
}
- (int) fillMatrix:locMatrix forFile:(BibliographicFile *)aFile
display:(int)dspType
select:(int)entryType
{
if( dspType==D_ENTRY ){
return [self fillMatrix:locMatrix withEntryTypesForFile:aFile];
}
if( entryType==-1 ){ // show all keys
return [self fillMatrix:locMatrix withKeysForFile:aFile display:dspType];
}
// show keys for a selected entryType only
return [self fillMatrix:locMatrix
withKeysForFile:aFile andEntryType:entryType display:dspType];
return 0;
}
- browserDidScroll:sender
{
//[[sender reenableDisplay] display];
if(0)fprintf( stderr, "%s didScroll %d %d (%d)\n",
[sender name],
[sender firstVisibleColumn],
[sender lastVisibleColumn], [sender lastColumn] );
[self windowDidResize:sender];
return self;
}
#ifdef VERY_LAZY
- browser:sender loadCell:cell atRow:(int)row inColumn:(int)column
{
if(0)fprintf( stderr, "loadCellat %d %d isLoaded=%d\n",
row, column, [cell isLoaded] );
if( column==0 ){
BibliographicFile *fileObj = [[[NXApp delegate] listOfFiles] objectAt:row];
[cell setEnabled:YES];
[cell setStringValue:[fileObj fileName]];
[cell setLeaf:NO];
[cell setLoaded:YES];
[cell setObject:nil inFile:fileObj];
[fileIcon clear]; // no file selected
[entryIcon clear];
return self;
}
if( column==1 ){
BibliographicFile *selFile=
[[[self matrixInColumn:0] selectedCell] fileObject];
BibTeXObject *litObj;
usedEntryList = [selFile listOfBibObjects];
litObj = [usedEntryList objectAt:row];
[cell setEnabled:YES];
[litObj setStringOf:[litObj key] to:cell];
[cell setLeaf:YES];
[cell setObject:litObj inFile:selFile];
[cell setLoaded:YES];
return self;
}
return self;
}
- (int) browser:sender getNumRowsInColumn:(int)column
{
//fprintf( stderr, "getNumRowsInColumn %d\n", column );
if( column==0 ){
return [[[NXApp delegate] listOfFiles] count];
}
if( column==1 ){
BibliographicFile *selFile=
[[[self matrixInColumn:0] selectedCell] fileObject];
return [[selFile listOfBibObjects] count];
}
return 2;
}
#endif // very lazy
#ifdef NORMAL
- (int) browser:sender fillMatrix:locMatrix inColumn:(int)column
{
int count, dspType, eType;
BibliographicFile *selFile=
[[[self matrixInColumn:0] selectedCell] fileObject];
Matrix *matrix = [theBrowser matrixInColumn:column-1];
int index = [matrix selectedRow];
if( popUpMatrix[column].button==nil ){
//fprintf( stderr, "new button\n" );
[self setUpPopUpListAt:column];
[popUpMatrix[column].button display];
}
if( column==0 ){
count = [self fillMatrix:locMatrix
withFiles:[[NXApp delegate] listOfFiles] ];
[[NXApp delegate] colZeroIsFilled];
return count;
}
if( [self displayTypeInCol:column-1]==D_FILE )
eType = -1; // display keys for all entryTypes
else eType = index; // entryType is the selectedRow (by accident)
switch( dspType = [self displayTypeInCol:column] ){
case D_FILE : break; // col 0 ???
case D_ENTRY:
case D_KEY_SORTED :
case D_KEY_AS_READ :
return [self fillMatrix:locMatrix
forFile:selFile display:dspType select:eType];
default : return 0;
}
fprintf( stderr, "ERROR in fillmatrix\n" );
return 0;
}
#endif // normal
// returns the new state of the menuCell
// YES = enabled
// NO = disabled
- (BOOL)updateMenuFor:menuCell
{
BOOL newState=NO; // .. and the compiler keeps silent
switch( [menuCell tag] ){
case CUT :
case COPY :
case PASTE :
case SELECTALL :
case ENTERSELECTION : newState = YES; break;
default : newState = [[NXApp delegate]updateMenuFor:menuCell];
break;
}
return newState;
}
// copy selected text to findPasteBoard
- enterSelection:sender
{
[[NXApp delegate] enterSelectionFor:testDocView];
return self;
}
- windowDidResize:sender
{
NXRect titleFrame;
int i = 0;
while( popUpMatrix[i].button ){
if( [theBrowser getTitleFrame:&titleFrame ofColumn:i] ){
titleFrame.W -= 4;
titleFrame.H -= 4;
titleFrame.X += 2;
titleFrame.Y += 2;
if( [popUpMatrix[i].button superview]==nil )
[theBrowser addSubview:popUpMatrix[i].button];
[popUpMatrix[i].button setFrame:&titleFrame];
}
else [popUpMatrix[i].button removeFromSuperview];
i++;
}
return self;
}
- selectAllIn:matrix column:(int)col
{
List *selList = nil;
switch( [self displayTypeInCol:col] ){
case D_FILE :
selList = [matrix getSelectedCells:nil];
[fileIcon setList:selList];
break;
case D_KEY_SORTED :
case D_KEY_AS_READ :
selList = [matrix getSelectedCells:nil];
[entryIcon setList:selList];
default : break;
}
if( selList ) [selList free];
[[NXApp delegate] browserDidChange:self];
return self;
}
- (BOOL)browser:sender columnIsValid:(int)column
{
return YES;
}
- (BOOL)browser:sender selectCell:(const char *)entry inColumn:(int)column
{
return YES;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.