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.