PDA

View Full Version : Cocoa Topics for Carbon Ex-patriots




GothicChess.Com
Jun 29, 2007, 09:29 PM
As a result of this thread, Carbon vs. Cocoa, a structered debate : http://forums.macrumors.com/showthread.php?t=317580

...I have decided to begin my Cocoa development phase sooner rather than later. My former initial objective was to take my OS 9 apps to Carbon to at least have them running native under OS X. I will continue what I have started for the sake of feeling some form of accomplishment, but all of my new projects will be with Cocoa.

Thanks to all who helped me make up my mind :) While I felt some of the discussion was needlessly overheated at times, it did address some key points, and for those who stayed on topic, my thanks.

I'd like to open up a new thread wherein the "Cocoa way" to do things that the Carbon-minded might find useful. I'll try to come up with some "common denominator" code snippets, not just items overly-specific to some of the 2,000,000 lines of code I have going back to the days of CodeWarrior and MPW.

I'll start things off in my next post, thank again to all of the Cocoa diehards out there.



iSee
Jun 29, 2007, 09:46 PM
LOL!!! :D I read a bunch of that thread (until it got ridiculous)...

Anyway, I'm a Carbon expat, too (although the process came much easier to me), so I'm interested to see what this leads to.

GothicChess.Com
Jun 29, 2007, 09:50 PM
One of the things I have done in C under carbon has been the writing of very large files for use with my chess, checkers, and Gothic Chess programs (see http://www.GothicChess.com if you want to see a cool version of chess with more pieces on the board.)

The files are basically millions or billions of positions with information such as "mate in 141" associated with each one.

A sample of how the data is written to disk...


void solve_3_checkers_versus_3_checkers(void)
{
unsigned char *g_db6_0K3C_0K3C = NULL;

FILE *file_pointer;
unsigned long k_how_many_positions = 7959904;
unsigned long i;

g_db6_0K3C_0K3C = (unsigned char *)malloc(k_how_many_positions);
if(g_db6_0K3C_0K3C)
{
/* initialize the values to highest 8-bit value */
for(i = 0; i < k_how_many_positions; i++)
g_db6_0K3C_0K3C[i] = 255;


/* some code to solve all of the positions goes here... */

file_pointer = fopen("db_06_(0K3C_0K3C)","wb");
fwrite(g_db6_0K3C_0K3C, k_how_many_positions, 1, file_pointer);
fclose(file_pointer);
free(g_db6_0K3C_0K3C);
}
}


Now, the vast majority of what you read and write is done after displaying the standard file dialog box. In the case above, this is completely circumvented because the "solving" of the data takes a while, and it just needs to be dumped from the RAM buffer to disk.

My question is: Does Cocoa require you to interact with the "Standard File" dialogs, or can you write directly to disk as in the above example?

How would one write the aforementioned using Cocoa?

kainjow
Jun 29, 2007, 10:42 PM
Well, if you're doing a pure Cocoa app, you'd have a lot of NSObjects and inside them NSStrings and NSDatas, with both have writeToFile:atomically: methods. Very easy :)

GothicChess.Com
Jun 30, 2007, 02:05 AM
Well, if you're doing a pure Cocoa app, you'd have a lot of NSObjects and inside them NSStrings and NSDatas, with both have writeToFile:atomically: methods. Very easy :)

That is encouraging :)

What is going to be very cool is when the databases being solved require gigantic chunks of RAM to solve quickly, such as the 3 kings + 2 checkers versus 3 kings + 2 checkers database, which has 946,853,107,200 (946 billion) positions!

I would still like to see how the code snippet in my previous post would look completely ported to Cocoa. I need to "see an example" to crib my way over to the Cocoa world :)

