Search code examples
cocoadelegatesclicknstableviewnsevent

Cocoa - How to distinguish between a click and scroll(continuous press of UP/DOWN key) inside a NSTableView


I want to fire a query when a particular record gets selected in an NSTableView, not when the user just scrolls down or scrolls up by continuously pressing UP/DOWN button to reach to a record.

My current implementation is

if ([notification object] == myTableView)
    {
        if ([myTableView selectedRow] >= 0) {
            myCont = [[MyController alloc] init];
            if([[detailsView subviews]count]>0)
                [detailsView removeAllSubviews];
            NSRect frameRect = [[scDetailsViewController view] frame];
            frameRect.size.height = [detailsView frame].size.height;
            frameRect.size.width = [detailsView frame].size.width;
            [[myCont view] setFrame:frameRect];
            [detailsView addSubview:[myCont view]];
//Firing the Query
            [myCont populateDetails :[[self myList] entityAt:[myTableView selectedRow]]];
        }
}

But in this way the query gets fired even if a long UP/DOWN press is done which is not intended.

Is there any way to distinguish between a click and scroll(continuous press of UP/DOWN key) inside an NSTableView just like the Mail application.


Solution

  • Just wrote the below piece of code in the tableViewSelectionDidChange method and that almost works perfectly.

    - (void)tableViewSelectionDidChange:(NSNotification *)notification
    {
        if ([notification object] == myTableView)
        {
            NSTimeInterval delayInterval = 0.0;
            NSEvent *event = [NSApp currentEvent];
            if(event != nil && [event type] == NSKeyDown && [event isARepeat])
            {
                NSLog(@"Long press of UP and DOWn arrow key.");
                delayInterval = [NSEvent keyRepeatInterval] + 0.01;
            }
            [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(myMethod) object:nil];
            [self performSelector:@selector(myMethod) withObject:nil afterDelay:delayInterval];
        }
        else
        {
            if ([[detailsView subviews] count]>0)
            {
                [detailsView removeAllSubviews];
            }
        }
    }
    

    Also written the code to fire the query in another method myMethod which is being called above in performSelector.

    -(void) myMethod
    {
        if ([scenarioTableView selectedRow] >= 0) {
            NSLog(@"Normal selection on table view row.");
            scDetailsViewController = [[ScenarioDetailsViewController alloc] init];
            if([[detailsView subviews]count]>0)
                [detailsView removeAllSubviews];
            NSRect frameRect = [[scDetailsViewController view] frame];
            frameRect.size.height = [detailsView frame].size.height;
            frameRect.size.width = [detailsView frame].size.width;
            [[scDetailsViewController view] setFrame:frameRect];
            [detailsView addSubview:[scDetailsViewController view]];
            [scDetailsViewController populateScenarioDetails :[[self scenarioDetailsList] entityAt:[scenarioTableView selectedRow]]];
        }
        else {
            if ([[detailsView subviews] count]>0)
            {
                [detailsView removeAllSubviews];
            }
        }
    }