This is PopupInTable.m in view mode; [Download] [Up]
/* File: PopupInTable.m Contains: Source code for the Controller of the popup menu button used in the "Input" window, see also InputController.m Written by: Eric Simenel Created: May 1997 Copyright: (c)1997 by Apple Computer, Inc., all rights reserved. Change History (most recent first): You may incorporate this sample code into your applications without restriction, though the sample code has been provided "AS IS" and the responsibility for its operation is 100% yours. However, what you are not permitted to do is to redistribute the source as "DSC Sample Code" after having made changes. If you're going to re-distribute the source, we require that you make it clear in the source that the code was descended from Apple Sample Code, but that you've made changes. */ #import "PopupInTable.h" #import "ComicsObj.h" #import "InputController.h" @implementation PopupInTable // private _reset - (void)_reset { pub = nil; pubTitle = pubChoice = -1; alreadyRemoved = 0; } // private _updateCurrentEditedRowWithPubRemoval - (void)_updateCurrentEditedRowWithPubRemoval:(BOOL)removal { if (removal) { // the pop up is removed from the super view, so it disappears if (!alreadyRemoved) [pub removeFromSuperview]; alreadyRemoved = 1; } // and let's update the current edited line [[ic inputView] deselectRow:pubTitle]; [[ic inputView] selectRow:pubTitle byExtendingSelection:NO]; } - (id)init { if (self = [super init]) [self _reset]; return self; } - (void)releasePub { if (pub) { // first let's make the pop up disappear and update the current edited line [self _updateCurrentEditedRowWithPubRemoval:YES]; // now we can release the pop up itself [pub release]; // and reset our private stuff to prevent confusion later on [self _reset]; } } // the user just selected a menu item, let's see what to do - (void)pubSelect:(id)sender { CTitle *thisTitle = [[ic array] objectAtIndex:pubTitle]; short mod = 0, choice = [pub indexOfSelectedItem], newFlagT = 0, fl = [thisTitle titleFlags]; short brands[] = {mskMarvel, mskDC, mskOther}; short series[] = {mskLong, mskMini}; short kinds[] = {mskMain, mskDual}; short states[] = {mskLive, mskDead}; short grades[] = {mskMint, mskFine, mskGood, mskPoor, mskMiss}; short types[] = {mskComics, mskLuxe, mskNewForm, mskMagazine}; short cntnts[] = {mskStory, mskInfo, mskReprint}; short i, j; switch (pubChoice) { // trivial, we modify the title attributes case 3: case 4: case 5: case 6: { switch (pubChoice) { case 3: newFlagT = ((fl & mskNotBrand ) | brands[choice]); break; case 4: newFlagT = ((fl & mskNotSeries) | series[choice]); break; case 5: newFlagT = ((fl & mskNotKind ) | kinds[choice]); break; case 6: newFlagT = ((fl & mskNotState ) | states[choice]); break; } if (newFlagT != fl) { CTitle *newTitle = [[CTitle alloc] initWithAbb:[thisTitle abb] withTitle:[thisTitle title] withFlag:newFlagT]; [comicsBase modTitle:thisTitle withNewTitle:newTitle]; [[ic array] replaceObjectAtIndex:pubTitle withObject:newTitle]; mod = 1; } break; } // use charIshMenu and shortIshMenu to determine what to do, and on what case 7: case 8: case 9: case 10: case 11: case 12: { CIssue *thisIssue, *newIssue; NSMenuItem *mi; char strDate[10]; switch (charIshMenu[choice]) { // move the selected issue (curIshArray[pubTitle]) to this edit month (shortIshMenu[choice]) case 'm': #if debug NSLog(@"choice m for date %@", [CComics nsStrDate:shortIshMenu[choice]]); #endif thisIssue = [[thisTitle issues] objectAtIndex:[thisTitle findIssue:[ic curIshArray][pubTitle]]]; if (shortIshMenu[choice] != [thisIssue editMonth]) { newIssue = [[CIssue alloc] initWithIsh:[thisIssue issueNumber] withEdit:shortIshMenu[choice] withBuy:[thisIssue buyMonth] withFlag:[thisIssue issueFlags]]; [thisTitle modIssue:thisIssue withNewIssue:newIssue]; mod = 1; [self _updateCurrentEditedRowWithPubRemoval:YES]; } break; // select the (shortIshMenu[choice]) issue and put it in curIshArray[pubTitle] // only useful when many issues of the same title are published the same month (weekly and bi-weekly) // see Action Comics run from 601 to 640 for example case 's': #if debug NSLog(@"choice s for issue %@", [NSString stringWithCString:gnums[shortIshMenu[choice]]]); #endif for(i=0, j=-1; (j==-1); i++) if (charIshMenu[i] == 'w') j = i; mi = [pub itemAtIndex:j]; strcpy(strDate, [[mi title] cString]); strDate[1] = ' '; [mi setTitle:[NSString stringWithCString:strDate]]; mi = [pub itemAtIndex:choice]; strcpy(strDate, [[mi title] cString]); strDate[1] = '>'; [mi setTitle:[NSString stringWithCString:strDate]]; charIshMenu[j] = 's'; charIshMenu[choice] = 'w'; [ic curIshArray][pubTitle] = shortIshMenu[choice]; [ic setTheBuyMonth:[[[thisTitle issues] objectAtIndex:[thisTitle findIssue:shortIshMenu[choice]]] buyMonth]]; [self _updateCurrentEditedRowWithPubRemoval:YES]; [[[[ic inputView] window] contentView] addSubview:pub]; alreadyRemoved = 0; break; // nothing to do here, this menuitem is just for the user to know which issue we're working upon. // it is displayed with a starting ">>" case 'w': #if debug NSLog(@"choice w for issue %@", [NSString stringWithCString:gnums[shortIshMenu[choice]]]); #endif break; // add issue (shortIshMenu[choice]) // or move it to this edit month (the current column) if it was already existing case 'a': #if debug NSLog(@"choice a for issue %@", [NSString stringWithCString:gnums[shortIshMenu[choice]]]); #endif if ((j = ([thisTitle findIssue:shortIshMenu[choice]])) == -1) { newIssue = [[CIssue alloc] initWithIsh:shortIshMenu[choice] withEdit:([ic theEditMonth]-12+pubChoice) withBuy:[ic theBuyMonth] withFlag:defaultFI]; [thisTitle addIssue:newIssue]; mod = 1; [self _updateCurrentEditedRowWithPubRemoval:YES]; } else { short newFlagI; thisIssue = [[thisTitle issues] objectAtIndex:j]; newFlagI = ([thisIssue issueFlags] & mskNotGrade) | mskMint; newIssue = [[CIssue alloc] initWithIsh:[thisIssue issueNumber] withEdit:([ic theEditMonth]-12+pubChoice) withBuy:[ic theBuyMonth] withFlag:newFlagI]; [thisTitle modIssue:thisIssue withNewIssue:newIssue]; mod = 1; [self _updateCurrentEditedRowWithPubRemoval:YES]; } break; // delete the issue (shortIshMenu[choice]) except if it is the last one. // I do this to not to have to test against empty issues array in CTitle or CComics methods all the time case 'd': #if debug NSLog(@"choice d for issue %@", [NSString stringWithCString:gnums[shortIshMenu[choice]]]); #endif if ([thisTitle nbIssues] > 1) { thisIssue = [[thisTitle issues] objectAtIndex:[thisTitle findIssue:[ic curIshArray][pubTitle]]]; [thisTitle deleteIssue:thisIssue]; mod = 1; [ic curIshArray][pubTitle] = [[[thisTitle issues] lastObject] issueNumber]; [self _updateCurrentEditedRowWithPubRemoval:YES]; } else NSRunAlertPanel(@"Comics", @"You can't delete the last issue. Delete the title instead.", @"OK", nil, nil); break; // the "Other..." choice, transform the current cell in an editable one, and start the edition // we'll get the user input in setObjectValue:forTableColumn:row: of InputController case 'o': #if debug NSLog(@"choice o"); #endif [[[[ic inputView] tableColumns] objectAtIndex:pubChoice] setEditable:YES]; [self _updateCurrentEditedRowWithPubRemoval:YES]; [[ic inputView] editColumn:pubChoice row:pubTitle withEvent:nil select:YES]; break; // nothing to do here, "empty" menu item. case ' ': #if debug NSLog(@"choice nothing"); #endif break; } break; } // trivial, we modify the issue (from the "Issue" column) attributes case 15: case 16: case 17: { CIssue *thisIssue = [[thisTitle issues] objectAtIndex:[thisTitle findIssue:[ic curIshArray][pubTitle]]]; short newFlagI = 0, fli = [thisIssue issueFlags]; switch (pubChoice) { case 15: newFlagI = ((fli & mskNotGrade) | grades[choice]); break; case 16: newFlagI = ((fli & mskNotType ) | types[choice]); break; case 17: newFlagI = ((fli & mskNotCntnt) | cntnts[choice]); break; } if (newFlagI != fli) { CIssue *newIssue = [[CIssue alloc] initWithIsh:[thisIssue issueNumber] withEdit:[thisIssue editMonth] withBuy:[thisIssue buyMonth] withFlag:newFlagI]; [thisTitle modIssue:thisIssue withNewIssue:newIssue]; mod = 1; } break; } } // let's not forget to signal that the database has changed if (mod) [ic contentChanged]; } - (void)setUpPopup; { pubTitle = [[ic inputView] clickedRow]; // has the user clicked in an "empty" row? if (pubTitle >= [[ic array] count]) return; pubChoice = [[ic inputView] clickedColumn]; if ((pubChoice > 2) && (pubChoice != 13) && (pubChoice != 14)) { CTitle *thisTitle = [[ic array] objectAtIndex:pubTitle]; CIssue *thisIssue = nil; char miTitle[10]; short i, j, k, k2, nbMI; NSRect aRect; // get the rectangle of the clicked cell aRect = [[ic inputView] frameOfCellAtColumn:pubChoice row:pubTitle]; // convert it in window coordinates aRect = [[[[ic inputView] window] contentView] convertRect:aRect fromView:[ic inputView]]; // add a little extra width aRect.size.width += 28; // and create the pop up button there pub = [[NSPopUpButton alloc] initWithFrame:aRect pullsDown:NO]; [pub setFont:((pubChoice >= 7) && (pubChoice <= 12))?[ic fontNonProp]:[ic fontProp]]; // and set the target and action so that we know when the user is using it [pub setTarget:self]; [pub setAction:@selector(pubSelect:)]; // and now let's put some menu items in the pop up depending on the clicked column if ((pubChoice >= 14) && (pubChoice <= 16)) thisIssue = [[thisTitle issues] objectAtIndex:[thisTitle findIssue:[ic curIshArray][pubTitle]]]; switch (pubChoice) { case 3: [pub addItemWithTitle:@"Marvel"]; [pub addItemWithTitle:@"DC"]; [pub addItemWithTitle:@"Other"]; [pub selectItemWithTitle:[thisTitle brand]]; break; case 4: [pub addItemWithTitle:@"Long"]; [pub addItemWithTitle:@"Mini"]; [pub selectItemWithTitle:[thisTitle series]]; break; case 5: [pub addItemWithTitle:@"Main"]; [pub addItemWithTitle:@"Dual"]; [pub selectItemWithTitle:[thisTitle kind]]; break; case 6: [pub addItemWithTitle:@"Live"]; [pub addItemWithTitle:@"Dead"]; [pub selectItemWithTitle:[thisTitle tstate]]; break; case 7: case 8: case 9: case 10: case 11: case 12: j = -1; i = [ic theEditMonth] - 12 + pubChoice; for(k=0; k<5; k++) monthArray[k] = -1; nbma = 0; nbMI = 0; for(k = [thisTitle nbIssues]-1; (k >= 0) && (j == -1); k--) if (([thisIssue = [[thisTitle issues] objectAtIndex:k] editMonth] == i) && !([thisIssue issueFlags] & mskMiss)) j = k; if (j != -1) { [ic setTheBuyMonth:[thisIssue buyMonth]]; for(k2=j; (k2>=0) && ([thisIssue = [[thisTitle issues] objectAtIndex:k2] editMonth] == i); k2--) if (!([thisIssue issueFlags] & mskMiss)) monthArray[nbma++] = [thisIssue issueNumber]; } if (nbma == 0) { short lastIshP1 = [[[thisTitle issues] lastObject] issueNumber] + 1; [pub addItemWithTitle:[NSString stringWithCString:strcat(strcpy(miTitle, " "),gnums[lastIshP1])]]; charIshMenu[nbMI] = 'a'; shortIshMenu[nbMI++] = lastIshP1; [pub addItemWithTitle:@""]; charIshMenu[nbMI++] = ' '; for(k=lastIshP1-2; k<lastIshP1; k++) if (k >= 0) { [pub addItemWithTitle:[NSString stringWithCString:strcat(strcpy(miTitle, " "),gnums[k])]]; charIshMenu[nbMI] = 'a'; shortIshMenu[nbMI++] = k; } for(k=lastIshP1+1; k<lastIshP1+6; k++) { [pub addItemWithTitle:[NSString stringWithCString:strcat(strcpy(miTitle, " "),gnums[k])]]; charIshMenu[nbMI] = 'a'; shortIshMenu[nbMI++] = k; } [pub addItemWithTitle:@" "]; charIshMenu[nbMI++] = ' '; [pub addItemWithTitle:@"Other..."]; charIshMenu[nbMI] = 'o'; shortIshMenu[nbMI++] = 0; } else { for(k=1; k <= 6; k++) { strcat(strcpy(miTitle, " "), [CComics cStrDate:[ic theEditMonth]-6+k]); [pub addItemWithTitle:[NSString stringWithCString:miTitle]]; charIshMenu[nbMI] = 'm'; shortIshMenu[nbMI++] = [ic theEditMonth]-6+k; } [pub addItemWithTitle:@" "]; charIshMenu[nbMI++] = ' '; for(k=nbma-1; k>=0; k--) { strcpy(miTitle, " "); strcat(miTitle, gnums[monthArray[k]]); miTitle[0] = '>'; if (k == 0) miTitle[1] = '>'; [pub addItemWithTitle:[NSString stringWithCString:miTitle]]; charIshMenu[nbMI] = (k==0)?'w':'s'; shortIshMenu[nbMI++] = monthArray[k]; } [pub addItemWithTitle:@""]; charIshMenu[nbMI++] = ' '; for(k=monthArray[nbma-1]-2; k<monthArray[nbma-1]; k++) if (k >= 0) { [pub addItemWithTitle:[NSString stringWithCString:strcat(strcpy(miTitle, " "),gnums[k])]]; charIshMenu[nbMI] = 'a'; shortIshMenu[nbMI++] = k; } for(k=monthArray[0]+1; k<monthArray[0]+6; k++) { [pub addItemWithTitle:[NSString stringWithCString:strcat(strcpy(miTitle, " "),gnums[k])]]; charIshMenu[nbMI] = 'a'; shortIshMenu[nbMI++] = k; } [pub addItemWithTitle:@" "]; charIshMenu[nbMI++] = ' '; [pub addItemWithTitle:@"Delete"]; [ic curIshArray][pubTitle] = monthArray[0]; charIshMenu[nbMI] = 'd'; shortIshMenu[nbMI++] = [ic curIshArray][pubTitle]; [self _updateCurrentEditedRowWithPubRemoval:NO]; [pub addItemWithTitle:@" "]; charIshMenu[nbMI++] = ' '; [pub addItemWithTitle:@"Other..."]; charIshMenu[nbMI] = 'o'; shortIshMenu[nbMI++] = 0; } break; case 15: [pub addItemWithTitle:@"Mint"]; [pub addItemWithTitle:@"Fine"]; [pub addItemWithTitle:@"Good"]; [pub addItemWithTitle:@"Poor"]; [pub addItemWithTitle:@"Missing"]; [pub selectItemWithTitle:[thisIssue grade]]; break; case 16: [pub addItemWithTitle:@"Comics"]; [pub addItemWithTitle:@"Luxe"]; [pub addItemWithTitle:@"New Format"]; [pub addItemWithTitle:@"Magazine"]; [pub selectItemWithTitle:[thisIssue ishtype]]; break; case 17: [pub addItemWithTitle:@"Story"]; [pub addItemWithTitle:@"Info"]; [pub addItemWithTitle:@"Reprint"]; [pub selectItemWithTitle:[thisIssue content]]; break; } // finally add the pop up button to the content view of the window [[[[ic inputView] window] contentView] addSubview:pub]; // and remember it's here alreadyRemoved = 0; } } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.