1.7.5 소스 수정
AppController.h를 오픈하여 아래와 같이 추가합니다. "/* */" 또는 "//"로 주석 처리된 부분은 생략 하셔도 됩니다.
저장 후에 Xcode의 MainMenu.nib를 더블클릭하여 인터페이스 빌더를 실행합니다. Xcode 좌측에서 AppController.h를 드래그 하여 MainMenu.nib 윈도우로 드래그해서 놓습니다.
이 작업은 이전 장에서 하였지만 변경된 AppController를 인터페이스 빌더에서 작업하기 위해 다시 한번 반복합니다. 아래와 같이 AppController의 myWindow 아울렛을 Window에 연결합니다.
MainMenu.nib를 저장 후, 인터페이스 빌더를 닫습니다.
MyWindow.h를 오픈하여 아래와 같이 추가합니다.
MyWindow.m을 오픈하여 아래와 같이 추가 합니다. 사용자의 키입력을 처리하고 AppController에 알려줄 수 있도록 합니다.
1) AppController.h 수정 및 MyWindow 연결
AppController.h를 오픈하여 아래와 같이 추가합니다. "/* */" 또는 "//"로 주석 처리된 부분은 생략 하셔도 됩니다.
#import <Cocoa/Cocoa.h>
/* 해당 버튼의 Tag 값 */
#define BTN_PLUS 100
#define BTN_MINUS 101
#define BTN_MULTIPLE 102
#define BTN_DIVISION 103
#define BTN_RESULT 104
#define BTN_CLEAR 105
@class MyWindow;
@interface AppController : NSObject {
int prevOperation; /* 사용자가 이전에 클릭한 연산 값 */
int isClear; /* 연산을 클릭 후, 다시 값을 입력할 때 지원야 함을 알리는 플래그 */
int totalValue; /* 현재 계산 총 합 */
IBOutlet MyWindow *myWindow; /* 사용자 윈도우 */
IBOutlet NSTextField *txtValue; /* 현재/결과 값 표시 창 */
IBOutlet NSTextField *txtOperation; /* 현재 연산 모드 결과 표시 창 */
IBOutlet NSTextField *txtHistory; /* 연산 내역 표시 창 */
}
- (void)awakeFromNib;
- (void)processCalcul:(int)val;
- (void)processInput:(int)val;
- (IBAction) processCommand:(id)sender;
@end
/* 해당 버튼의 Tag 값 */
#define BTN_PLUS 100
#define BTN_MINUS 101
#define BTN_MULTIPLE 102
#define BTN_DIVISION 103
#define BTN_RESULT 104
#define BTN_CLEAR 105
@class MyWindow;
@interface AppController : NSObject {
int prevOperation; /* 사용자가 이전에 클릭한 연산 값 */
int isClear; /* 연산을 클릭 후, 다시 값을 입력할 때 지원야 함을 알리는 플래그 */
int totalValue; /* 현재 계산 총 합 */
IBOutlet MyWindow *myWindow; /* 사용자 윈도우 */
IBOutlet NSTextField *txtValue; /* 현재/결과 값 표시 창 */
IBOutlet NSTextField *txtOperation; /* 현재 연산 모드 결과 표시 창 */
IBOutlet NSTextField *txtHistory; /* 연산 내역 표시 창 */
}
- (void)awakeFromNib;
- (void)processCalcul:(int)val;
- (void)processInput:(int)val;
- (IBAction) processCommand:(id)sender;
@end
저장 후에 Xcode의 MainMenu.nib를 더블클릭하여 인터페이스 빌더를 실행합니다. Xcode 좌측에서 AppController.h를 드래그 하여 MainMenu.nib 윈도우로 드래그해서 놓습니다.
이 작업은 이전 장에서 하였지만 변경된 AppController를 인터페이스 빌더에서 작업하기 위해 다시 한번 반복합니다. 아래와 같이 AppController의 myWindow 아울렛을 Window에 연결합니다.
MainMenu.nib를 저장 후, 인터페이스 빌더를 닫습니다.
2) MyWindow 소스파일 변경
MyWindow.h를 오픈하여 아래와 같이 추가합니다.
#import <Cocoa/Cocoa.h>
@class AppController;
@interface MyWindow : NSWindow
{
AppController *app;
}
- (void)setAppController:(AppController *)a;
- (void)keyDown:(NSEvent *)event;
@end
@class AppController;
@interface MyWindow : NSWindow
{
AppController *app;
}
- (void)setAppController:(AppController *)a;
- (void)keyDown:(NSEvent *)event;
@end
MyWindow.m을 오픈하여 아래와 같이 추가 합니다. 사용자의 키입력을 처리하고 AppController에 알려줄 수 있도록 합니다.
#import "MyWindow.h"
#import "AppController.h"
@implementation MyWindow
/* AppControllerd에서 호출 */
- (void)setAppController:(AppController *)a
{
app = a;
}
/* 키가 눌려질 경우, 자동으로 호출된다. */
- (void)keyDown:(NSEvent *)event
{
int keyCode;
int val = -1;
/* 현재 눌려진 키값을 얻어 온다. */
keyCode = [event keyCode];
NSLog(@"KEY: %d", keyCode);
/* 키값을 AppController에서 처리할 수 있도록 변경해 준다.
각각의 키값은 좌측 숫자키 보드에서 누른 키값들이며, 위의 NSLog에서 확인할 수 있다. */
if(keyCode >= 82 && keyCode <= 90) // 0~7
val = keyCode - 82;
else if(keyCode ==91) // 8
val = 8;
else if(keyCode ==92) // 9
val = 9;
else if(keyCode == 67) // *
val = BTN_MULTIPLE;
else if(keyCode == 75) // /
val = BTN_DIVISION;
else if(keyCode == 69) // +
val = BTN_PLUS;
else if(keyCode == 78) // -
val = BTN_MINUS;
else if(keyCode == 71) // clear
val = BTN_CLEAR;
else if(keyCode == 81) // =
val = BTN_RESULT;
/* val이 세팅되어 처리해야 될 값일 경우에, AppController의 processInput에 값을 넘겨 준다. */
if(val != -1)
[app processInput:val];
[self interpretKeyEvents:[NSArray arrayWithObject:event]];
}
@end
#import "AppController.h"
@implementation MyWindow
/* AppControllerd에서 호출 */
- (void)setAppController:(AppController *)a
{
app = a;
}
/* 키가 눌려질 경우, 자동으로 호출된다. */
- (void)keyDown:(NSEvent *)event
{
int keyCode;
int val = -1;
/* 현재 눌려진 키값을 얻어 온다. */
keyCode = [event keyCode];
NSLog(@"KEY: %d", keyCode);
/* 키값을 AppController에서 처리할 수 있도록 변경해 준다.
각각의 키값은 좌측 숫자키 보드에서 누른 키값들이며, 위의 NSLog에서 확인할 수 있다. */
if(keyCode >= 82 && keyCode <= 90) // 0~7
val = keyCode - 82;
else if(keyCode ==91) // 8
val = 8;
else if(keyCode ==92) // 9
val = 9;
else if(keyCode == 67) // *
val = BTN_MULTIPLE;
else if(keyCode == 75) // /
val = BTN_DIVISION;
else if(keyCode == 69) // +
val = BTN_PLUS;
else if(keyCode == 78) // -
val = BTN_MINUS;
else if(keyCode == 71) // clear
val = BTN_CLEAR;
else if(keyCode == 81) // =
val = BTN_RESULT;
/* val이 세팅되어 처리해야 될 값일 경우에, AppController의 processInput에 값을 넘겨 준다. */
if(val != -1)
[app processInput:val];
[self interpretKeyEvents:[NSArray arrayWithObject:event]];
}
@end
3) AppController.m 소스파일 변경
#import "AppController.h"
#import "MyWindow.h"
@implementation AppController
/* awakeFromNib는 nib파일이 로드된 후, 오브젝트들에게 보내지는 메세지 입니다.
어플리케이션 실행 후, 각종 초기화 작업을 할 수 있습니다.
*/
- (void)awakeFromNib
{
isClear = 0;
prevOperation = 0;
totalValue = 0;
/* myWindow의 AppController 변수를 세팅합니다.
myWindow는 키보드 입력시 이 AppController로 전달합니다.
*/
[myWindow setAppController:self];
}
/* 연산자 (+, -, X, /, = )가 입력되었을 경우, 처리 합니다. */
- (void)processCalcul:(int)val
{
/* 이전에 설정된 연산자를 처리한다. */
if(prevOperation == BTN_PLUS)
totalValue += [txtValue intValue];
else if(prevOperation == BTN_MINUS)
totalValue -= [txtValue intValue];
else if(prevOperation == BTN_MULTIPLE)
totalValue *= [txtValue intValue];
else if(prevOperation == BTN_DIVISION)
totalValue /= [txtValue intValue];
/* 연산명령이 처음 수행되었을 경우에는, 결과값을 현재 입력된 값으로 설정 합니다. */
if([[txtHistory stringValue] length] < 1)
totalValue = [txtValue intValue];
char operation;
NSString *strTemp;
/* 입력된 키에 따라 출력될 문자를 설정 합니다. */
if(val == BTN_PLUS)
operation = '+';
else if(val == BTN_MINUS)
operation = '-';
else if(val == BTN_MULTIPLE)
operation = '*';
else if(val == BTN_DIVISION)
operation = '/';
else
operation = '=';
/* 계산 History에 출력될 값으로 = 일 경우에는 결과값을 출력합니다. */
if(val == BTN_RESULT)
strTemp = [[NSString alloc] initWithFormat:@"= %d\n", totalValue];
else
strTemp = [[NSString alloc] initWithFormat:@"%c", operation];
/* clear 모드를 1로 설정해 이후 다시 숫자를 입력 하면, 이전 결과 값이 지워진 후,
새 입력값이 나올 수 있도록 합니다.
prevOperation에 다음 연산 작업을 위해 입력된 연산값을 저장합니다.
*/
isClear = 1;
prevOperation = val;
/* 연산 창에 현재 연산모드를 출력합니다. */
[txtOperation setStringValue:[NSString stringWithFormat:@"%c", operation]];
/* 연산내역 창에 현재 연산 내역을 추가 합니다. */
[txtHistory setStringValue:[NSString stringWithFormat:@"%@ %@ %@",
[txtHistory stringValue],
[txtValue stringValue],
strTemp]];
/* 결과 창에 현재까지 계산된 결과를 보여 줍니다. */
[txtValue setFloatValue:totalValue];
[strTemp release];
}
/* 버튼 클릭과 사용자의 키보드 입력을 처리 합니다. */
- (void)processInput:(int)val
{
NSString *strTemp;
if(val >= 0 && val <= 9)
{
/* 숫자가 입력되었을 경우, 처리 합니다. */
if(isClear == 1)
{
/* 연산을 클릭하고, 처음 숫자가 입력되었을 경우 결과창을 초기화 합니다. */
[txtValue setStringValue:@""];
isClear = 0;
}
/* 결과 창에 현재 입력된 값을 추가하여 출력 합니다. */
strTemp = [NSString stringWithFormat:@"%@%d", [txtValue stringValue], val];
[txtValue setStringValue:strTemp];
}
else if(val == BTN_CLEAR)
{
/* clear 키를 입력하였을 경우, 데이터와 출력을 초기화 합니다. */
isClear = 0;
prevOperation = 0;
[txtValue setStringValue:@""];
[txtHistory setStringValue:@""];
[txtOperation setStringValue:@""];
}
else if(val >= BTN_PLUS && val <= BTN_RESULT)
{
/* 연산이 입력되었을 경우에 현재 값이 있는지 확인 후 처리 합니다. */
if([[txtValue stringValue] length] > 0)
[self processCalcul:val];
}
}
/* 버튼이 클릭되었을 경우에, processInput에 알려 줍니다. */
- (IBAction) processCommand:(id)sender
{
/* 현재 선택(클릭)된 버튼의 tag값을 얻어 옵니다. */
int val = [[sender selectedCell] tag];
[self processInput:val];
}
@end
#import "MyWindow.h"
@implementation AppController
/* awakeFromNib는 nib파일이 로드된 후, 오브젝트들에게 보내지는 메세지 입니다.
어플리케이션 실행 후, 각종 초기화 작업을 할 수 있습니다.
*/
- (void)awakeFromNib
{
isClear = 0;
prevOperation = 0;
totalValue = 0;
/* myWindow의 AppController 변수를 세팅합니다.
myWindow는 키보드 입력시 이 AppController로 전달합니다.
*/
[myWindow setAppController:self];
}
/* 연산자 (+, -, X, /, = )가 입력되었을 경우, 처리 합니다. */
- (void)processCalcul:(int)val
{
/* 이전에 설정된 연산자를 처리한다. */
if(prevOperation == BTN_PLUS)
totalValue += [txtValue intValue];
else if(prevOperation == BTN_MINUS)
totalValue -= [txtValue intValue];
else if(prevOperation == BTN_MULTIPLE)
totalValue *= [txtValue intValue];
else if(prevOperation == BTN_DIVISION)
totalValue /= [txtValue intValue];
/* 연산명령이 처음 수행되었을 경우에는, 결과값을 현재 입력된 값으로 설정 합니다. */
if([[txtHistory stringValue] length] < 1)
totalValue = [txtValue intValue];
char operation;
NSString *strTemp;
/* 입력된 키에 따라 출력될 문자를 설정 합니다. */
if(val == BTN_PLUS)
operation = '+';
else if(val == BTN_MINUS)
operation = '-';
else if(val == BTN_MULTIPLE)
operation = '*';
else if(val == BTN_DIVISION)
operation = '/';
else
operation = '=';
/* 계산 History에 출력될 값으로 = 일 경우에는 결과값을 출력합니다. */
if(val == BTN_RESULT)
strTemp = [[NSString alloc] initWithFormat:@"= %d\n", totalValue];
else
strTemp = [[NSString alloc] initWithFormat:@"%c", operation];
/* clear 모드를 1로 설정해 이후 다시 숫자를 입력 하면, 이전 결과 값이 지워진 후,
새 입력값이 나올 수 있도록 합니다.
prevOperation에 다음 연산 작업을 위해 입력된 연산값을 저장합니다.
*/
isClear = 1;
prevOperation = val;
/* 연산 창에 현재 연산모드를 출력합니다. */
[txtOperation setStringValue:[NSString stringWithFormat:@"%c", operation]];
/* 연산내역 창에 현재 연산 내역을 추가 합니다. */
[txtHistory setStringValue:[NSString stringWithFormat:@"%@ %@ %@",
[txtHistory stringValue],
[txtValue stringValue],
strTemp]];
/* 결과 창에 현재까지 계산된 결과를 보여 줍니다. */
[txtValue setFloatValue:totalValue];
[strTemp release];
}
/* 버튼 클릭과 사용자의 키보드 입력을 처리 합니다. */
- (void)processInput:(int)val
{
NSString *strTemp;
if(val >= 0 && val <= 9)
{
/* 숫자가 입력되었을 경우, 처리 합니다. */
if(isClear == 1)
{
/* 연산을 클릭하고, 처음 숫자가 입력되었을 경우 결과창을 초기화 합니다. */
[txtValue setStringValue:@""];
isClear = 0;
}
/* 결과 창에 현재 입력된 값을 추가하여 출력 합니다. */
strTemp = [NSString stringWithFormat:@"%@%d", [txtValue stringValue], val];
[txtValue setStringValue:strTemp];
}
else if(val == BTN_CLEAR)
{
/* clear 키를 입력하였을 경우, 데이터와 출력을 초기화 합니다. */
isClear = 0;
prevOperation = 0;
[txtValue setStringValue:@""];
[txtHistory setStringValue:@""];
[txtOperation setStringValue:@""];
}
else if(val >= BTN_PLUS && val <= BTN_RESULT)
{
/* 연산이 입력되었을 경우에 현재 값이 있는지 확인 후 처리 합니다. */
if([[txtValue stringValue] length] > 0)
[self processCalcul:val];
}
}
/* 버튼이 클릭되었을 경우에, processInput에 알려 줍니다. */
- (IBAction) processCommand:(id)sender
{
/* 현재 선택(클릭)된 버튼의 tag값을 얻어 옵니다. */
int val = [[sender selectedCell] tag];
[self processInput:val];
}
@end
이제 모든 작업이 완료되었습니다. 빌드하고 실행시켜 계산기 프로그램을 테스트 해 봅니다.
아직 처리하지 않는 부분이 많이 있습니다. 이 부분과 몇 가지 기능들을 다음 튜토리얼을 통해 계속 수정/추가해 나가겠습니다. 이번 장부터는 소스코드를 압축하여 올립니다. 참고하실 분은 다운 받아 압축을 풀고, Xcode에서 확인하시고, 이 소스코드에는 주석이 되어 있지 않습니다.
'Xcode 2 > Cocoa 따라해보기' 카테고리의 다른 글
1.8 간단한 슈팅게임 (2) (2) | 2007.10.03 |
---|---|
1.8 간단한 슈팅게임 (1) (4) | 2007.08.14 |
1.7 업그레이드된 계산기 프로그램 (1) (0) | 2007.06.03 |
1.6 SimpleViewer 이미지 뷰어 (2) (0) | 2007.05.17 |
1.6 SimpleViewer 이미지 뷰어 (1) (2) | 2007.05.16 |