Fukui
Jun 30, 2007, 02:28 AM
One of the things I have done in C under carbon has been the writing of very large files for use with my chess, checkers, and Gothic Chess programs (see http://www.GothicChess.com if you want to see a cool version of chess with more pieces on the board.)

The files are basically millions or billions of positions with information such as "mate in 141" associated with each one.

A sample of how the data is written to disk...


Now, the vast majority of what you read and write is done after displaying the standard file dialog box. In the case above, this is completely circumvented because the "solving" of the data takes a while, and it just needs to be dumped from the RAM buffer to disk.

My question is: Does Cocoa require you to interact with the "Standard File" dialogs, or can you write directly to disk as in the above example?


You can do what ever you want. Cocoa is just an infrastructure, use pure C for your file writing if you want. As always, test, and if there are advantages to using NSData etc. then try it and test, see what your performance is... one thing about using a lot of C is though, unicode. Using the Cocoa API's you get internationalization for free..... again, it depends on what your saving.....

garethlewis2
Jun 30, 2007, 02:48 AM
Have you bought the books from the Big Nerd Ranch?

As iterated by another poster, you can do anything you want with Cocoa. You can't write the GUI code in C, but unless your code is so tightly coupled you can call functions directly in Objective-C. You might want to wait for Leopard before starting development. Besides GC which is run in a parallel thread, no NDA issues there. The [] convention for Objective-C is going to be added to with .

In other words

Fraction *fract = [[[Fraction] initWithNum: 1 over: 3] autorelease]

Could be written as

Fraction *fract = Fraction.initWithNum(1,3).autorelease;

Makes it easier for Java and C++ developers to get their heads around.

cblackburn
Jun 30, 2007, 03:37 AM
void solve_3_checkers_versus_3_checkers(void)
{
...
}



If I was coding that in Cocoa I would use the code you just pasted :). None of that code segment contains Carbon calls, it's all raw POSIX C. This will become 64 bit in leopard and be supported for years to come.

More than that this code is battle hardened and proven to be stable by you. Also Cocoa is a very nice framework to code in but no one can argue against the fact that it is always slower than the Raw C alternative.

To move your app from Carbon to Cocoa you need only change the Carbon GUI calls to Cocoa GUI calls, all the Raw C code you have just copy and paste.

Chris

lazydog
Jun 30, 2007, 03:49 AM
The [] convention for Objective-C is going to be added to with .

In other words

Fraction *fract = [[[Fraction] initWithNum: 1 over: 3] autorelease]

Could be written as

Fraction *fract = Fraction.initWithNum(1,3).autorelease;

Makes it easier for Java and C++ developers to get their heads around.

Fantastic! I was just thinking a couple of nights ago if it would be possible to convert the bracketed format to dot format.

I have one question though, in your example would the call not be

Fraction *fract = Fraction.initWithNumOver(1,3).autorelease;


Thanks for the post, I look forward to the Leopard release even more now.

b e n

GothicChess.Com
Jun 30, 2007, 04:44 AM
If I was coding that in Cocoa I would use the code you just pasted :). None of that code segment contains Carbon calls, it's all raw POSIX C. This will become 64 bit in leopard and be supported for years to come.

More than that this code is battle hardened and proven to be stable by you. Also Cocoa is a very nice framework to code in but no one can argue against the fact that it is always slower than the Raw C alternative.

To move your app from Carbon to Cocoa you need only change the Carbon GUI calls to Cocoa GUI calls, all the Raw C code you have just copy and paste.

Chris

I was kind of wishing along these lines :)

I didn't know if Cocoa would put a stop to the C file I/O such as fopen() and fwrite(), forcing some XML format enveloped inside calls to the Standard File dialog boxes.

I would say 90% of my code, possibly even more, is highly optimized C code, so it sounds like the jump to Cocoa might not be too bad at all.

garethlewis2
Jun 30, 2007, 05:14 AM
If your code isn't tightly coupled at all, then you should have no problems converting from Carbon calls to Cocoa.

You seem to have your head filled with horror stories stating that Cocoa forces you to open files using NSHugeCrapRubbishMethod that takes 8 hours to run. These are convenience methods designed to make it easier to code, they aren't slow, as they wrap around the raw IO calls from Posix.

Just please don't fall into the trap of believing that dynamic dispatch is massively slow compared to static method binding. If it was, Apple would never have coded OS X with Objective-C. They would have converted the entire framework of NextSTEP over to C++.

GothicChess.Com
Jun 30, 2007, 06:55 AM
You seem to have your head filled with horror stories stating that Cocoa forces you to open files using NSHugeCrapRubbishMethod that takes 8 hours to run.

It's up to 8 now? It was just 7.5 last week!

:)

kainjow
Jun 30, 2007, 12:30 PM
The [] convention for Objective-C is going to be added to with .

In other words

Fraction *fract = [[[Fraction] initWithNum: 1 over: 3] autorelease]

Could be written as

