This is PianoOctave.m in view mode; [Download] [Up]
/* One octave of a piano keyboard control. Drawing code by Doug Keislar. */
#import "PianoOctave.h"
#import <appkit/nextstd.h>
#import <dpsclient/dpsNeXT.h>
#import <dpsclient/wraps.h>
#define HIGHLIGHTCOLOR NX_DKGRAY
enum keyRectNum {CLOW,CUP,DLOW,DUP,ELOW,EUP,FLOW,FUP,GLOW,GUP,
ALOW,AUP,BLOW,BUP,CSH,DSH,FSH,GSH,ASH};
static int rectToKey[] = {0,0,2,2,4,4,5,5,7,7,9,9,11,11,1,3,6,8,10};
static int keyToRect[] = {0,14,2,15,4,6,16,8,17,10,18,12};
@implementation PianoOctave : Control
{
}
- initFrame:(const NXRect *)frameRect
/* Initialize all the key rects according to the frameRect size */
{
double viewWidth,viewHeight, viewX,viewY,
lowerWhiteWidth, lowerWhiteHeight,
CDEupperWidth, upperWhiteHeight ,FGABupperWidth,
blackWidth,blackHeight, gap,
upperWhiteY,blackY,whitePlusGap;
self = [super initFrame:frameRect];
viewX = bounds.origin.x;
viewY = bounds.origin.y;
viewWidth = bounds.size.width;
viewHeight = bounds.size.height;
gap = 4;
lowerWhiteWidth = viewWidth/7 - gap;
lowerWhiteHeight = viewHeight * .4;
whitePlusGap = lowerWhiteWidth + gap;
blackWidth = lowerWhiteWidth / 2.0;
upperWhiteY = lowerWhiteHeight;
upperWhiteHeight = viewHeight - lowerWhiteHeight;
blackY = upperWhiteY + gap;
blackHeight = upperWhiteHeight - gap;
CDEupperWidth = ((whitePlusGap*3)-gap -
(blackWidth*2+gap*4))/3;
FGABupperWidth = ((whitePlusGap*4)-gap-
(blackWidth*3+gap*6))/4;
NXSetRect(&keyRects[CLOW],0,0,lowerWhiteWidth,lowerWhiteHeight);
NXSetRect(&keyRects[DLOW],whitePlusGap,0,
lowerWhiteWidth, lowerWhiteHeight);
NXSetRect(&keyRects[ELOW],whitePlusGap*2.0,0,
lowerWhiteWidth,lowerWhiteHeight);
NXSetRect(&keyRects[FLOW],whitePlusGap*3.0,0,
lowerWhiteWidth,lowerWhiteHeight);
NXSetRect(&keyRects[GLOW],whitePlusGap*4.0,0,
lowerWhiteWidth,lowerWhiteHeight);
NXSetRect(&keyRects[ALOW],whitePlusGap*5.0,0,
lowerWhiteWidth,lowerWhiteHeight);
NXSetRect(&keyRects[BLOW],whitePlusGap*6.0,0,
lowerWhiteWidth,lowerWhiteHeight);
NXSetRect(&keyRects[CUP],0,upperWhiteY,
CDEupperWidth,upperWhiteHeight);
NXSetRect(&keyRects[CSH],CDEupperWidth+gap,blackY,
blackWidth,blackHeight);
NXSetRect(&keyRects[DUP],CDEupperWidth + gap *2 + blackWidth,
upperWhiteY,CDEupperWidth,upperWhiteHeight);
NXSetRect(&keyRects[DSH],CDEupperWidth*2+gap*3+blackWidth,blackY,
blackWidth,blackHeight);
NXSetRect(&keyRects[EUP],viewWidth*3/7-CDEupperWidth-gap,
upperWhiteY,CDEupperWidth,upperWhiteHeight);
NXSetRect(&keyRects[FUP],whitePlusGap*3.0,
upperWhiteY,FGABupperWidth,upperWhiteHeight);
NXSetRect(&keyRects[FSH],whitePlusGap*3.0+FGABupperWidth+
gap,blackY,blackWidth,blackHeight);
NXSetRect(&keyRects[GUP],whitePlusGap*3.0+FGABupperWidth+
gap*2+blackWidth,upperWhiteY,FGABupperWidth,upperWhiteHeight);
NXSetRect(&keyRects[GSH],whitePlusGap*3.0+FGABupperWidth*2+
gap*3+blackWidth,blackY,blackWidth,blackHeight);
NXSetRect(&keyRects[AUP],
viewWidth-(FGABupperWidth*2+gap*3+blackWidth),
upperWhiteY,FGABupperWidth,upperWhiteHeight);
NXSetRect(&keyRects[ASH],
viewWidth-(FGABupperWidth+gap*2+blackWidth),
blackY,blackWidth,blackHeight);
NXSetRect(&keyRects[BUP],viewWidth-(FGABupperWidth+gap),
upperWhiteY,FGABupperWidth,upperWhiteHeight);
value = -1;
return self;
}
- drawSelf:(const NXRect *)rects :(int)rectCount
/* doesn't call drawKey, since the latter sets lockFocus etc. */
{
PSsetgray(NX_WHITE);
NXRectFillList(&keyRects[CLOW],14);
PSsetgray(NX_BLACK);
NXRectFillList(&keyRects[CSH],5);
return self;
}
- setKey:(int) keyNum toState:(int)state
/* Programmatically set the state of a particular key */
{
int rectNum;
if (keyNum < 0 || keyNum > 11) return self;
rectNum= keyToRect[keyNum];
keyStates[keyNum] = state;
[self lockFocus];
if (rectNum < 14) {
PSsetgray(state? HIGHLIGHTCOLOR: NX_WHITE);
NXRectFillList(&keyRects[rectNum],2);
}
else {
PSsetgray(state? HIGHLIGHTCOLOR: NX_BLACK);
NXRectFill(&keyRects[rectNum]);
}
[self unlockFocus];
[window flushWindow];
return self;
}
- mouseDown: (NXEvent *) event
/* Find the key rect in which the cursor is located, and send a message
* to the target.
*/
{
int i;
[self convertPoint:&(event->location) fromView:nil];
for (i=0; i<19; i++)
if (NXPointInRect(&(event->location),&keyRects[i])) {
value = rectToKey[i];
[self setKey:value toState:!keyStates[value]];
[self sendAction:action to:target];
break;
}
return self;
}
- mouseUp: (NXEvent *) event
/* Send a message to the target when the mouse button goes up as well */
{
if (keyStates[value] && !(event->flags & NX_COMMANDMASK)) {
[self setKey:value toState:0];
[self sendAction:action to:target];
}
return self;
}
- (BOOL) acceptsFirstMouse;
{
return(YES);
}
- (int)intValue
{
return value;
}
- setTarget:anObject
{
target = anObject;
return self;
}
- setAction:(SEL)aSelector
{
action = aSelector;
return self;
}
- (int)state:(int)keyNum
{
return keyStates[keyNum];
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.