Parag Bafna
Parag Bafna

Reputation: 22930

How to change selection of NSMatrix in IBAction?

I have NSRadioModeMatrix with 3 cells. - (IBAction) EnableProxy:(id)inSender is connected to NSRadioModeMatrix

- (IBAction) EnableProxy:(id)sender
{   

    if ([[sender selectedCell] tag]==2)
    { 

/*(gdb) p (int)[[inSender selectedCell] tag]
$1 = 2*/
        if (condition) {
             // select cell with tag 0
            [sender selectCellAtRow:0 column:0]; // This is not working
        }
        /*(gdb) p (int)[[inSender selectedCell] tag]
$2 = 1*/
    }
}// selection is not visible

When condition is true. selection is going back to tag 2(old selected cell).Sample project.

Upvotes: 1

Views: 2052

Answers (2)

Abdul Naveed
Abdul Naveed

Reputation: 587

With reference to the above answer provided by NSGod, This can be also achieved using GCD rather giving the unnecessary delay with 0.0

ViewController * __weak weakRef = self;
        dispatch_async(dispatch_get_main_queue(), ^{
            [weakRef selectFirstMatrixRow];
        });

Upvotes: 0

NSGod
NSGod

Reputation: 22958

To be honest, this is the intended behavior, and for good reason.

enter image description here

Given the above UI, if a user clicks on C, they expect C to become selected. If instead, a user clicks on C and A becomes selected, you have a confused (and potentially frustrated) user. Indeed, implementing this type of behavior violates the OS X Human Interface Guidelines for Radio Buttons.

That said, I'll move on to how you can implement the behavior you want. Basically, the reason why when you select C, the immediate call to select A doesn't seem to succeed is that, technically speaking, C is still in the process of being selected. In other words, a simplified timeline of the events would look like the following:

  1. begin click on matrix
  2. EnableProxy: method called
  3. matrix immediately told to select A
  4. finished click on matrix and C is finally completely selected

In order to achieve the results you want, instead of immediately telling the matrix to select A, you'll need to "queue" the request up like the following code does:

- (IBAction) EnableProxy:(id)inSender {
    if ([[inSender selectedCell] tag] == 2) {
//        [mProxyEnable selectCellAtRow:0 column:0];
        [self performSelector:@selector(selectFirstMatrixRow) withObject:nil
                                                              afterDelay:0.0];
    }
}

- (void)selectFirstMatrixRow {
    NSLog(@"[%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
    [mProxyEnable selectCellAtRow:0 column:0];
}

By using [self performSelector:withObject:afterDelay:], you basically say "call this method as soon as possible". Doing so lets C be fully selected before that method is called, which allows the results you want. In other words, the timeline of events would look like this:

  1. begin click on matrix
  2. EnableProxy: method called
  3. finished click on matrix and C is finally completely selected
  4. --------- control returns to normal event loop ---------
  5. selectFirstMatrixRow method called
  6. matrix selects A

Upvotes: 3

Related Questions