Fraction *fract = Fraction.initWithNum(1,3).autorelease;

Makes it easier for Java and C++ developers to get their heads around.

Hm, not sure if I can comment on this in more detail, but I think you are incorrect.

Fukui
Jun 30, 2007, 01:09 PM
Hm, not sure if I can comment on this in more detail, but I think you are incorrect.

Yea, thats under NDA, probably... I wouldn't put too much weight behind assertions about things that haven't been publicly stated by apple.

GothicChess.Com
Jul 1, 2007, 11:35 PM
I am wondering if there is an OpenSource example of an application that handles all of the standard events in Cocoa...

Menus, windows with drawers, the old "offscreenbitmaps" kind of color animation, tracking for the replacement to the old "keyDown" event, opening/saving of files, stuff like that.

I would like to stratify by #define some of the OS-dependent stuff. For example, I have a cool blackjack program that I can run under OS 9 on a 680X0 Mac, a Power Mac, and now under OS X as a Carbonized app, all by changing one #define. Technically speaking, I can even run it under OS 6.0.5 which was the last stable release before "System 7", but the code is not as clean as it should be.

I would eventually like to make a Cocoa app that can be run under any Macintosh, just for kicks :)

If anyone knows of some good OpenSource Cocoa links, feel free to post them here.

garethlewis2
Jul 2, 2007, 02:18 AM
No it's not under NDA.

It is part of the new GCC features for Objective-C 2.0. Whether Apple adopts them is not known, but they are part of gcc now.

HiRez
Jul 2, 2007, 02:23 AM
If you use Objective-C seriously for a week or so and still can't "get your head around" the bracketed format, then you probably never will (meaning, you're not a very adaptable programmer). I came from a Java background, it was weird for me for a few days, but that's it. Now I love it, and Cocoa's wordy method names and self-documenting, forced named message arguments. I've certainly come to see Objective-C code as more readable than Java, C, C++, Perl, PHP, and other languages (still love looking at Python code though). Having said that, I am looking forward to abbreviated enumeration/loop handling.

Nutter
Jul 2, 2007, 03:45 AM
Cocoa / Carbon with #define? Not bloody likely!

The philosophy of Cocoa is entirely different to Carbon. There's no one-to-one mapping of functionality from one to the other. While Objective-C is a superset of C, Cocoa itself takes full advantage of the dynamic object-oriented features of the language. That's what makes Cocoa such a successful and unique API. Trying to hack it onto your existing C implementation is a bit of a waste of time, and much more difficult than putting your C code in Objective-C wrapper classes that can be used properly with Cocoa.

I mean, really, in 2001 I could understand the appeal of supporting both OS 9 and OS X with one source. But supporting OS 6? Today, in 2007? For fun??! Weird.

GeeYouEye
Jul 2, 2007, 02:47 PM
Hm, not sure if I can comment on this in more detail, but I think you are incorrect.

You can, as it's all in the GCC repository, and he is incorrect. What he posted is only true for getters and setters, and only if an ivar is declared as a property.

As for the original question, I'd transform the code into a method on the application controller class:


/* In AppController.m */
-(void)solve_3_checkers_versus_3_checkers
{
unsigned char *g_db6_0K3C_0K3C = NULL;
NSString *fileName = @"db_06_(0K3C_0K3C)"
unsigned long k_how_many_positions = 7959904;
unsigned long i;

g_db6_0K3C_0K3C = (unsigned char *)malloc(k_how_many_positions);
if(NULL != g_db6_0K3C_0K3C)
{
/* initialize the values to highest 8-bit value */
for(i = 0; i < k_how_many_positions; i++)
g_db6_0K3C_0K3C[i] = 255;


/* some code to solve all of the positions goes here... */
NSData *fileData = [NSData dataWithBytes:g_db6_OK3C_0K3C];
[fileData writeToFile:fileName atomically:YES];
free(g_db6_0K3C_0K3C);
}
}
You'll notice I declared an NSData * midway through - I just leave C99 enabled. You can move the declaration to the top of the block if you have to use C89 for some reason.

Also, I'm a bit confused as to why you need to malloc instead of simply declaring g_db6_0K3C_0K3C as an array of k_how_many_positions unsigned chars.

Catfish_Man
Jul 2, 2007, 04:48 PM
Also, I'm a bit confused as to why you need to malloc instead of simply declaring g_db6_0K3C_0K3C as an array of k_how_many_positions unsigned chars.

