Programmatic NSTableView selection changes
Programmatic NSTableView selection changes
- Subject: Programmatic NSTableView selection changes
- From: "Brent Burton" <email@hidden>
- Date: Wed, 19 Nov 2008 09:14:02 -0600
Hi,
I think I have this figured out, but I wanted to bounce it off the
list to see if there's a better way.
I wrote a small app that reads in a text file containing a chat log,
which contains lines in the format "Speaker: something they said",
like a script. The application allows you to select the speech
synthesizer voice for each speaker, adjust the speaking rates of each,
and speak the text. The GUI displays the spoken lines in a NSTableView
backed with an array controller.
To speak, the app starts at whichever row is selected, speaks the
text, then selects the next row, etc, until the end. The problem I
first encountered with early code was that programmatically changing
the selected objects doesn't take effect until the next runloop
iteration, so what the code thought was the current line was
one-behind what was displayed in the tableview. This means the code
must wait for tableViewSelectionDidChange: to get the next line. The
application controller is a delegate to both the speech synthesizer
and the table view, and implements the
speechSynthesizer:didFinishSpeaking: and tableViewSelectionDidChange:
methods.
Code flow below is:
1. User presses button, which invokes startSpeaking:.
2. startSpeaking: ensures a line is selected, and calls speakNextLine
3. speakNextLine gets the currently selected object, configures the
synthesizer, and begins speaking it.
4. When the synthesizer completes,
speechSynthesizer:didFinishSpeaking: selects the next row if
available, else stops.
5. After the selected row change takes effect,
tableViewSelectionDidChange: calls speakNextLine (repeats to step 3).
After about three different strategies, the above flow works as I
wanted. My only question is, is this The Cocoa Way to do it, or is
there a better way? The obstacle was not speaking the lines displayed
in the tableview, but automatically-updating the highlighted row to
show which is currently being spoken.
thanks,
-Brent
Relevant code:
// spokenLinesAC is the arraycontroller
- (IBAction)startSpeaking:(id)sender
{
if ([[spokenLinesAC selectedObjects] count] > 0)
{
shouldSpeak = YES;
...
[self speakNextLine];
}
}
- (void)speakNextLine
{
NSArray *selected = [spokenLinesAC selectedObjects];
SpokenLine *sline = [selected objectAtIndex:0];
// set the voice, rate, begin speaking
...
}
// ---- NSSpeechSynthesizer delegate methods ----
- (void)speechSynthesizer:(NSSpeechSynthesizer *)sender
didFinishSpeaking:(BOOL)success
{
if (shouldSpeak)
{
// Check for last object in arraycontroller; disable speaking
if no more to select.
if ( (shouldSpeak = [spokenLinesAC canSelectNext]) )
[spokenLinesAC selectNext:self];
}
...
}
// ---- TableView delegate methods ----
- (void)tableViewSelectionDidChange:(NSNotification *)aNotification
{
if (shouldSpeak)
[self speakNextLine];
}
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden