Extracting index values from table view multiple row selection

Hi Guys, I have a single column table view set up which allows for multiple row selections; then:


on tableView_(sender)
      set whichRows to sender's selectedRowIndexes
      log whichRows's |class|() -->NSIndexSet
      log whichRows --<NSIndexSet: 0x200618dc0>[number of indexes: 3 (in 3 ranges), indexes: (1 3 5)]  --ie. I had selected rows 1, 3 and 5
end tableView_

From the console log I see that selectedRowIndexes has returned [number of indexes: 3 (in 3 ranges), indexes: (1 3 5)]
I want to extract “1”, “3”, and “5” - or whatever row numbers are returned.
However, for the life of me, I cannot figure out the correct approach…

Looking at the AppDevDocs, for NSIndexSet, the class of selectedRowIndexes and also “Collections Programming Topics”, I see under NSIndexPath Class reference, the instance method:
"firstIndex
Returns either the first index in the index set or the not-found indicator.

  • (NSUInteger)firstIndex
    Return Value
    First index in the index set or NSNotFound when the index set is empty."

However, whatever incantantion I have tried fails eg:

on tableView_(sender)
      set whichRows to sender's selectedRowIndexes
      log whichRows's |class|() -->NSIndexSet
      log whichRows --<NSIndexSet: 0x200618dc0>[number of indexes: 3 (in 3 ranges), indexes: (1 3 5)]  --ie. I had selected rows 1, 3 and 5

set thevalue to current application's NSUInteger's whichRows's firstIndex
      log thevalue
(*2012-03-18 22:57:46.628 NewYields[543:903] *** -[NewYieldsAppDelegate tableView:]: Can't get firstIndex of whichRows of NSUInteger. (error -1728)  *)
end tableView_

I have tried pretty much every logical variation I could think of from changing the class NSUInteger’s to NSIndexSet’s…(that failed with [<NSIndexSet 0x7fff7124a708> valueForUndefinedKey:]: this class is not key value coding-compliant for the key whichRows… which kind of confuses me in a way.

I feel that I am getting back an array object, fair enough, but it seems a special kind of array…? if I select 4 rows, 3 of them contiguous, i get:
2012-03-18 23:30:33.097 NewYields[603:903] <NSIndexSet: 0x2003f9420>[number of indexes: 4 (in 2 ranges), indexes: (2 4-6)]
ie. I chose rows 2, 4, 5, 6 …getting 4-6 I guess will also ultimately require some further manipulation

Can anybody please offer some help or thoughts on this?

Answering the first part of my question here:
I got this to work:

  
on tableView_(sender)
      set whichRows to sender's selectedRowIndexes
      log whichRows's |class|() -->NSIndexSet
     -- log whichRows --2012-03-19 00:43:03.315 NewYields[1780:903] <NSIndexSet: 0x20066b6c0>[number of indexes: 3 (in 3 ranges), indexes: (3 5 7)] --ie. I had selected rows 3, 5 and 7

      set thevalues to whichRows's firstIndex() as  real
      log thevalues

2012-03-19 00:43:03.316 NewYields[1780:903] 3

  end

…I am sure this was one of the very first things I tried and repeated, probably with some small syntax error I guess…anyway, of course if I now use the lastIndex() method I get the value of the last row selected ie. 7

However, I am now wearily pondering as to how to iterate through this kind of array to extract all of its values, not just the first and last…This was so much more straightforward in AS… ; )

You never mentioned why you need the row numbers of your selected rows – depending on what you want to do with those numbers, you might be able to use the index set directly. Unfortunately, the NSIndexSet methods that iterate through the set use blocks which can’t be used in ASOC.

However in ASOC, it can be done with following method which will iterate through the set to give you an NSArray of the index numbers. I’m not sure how you were calling your method, I call mine from a button in this example:

on buttonClick_(sender)
        set indexArray to current application's NSMutableArray's array()
        set indxs to theTable's selectedRowIndexes() -- theTable is the IBOutlet for the NSTableView
        set currentIndex to indxs's firstIndex()
        repeat while currentIndex does not equal current application's NSNotFound
            indexArray's addObject_(currentIndex)
            set currentIndex to indxs's indexGreaterThanIndex_(currentIndex)
        end repeat
         log indexArray   
    end

Ric

Thanks for the suggestion Ric,

For this purpose I have a very basic set up: a single window with a single-column scroll view, enabled for multiple selections and a push-button; an Array Controller has also been added.
The table column’s Value is bound to the Array Controller, with a Controller Key of arrangedObjects.
The Array Controller’s content array is bound to the appDelegate with MKP of theData.
The push-button’s action is connected to the appDelegate’s Received Actions’ buttonClick.
I also note that the appDelegate’s Outlet theTable - declared as a property with missing value in the delegate’s script- is connected to Table View.

The goal is to allow a selection of one or more rows and have this returned to the script for conversion to integers or a list of integers. These values will then -eventually- be used to extract the contents of the filenames selected and output these to another (contiguous) table -not there yet… ; )

The table builds fine and populates fine, but when I hit the push-button I get an infinity loop with the first line of the console as follows:
2012-03-19 22:59:52.217 TableRows[4335:903] *** -[NSIndexSet indexGreaterThanIndex:]: unable to set argument 2 because the AppleScript value <NSAppleEventDescriptor: 9.22337e+18> could not be coerced to type Q.

To stop the loop I need to ForceQuit the app. (So warning !!)

The actual ASOC script is as follows:

script TableRowsAppDelegate
	property parent : class "NSObject"
    property theData:{}
    property theTable: missing value  --IBOutlet, 
    ------------------------------------
    property initialList:{"Choose from List","BritishList", "EuropeanList", "AsianList", "LatAmList", "RussianList", "AfricanList"} 
	
	on applicationWillFinishLaunching_(aNotification)
		-- Insert code here to initialize your application before any files are opened 
        
        set my initialList to current application's NSArray's arrayWithArray_(initialList)
        set my theData to initialList
        
	end applicationWillFinishLaunching_
    
    on buttonClick_(sender)
        set indexArray to current application's NSMutableArray's array()
        set indxs to theTable's selectedRowIndexes() -- theTable is the IBOutlet for the NSTableView
        set currentIndex to indxs's firstIndex()
        repeat while currentIndex does not equal current application's NSNotFound
            indexArray's addObject_(currentIndex)
            set currentIndex to indxs's indexGreaterThanIndex_(currentIndex)
        end repeat
        log indexArray   
    end
    
    on applicationShouldTerminate_(sender)
		-- Insert code here to do any housekeeping before your application quits 
		return current application's NSTerminateNow
	end applicationShouldTerminate_
	
end script

Thanks for any suggestions.
Tim

Tim,

I can’t duplicate your error. I cut and pasted your code into a new project, hooked everything up like you posted, and everything worked fine. Try logging currentIndex right before the “end repeat” line and see what you get. This may have something to do with the way the max number is handled in different systems (which is apparently the way NSNotFound is interpreted). The other thing you could try is is changing your while condition to something like “currentIndex < 1000” or some other number you know will be bigger than the number of rows in your table.

In any case, I’m still not sure you even need to deal with indexes – it’s not clear to me whether you’re using the actual data in the table (I don’t know if this is just a simplified example, since your values don’t look like file names), or you’re somehow extracting that from these strings in your list. If you are using the actual data in the table, then you can just create an outlet for your array controller and use its selectedObjects() method to give you an array of the things that are selected (and even easier, you can bind the content array of a second array controller to the first array controller’s selectedObjects, and then bind the column of that second table to the 2nd array controller’s arrangedObjects – this way you don’t need any code at all).

Ric

Many thanks I will check my values and reflect on your other points. In any case, I will be back with some feedback, results and thoughts.
Cheers.

Quick feedback is that in my machine the loop just runs off…the current value logged is any integer from 0 to 6 so the problem was with current application’s NSNotFound - at least at my end. I got around it by coercing the data array to a list, counting the items and setting that sum+1 to the max value in repeat loop, as you suggested. This now works fine and I get a list of values back.

Just to give you a sense of what I am doing, the BritishList if selected will return a list of say 10 sub-items, which are stored as two lists, one of titles, the other one of codenumbers, to look up the code numbers I would need to know their positions within their respective list. I have thought about converting these to plists or dictionaries…but there are close on a couple of thousand, and perhaps I will do that at some point later…for the time being it works fine and I am happy with the speed…I want to keep the interface as light, flexible in choice selection combinations and responsive as is possible for me to do…and actually finish it!.

Your suggestion to return the actual values via bindings sounds pretty appealing in this sense, and will certainly be an incentive to think about converting the data held as lists within a script object, as described, to something more flexible…of course, it would require thinking a program to do the conversion… ; ))

Many thanks…much appreciated.