Making sure it's not on the stack?

garethlewis2
Jul 3, 2007, 02:14 AM
Who said it was in the repository for GCC.

If you think Apple would put those features into the public domain before releasing Leopard you are smoking too much pot.

SC68Cal
Jul 3, 2007, 02:26 AM
Gothic,

How much of your code is similar to the snippets above? You might already be a step ahead of the game if most of your engine is POSIX C code. You might just be doing GUI work :)

MongoTheGeek
Jul 3, 2007, 07:27 AM
Who said it was in the repository for GCC.

If you think Apple would put those features into the public domain before releasing Leopard you are smoking too much pot.

A bunch of the iCal stuff is in the wild and actually more advanced than what is in the leopard beta. Then again thats in the nightly builds.

GeeYouEye
Jul 3, 2007, 10:52 AM
Who said it was in the repository for GCC.

If you think Apple would put those features into the public domain before releasing Leopard you are smoking too much pot.

The Objc-lang mailing list run by Apple disagrees. There have been dozens of discussion threads about what's in Objective-C 2.0, and Apple monitors (and occasionally posts) on that list. It's Cocoa in Leopard that's not allowed to be talked about, except for what's already known.

Making sure it's not on the stack?Well yeah, but why? It's not being returned, and if it's likely to overflow the remaining stack space and hit the heap, it'd overflow the remaining heap space and hit the stack if it's allocated there.

GothicChess.Com
Jul 4, 2007, 06:16 AM
Also, I'm a bit confused as to why you need to malloc instead of simply declaring g_db6_0K3C_0K3C as an array of k_how_many_positions unsigned chars.

Thanks for that code conversion... starting to get the feel for this newer stuff now.

The short answer to your question: During part of the computation, I can stuff 4 checkers positions into each byte. The positions have values of either UNKNOWN, WIN, LOSS, or DRAW. I use binary 11 for UNKNOWN, 10 for WIN, 01 for DRAW, and 00 for LOSS.

Using only 2-bits per position, I can line 4 of them up in one byte.

So say I need to know what is the value of position #105671.

I know it is in byte # (105671/4) = 26417. So g_db6_0K3C_0K3C[26417] is the byte with the result. Since (105671%4) = 3, I know the result is in bits (3 x 2) + 1 and (3 x 2) + 2 = 7 and 8.

With a bit pattern such as 11000000 representing the mask for bits 7 and 8 being set, I can say:

my_result = g_db6_0K3C_0K3C[26417] & 0xC0; where the result will be WIN, LOSS, DRAW, or UNKNOWN.

This may seem like a waste of time, until you try and solve the 132 billion positions comprising every 8-piece (and fewer) combination possible in the game of checkers.

During another phase of the computation, I filter out all of the draws, and only "operate" on the WINS and LOSS values. During that phase, I realloc() and need 1 byte per position, using all 8-bits to describe the distance to win (or lose.) But, since maybe 35% of the positions are draws, they drop out, saving RAM, and loop iteration time.

GothicChess.Com
Jul 4, 2007, 06:43 AM
Cocoa / Carbon with #define? Not bloody likely!

....

I mean, really, in 2001 I could understand the appeal of supporting both OS 9 and OS X with one source. But supporting OS 6? Today, in 2007? For fun??! Weird.

I still have MPW Pascal (and C) on my Mac SE/30. It is fun dumping my latest source code projects over to that platform and watching it compile for 2 hours! And the thing will actually run!

I have striven to totally divorce my Operating System dependant calls, such as drawing and event handling, from the rest of my programs, which are in highly portable C.

My chess program runs under every Macintosh ever made (except the latest Mac OS) and, with maybe 3 or 4 #define changes, I can get it to run under WindowsXP, Windows2000, or a Tru64 flavor of Unix.

It's really not THAT hard to do compared to the search engine stuff.

The beauty of it is: The drawing environment/Operating System can change ad infinitum, if I bracket the #defines properly, the thing should be able to run into the "forever future" without too much change.

I can see this will change now with all that NSString stuff...

kainjow
Jul 4, 2007, 12:38 PM
I don't think you'll have to change too much of your code, if any since it's already portable. It's just the UI that will need to be rewritten in Cocoa (if you want to go that route). And that should be easy to separate from the rest.

