This is ColumnMatrix.m in view mode; [Download] [Up]
/* Generated by Interface Builder */ #import "ColumnMatrix.h" @implementation ColumnMatrix + newFrame:(const NXRect *)frameRect { id newPrototype; NXSize newIntercell = {0.0, 0.0}, newCellSize; char **data = calloc(1, sizeof(char *)); float *tab = calloc(1, sizeof(float)); self = [super newFrame:frameRect mode:NX_LISTMODE prototype:[IconColumnCell new] numRows:0 numCols:1]; [protoCell setBordered:TRUE]; [protoCell setAlignment:NX_LEFTALIGNED]; // this whole section is an ugly kluge because the protoCell // won't return the correct calcCellSize, since it has no // data. if we give it data, the clones won't work. so we // create a new prototype cell, and get its size. newPrototype = [IconColumnCell new]; [newPrototype setBordered:TRUE]; [newPrototype setNumColumns:1]; [newPrototype setTabs:tab]; data[0] = "data"; [newPrototype setData:data]; [newPrototype calcCellSize:&newCellSize]; [newPrototype free]; newCellSize.height--; newCellSize.width = frameRect->size.width; [self setCellSize:&newCellSize]; [self setIntercell:&newIntercell]; [self setBackgroundGray:NX_LTGRAY]; [self setAutoscroll:TRUE]; itemsList = [HashList new]; return self; } - (BOOL)acceptsFirstResponder { return TRUE; } - superviewSizeChanged:(const NXSize*)oldSize { NXSize newCellSize; [super superviewSizeChanged:oldSize]; newCellSize.width = bounds.size.width; newCellSize.height = cellSize.height; [self setCellSize:&newCellSize]; [self calcTabs]; return self; } - calcTabs { int i, cellIndex; for (i=0; i<numColumns; i++) { realTabs[i] = tabs[i] * bounds.size.width; } [protoCell setTabs:(float *)&realTabs]; for (cellIndex=0; cellIndex<numRows; cellIndex++) [((List *)cellList)->dataPtr[cellIndex] setTabs:(float *)&realTabs]; return self; } #ifdef STUPID - _mouseDown_listMode:(NXEvent *)event; { int cellIndex; Item *item; id ret; BOOL kill = FALSE; firstCheckRow = numRows+1; lastCheckRow = 0; ret = [super _mouseDown_listMode:event]; for (cellIndex = lastCheckRow; cellIndex >= firstCheckRow; cellIndex--) { item = (((IconColumnCell *) (((List*)cellList)->dataPtr[cellIndex]))->aux); #ifdef DEBUG printf("Checking cell %d, visible %d\n", cellIndex, item->shown); #endif if (!item->shown) { kill = TRUE; [self removeRowAt:cellIndex andFree:TRUE]; } } if (kill) { [self updateCells]; [[self superview] display]; } return ret; } #endif - _highlightCellAt:(int)row :(int)col lit:(BOOL)lit andDraw:(BOOL)draw { Item *item; #ifdef STUPID if (!lit) { item = (((IconColumnCell *)(((List *)cellList)->dataPtr[row]))->aux); if (![self itemVisible:item]) { firstCheckRow = MIN(firstCheckRow, row); lastCheckRow = MAX(lastCheckRow, row); } } #endif [super _highlightCellAt:row :col lit:lit andDraw:draw]; return [self drawCellAt:row :col]; } - updateCells { int itemIndex, cellIndex, newCellCount = 0, itemCount = [itemsList count]; int prevItemIndex, row, col, nextRow; Item *item, *prevItem; IconColumnCell *aCell; BOOL wasShown, add = FALSE, kill = FALSE; if (!numRows) { // boy, is this ugly, and boy, is it fast. for (itemIndex=0; itemIndex<itemCount; itemIndex++) { item = ((List *)itemsList)->dataPtr[itemIndex]; newCellCount += [self itemVisible:item]; } [self setCellCount:newCellCount]; for (itemIndex=0, cellIndex=0; itemIndex<itemCount; itemIndex++) { item = ((List *)itemsList)->dataPtr[itemIndex]; if (item->shown) { item->cell = ((List *)cellList)->dataPtr[cellIndex]; [((List *)cellList)->dataPtr[cellIndex] setAux:item]; cellIndex++; } else { item->cell = nil; } } [self sizeToCells]; [self selectCellAt:-1 :-1]; add = (newCellCount > 0); } else { for (itemIndex=0; itemIndex<itemCount; itemIndex++) { item = ((List *)itemsList)->dataPtr[itemIndex]; wasShown = item->shown; newCellCount += [self itemVisible:item]; if ((wasShown) && (!item->shown)) { kill = TRUE; ((IconColumnCell *)(item->cell))->aux = nil; item->cell = nil; } else if ((!wasShown) && (item->shown)) { add = TRUE; item->cell = nil; } } if (kill) { for (cellIndex=numRows-1; cellIndex >= 0; cellIndex--) { aCell = [cellList objectAt:cellIndex]; if (!aCell->aux) [self removeRowAt:cellIndex andFree:TRUE]; } for (itemIndex=0, cellIndex=0; itemIndex<itemCount; itemIndex++) { item = ((List *)itemsList)->dataPtr[itemIndex]; if (item->cell && item->shown) { if (cellIndex >= numRows) exit(1); item->cell = ((List *)cellList)->dataPtr[cellIndex]; [((List *)cellList)->dataPtr[cellIndex] setAux:item]; cellIndex++; } } } if (add) { for (itemIndex=itemCount-1; itemIndex >= 0; itemIndex--) { item = ((List *)itemsList)->dataPtr[itemIndex]; if (item->shown && !item->cell) { nextRow = 0; for (prevItemIndex=itemIndex-1; (nextRow == 0)&&(prevItemIndex >= 0); prevItemIndex--) { if ((prevItem=((List *)itemsList)->dataPtr[prevItemIndex])->cell) { if ([self getRow:&row andCol:&col ofCell:prevItem->cell]) { nextRow = row+1; } } } [self insertRowAt:nextRow]; item->cell = ((List *)cellList)->dataPtr[nextRow]; [((List *)cellList)->dataPtr[nextRow] setAux:item]; } } for (itemIndex=0, cellIndex=0; itemIndex<itemCount; itemIndex++) { item = ((List *)itemsList)->dataPtr[itemIndex]; if (item->shown) { item->cell = ((List *)cellList)->dataPtr[cellIndex]; [((List *)cellList)->dataPtr[cellIndex] setAux:item]; cellIndex++; } } } [self sizeToCells]; } if (add || kill) return nil; else return self; } - setCell:aCell fromItem:item { [item setCell:aCell]; [aCell setAux:item]; return self; } // Hmm, this is just begging to be subclassed, eh? - (BOOL)itemVisible:item { return TRUE; } - setCellCount:(int)newCount { int i; // if (newCount > numRows) [self renewRows:newCount cols:1]; // else // while (newCount < numRows) // [self removeRowAt:numRows-1 andFree:TRUE]; return self; } - empty { [itemsList freeObjects]; [self setCellCount:0]; [self sizeToCells]; [[self superview] display]; [self selectCellAt:-1 :-1]; [self sendAction]; return self; } - selectedCell { return realSelectedCell; } - selectAll:sender { int cellIndex; for (cellIndex = 0; cellIndex < [cellList count]; cellIndex++) { // [[cellList objectAt:cellIndex] setIntValue:TRUE]; [self highlightCellAt:cellIndex :0 lit:TRUE]; } selectedRow = [cellList count]; selectedCell = [cellList objectAt:selectedRow]; [self sendAction]; return [[self superview] display]; } - sendAction:(SEL)theAction to:theTarget { int cellIndex; id ret; if (refreshTarget) { refreshTarget = FALSE; realSelectedCell = nil; [super sendAction:theAction to:theTarget]; } firstSelectedRow = -1; lastSelectedRow = numRows; for (cellIndex=0; cellIndex<numRows; cellIndex++) { if ([(id)(((List *)cellList)->dataPtr[cellIndex]) isHighlighted]) { lastSelectedRow = cellIndex; if (firstSelectedRow == -1) firstSelectedRow = cellIndex; } } if ((firstSelectedRow == lastSelectedRow) && (firstSelectedRow >= 0)) { realSelectedRow = firstSelectedRow; realSelectedCell = ((List *)cellList)->dataPtr[realSelectedRow]; [self scrollCellToVisible:realSelectedRow :0]; } else { realSelectedRow = lastSelectedRow = firstSelectedRow = -1; realSelectedCell = nil; } ret = [super sendAction:theAction to:theTarget]; if (![self updateCells]) { [[self superview] display]; [self sendAction]; } return ret; } - selectUp:sender { if ((firstSelectedRow > 0) && (firstSelectedRow <= numRows-1)) { [self selectCellAt:--firstSelectedRow :0]; [self sendAction]; } else if (firstSelectedRow == 0) { [self selectWayUp:sender]; } else { [self selectCellAt:numRows-1 :0]; [self sendAction]; } return self; } - selectDown:sender { if ((lastSelectedRow >= 0) && (lastSelectedRow < numRows-1)) { [self selectCellAt:++lastSelectedRow :0]; [self sendAction]; } else if (lastSelectedRow == numRows-1) { [self selectWayDown:sender]; } else { [self selectCellAt:0 :0]; [self sendAction]; } return self; } // Subclass, perchance to use. - selectWayUp:sender { return self; } - selectWayDown:sender { return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.