GeeYouEye
Jul 5, 2007, 01:05 PM
I still have MPW Pascal (and C) on my Mac SE/30. It is fun dumping my latest source code projects over to that platform and watching it compile for 2 hours! And the thing will actually run!

I have striven to totally divorce my Operating System dependant calls, such as drawing and event handling, from the rest of my programs, which are in highly portable C.

My chess program runs under every Macintosh ever made (except the latest Mac OS) and, with maybe 3 or 4 #define changes, I can get it to run under WindowsXP, Windows2000, or a Tru64 flavor of Unix.

It's really not THAT hard to do compared to the search engine stuff.

The beauty of it is: The drawing environment/Operating System can change ad infinitum, if I bracket the #defines properly, the thing should be able to run into the "forever future" without too much change.

I can see this will change now with all that NSString stuff...

NSString isn't a mandatory replacement for char *. If all your code is already portable, no reason to make anything but the UI in Cocoa. But to be honest, to an OO Programmer, saving during a solving routine sounds like a horrible layering violation. Even in straight C, I'd keep them in separate functions; you're already mallocing and freeing instead of declaring on the stack so you shouldn't have any trouble passing around a pointer and a length (though even that doesn't matter if you call save from solve, though I'd call both from an enclosing function).

GeeYouEye
Jul 5, 2007, 03:37 PM
Basically, if you want help going from Carbon to Cocoa, we're happy to help, but C != Carbon.

GothicChess.Com
Jul 6, 2007, 12:58 PM
Basically, if you want help going from Carbon to Cocoa, we're happy to help, but C != Carbon.

Thanks :)

Most of the engine is very portable, as you can see the "output" from the database generation run here:

http://www.onlyperfectcheckers.com/databases.txt

Everything is lean C code. If you scroll to the very bottom of that text file, you can see the ASCII diagram of the longest win involving 3 checkers vs. 3 checkers. It takes 161 moves for white to move and win (counting moves for both sides) but the position looks rather docile to the untrained eye:


***********************************************************************************
* 6-piece database, 0 white kings 3 white checkers vs. 0 red kings 3 red checkers *
***********************************************************************************

TOTAL POSITIONS: 7959904
TOTAL BYTES: 7959904

TOTAL WINS (white to move): 2700665
TOTAL DRAWS (white to move): 4931025
TOTAL LOSSES (white to move): 328214

Wins resolved as jumps: 2212771
Draws resolved as jumps: 274333
Losses resolved as jumps: 25891

Wins resolved from moving: 487894
Draws resolved from moving: 4656692
Losses resolved from moving: 302323

Wins with NO JUMPS for EITHER SIDE: 425177
Draws with NO JUMPS for EITHER SIDE: 4005208
Losses with NO JUMPS for EITHER SIDE: 130577

Draws resolved from unknowns: 0

Cumulative win length improvements: 19173
Cumulative loss length changes: 4915

Database resolved after 22 iterations
(including 1 jump pass and 1 pass to set unknown positions to draws.)

The longest win requires 161 ply to complete.

There is only one win in this database slice that is that long.
The longest white to move and win position: (white pieces start at top of board)

**************************************************************************************************** ***********
*----------*----------*----------*----------*----------*----------*----------*----------*----------*----------*
*----------*----------*----------*----------*----------*----------*----------*----------*----------*----------*
*----------*----------*----------*----------*----------*----------*----------*----------*----------*----------*
*----------*----------*----------*----------*----------*----------*----------*----------*----------*----------*
*----------*----------*----------*----------*----------*----------*----------*----------*----------*----------*
**************************************************************************************************** ***********
*----------*##########* *##########* *##########* *##########* *----------*
*----------*##########* *##########* *##########* *##########* *----------*
*----------*### 32 ###* -------- *### 31 ###* -------- *### 30 ###* -------- *### 29 ###* *----------*
*----------*##########* |wwwwww| *##########* |wwwwww| *##########* |wwwwww| *##########* *----------*
*----------*##########* -------- *##########* -------- *##########* -------- *##########* *----------*
**************************************************************************************************** ***********
*----------* *##########* *##########* *##########* *##########*----------*
*----------* *##########* *##########* *##########* *##########*----------*
*----------* *### 28 ###* *### 27 ###* *### 26 ###* *### 25 ###*----------*
*----------* *##########* *##########* *##########* *##########*----------*
*----------* *##########* *##########* *##########* *##########*----------*
**************************************************************************************************** ***********
*----------*##########* *##########* *##########* *##########* *----------*
*----------*##########* *##########* *##########* *##########* *----------*
*----------*### 24 ###* *### 23 ###* *### 22 ###* *### 21 ###* *----------*
*----------*##########* *##########* *##########* *##########* *----------*
*----------*##########* *##########* *##########* *##########* *----------*
**************************************************************************************************** ***********
*----------* *##########* *##########* *##########* *##########*----------*
*----------* *##########* *##########* *##########* *##########*----------*
*----------* *### 20 ###* -------- *### 19 ###* *### 18 ###* *### 17 ###*----------*
*----------* *##########* |rrrrrr| *##########* *##########* *##########*----------*
*----------* *##########* -------- *##########* *##########* *##########*----------*
**************************************************************************************************** ***********
*----------*##########* *##########* *##########* *##########* *----------*
*----------*##########* *##########* *##########* *##########* *----------*
*----------*### 16 ###* -------- *### 15 ###* *### 14 ###* -------- *### 13 ###* *----------*
*----------*##########* |rrrrrr| *##########* *##########* |rrrrrr| *##########* *----------*
*----------*##########* -------- *##########* *##########* -------- *##########* *----------*
**************************************************************************************************** ***********
*----------* *##########* *##########* *##########* *##########*----------*
*----------* *##########* *##########* *##########* *##########*----------*
*----------* *### 12 ###* *### 11 ###* *### 10 ###* *### 09 ###*----------*
*----------* *##########* *##########* *##########* *##########*----------*
*----------* *##########* *##########* *##########* *##########*----------*
**************************************************************************************************** ***********
*----------*##########* *##########* *##########* *##########* *----------*
*----------*##########* *##########* *##########* *##########* *----------*
*----------*### 08 ###* *### 07 ###* *### 06 ###* *### 05 ###* *----------*
*----------*##########* *##########* *##########* *##########* *----------*
*----------*##########* *##########* *##########* *##########* *----------*
**************************************************************************************************** ***********
*----------* *##########* *##########* *##########* *##########*----------*
*----------* *##########* *##########* *##########* *##########*----------*
*----------* *### 04 ###* *### 03 ###* *### 02 ###* *### 01 ###*----------*
*----------* *##########* *##########* *##########* *##########*----------*
*----------* *##########* *##########* *##########* *##########*----------*
**************************************************************************************************** ***********
*----------*----------*----------*----------*----------*----------*----------*----------*----------*----------*
*----------*----------*----------*----------*----------*----------*----------*----------*----------*----------*
*----------*----------*----------*----------*----------*----------*----------*----------*----------*----------*
*----------*----------*----------*----------*----------*----------*----------*----------*----------*----------*
*----------*----------*----------*----------*----------*----------*----------*----------*----------*----------*


I have the code in place to handle the 19 billion 7-piece endings, 111 billion 8-piece endings, just under 2 trillion of the 9-piece endings, and 8.5 trillion of the 10-piece endings.

You can imagine this will make the program unbeatable.

And you can see I have a lot of "coding time" invested in this, so making a Coca app out of it to insure survivability is a high priority for me.

GeeYouEye
Jul 6, 2007, 03:25 PM
A few months ago there was a series of articles on MacDevCenter.com on how to draw a checkers program in Cocoa. Just hook that up to your backend (though, again, I'd refactor it a bit) and you should be good to go.

cube
Jul 6, 2007, 03:49 PM
expatriates

GothicChess.Com
Jul 7, 2007, 06:11 AM
A few months ago there was a series of articles on MacDevCenter.com on how to draw a checkers program in Cocoa. Just hook that up to your backend (though, again, I'd refactor it a bit) and you should be good to go.

Cool, thanks for the tip, I will surely check it out!

GothicChess.Com
Jul 7, 2007, 06:20 AM
Laugh if you will, I was just running my old MacSE/30 version (System 7!) of the checkers program to test it out against the new OS X version (mostly for kicks.)

Then I realized I had the "takeback/replay moves" feature tied into the arrow keys on the old extended keyboard.

Now I realize the "keyDown" event has undergone a major re-thinking in both Carbon and Cocoa, and it is, in fact, quietly discouraged.

What I would like to do:

1. User hits the right arrow key, dispatch to the same menu command as "Replay Next move".

2. User hits the up arrow key, dispatch to the same menu command as "Replay All Moves".

3. User hits the left arrow key, dispatch to the same menu command as "Takeback Previous Move".

4. User hits the down arrow key, dispatch to the same menu command as "Takeback All Moves".

I would like to see how it is done in Carbon C, and Cocoa.

Think of all of the carpal-tunnel you are saving future end users of the program by sparing them constant access to the menus!

:)

Eraserhead
Jul 7, 2007, 06:45 AM
In Cocoa you should be able to use keyboard keys to control the menus but I can't figure out how you would use arrows...

GothicChess.Com
Jul 7, 2007, 06:51 AM
It used to be that you could case off of the keyDown event with ASCII constants for the 4 arrow keys, and do whatever based on the handling of it as an event type.

Eraserhead
Jul 7, 2007, 09:01 AM
It used to be that you could case off of the keyDown event with ASCII constants for the 4 arrow keys, and do whatever based on the handling of it as an event type.

If you can do it in C you can do it in Cocoa, by simply using the C code ;).

GothicChess.Com
Jul 7, 2007, 10:20 PM
If you can do it in C you can do it in Cocoa, by simply using the C code ;).

I understand that amigo, but... the "old way" is going away, and there is some "new way" to do it.

For example, at this post I raised that question:

http://forums.macrumors.com/showthread.php?t=317190

... which referenced this tech note...

http://developer.apple.com/qa/qa2005/qa1446.html

..wherein it states:

A modern Mac OS X application should not react to keyboard events but either to commands (when the Command key is down) or to high level Unicode text input, handling the kEventTextInputUnicodeForKeyEvent Carbon Event.

You should not care even if your application is older and still processes keyboard events the old-fashioned way handling the keyDown event.

...which leads to me ask:

"OK, how do you do this now?"

:)

kainjow
Jul 8, 2007, 11:07 AM
What I would like to do:

1. User hits the right arrow key, dispatch to the same menu command as "Replay Next move".

[...]


So you have a menu item, and you want an arrow key to be the key equivalent for that menu item? Check out this (http://www.cocoabuilder.com/archive/message/cocoa/2004/3/8/101061) post from the cocoa-dev mailing list. That website (searching the archives) is also very useful for finding out how to do almost anything in Cocoa.

Also, for general arrow key events in an NSView, read here (http://www.cocoabuilder.com/archive/message/cocoa/2003/3/19/87151).

GothicChess.Com
Jul 9, 2007, 02:59 PM
So you have a menu item, and you want an arrow key to be the key equivalent for that menu item? Check out this (http://www.cocoabuilder.com/archive/message/cocoa/2004/3/8/101061) post from the cocoa-dev mailing list. That website (searching the archives) is also very useful for finding out how to do almost anything in Cocoa.

Also, for general arrow key events in an NSView, read here (http://www.cocoabuilder.com/archive/message/cocoa/2003/3/19/87151).

Hi,

Thanks for the links. There is 1 small problem with the solution presented:


(void)keyDown:(NSEvent *)theEvent
{
NSString *characters = [theEvent characters];
int key = [characters characterAtIndex: 0];

if (key == NSUpArrowFunctionKey) {
; // do your up arrow code
} else if (key == NSDownArrowFunctionKey) {
; // do your down arrow code
} else if (key == NSLeftArrowFunctionKey) {
; // do your left arrow code
} else if (key == NSRightArrowFunctionKey) {
; // do your right arrow code
}


In the Tech Note I furnished in the prior post, we have been advised to stay away from keyDown so intercepting it most likely will not be supported into the "forever future."

Additionally, I am looking for a Carbon example for now, one that I can port to Cocoa with just the "window dressings" changed.

kainjow
Jul 9, 2007, 03:03 PM
In the Tech Note I furnished in the prior post, we have been advised to stay away from keyDown so intercepting it most likely will not be supported into the "forever future."

That technote is for Carbon. The keyDown: method is from NSResponder, which is 100% supported.

GothicChess.Com
Jul 11, 2007, 02:48 AM
That technote is for Carbon. The keyDown: method is from NSResponder, which is 100% supported.

Aha! Light bulb moment, thanks :)