Making NSBrowser usable when it's updating

195 Views Asked by At

I have an NSBrowser which displays 2 columns of data that is calculated on several other threads while my app is running. The problem I'm trying to solve is to allow the user to interact with the browser while the data is still coming in. Right now, when a background thread indicates there are new rows to be displayed, I call -[NSBrowser reloadColumn:0]. This works when the user is simply looking at data in column 0. However, if they attempt to select an item in column 0, it will immediately become deselected as soon as the app calls reloadColumn:0. The data often comes in as hundreds of rows per second.

As a workaround, I tried getting the current selection before calling reloadColumn:0 and then resetting it immediately afterwards. This keeps the selection as desired, but if the user scrolls the selection off the view, as soon as the column is reloaded, the scroll position pops back to including the selected row. Trying to use the selectionIndexPath property has the same effect.

So it appears that I have to choose between:

  1. The user's selection will disappear every few seconds
  2. The user won't be allowed to scroll the selection off the screen

Neither of these are very useable. I have also tried calling -[NSBrowser reloadDataForRowIndexes:inColumn: to only "reload" (or actually load) the new rows, but this does not load rows which were not already loaded, apparently. Basically, after loading the first row, no further rows show up.

I also tried calling -loadedCellAtRow:Column: on every newly created row, and it also does not cause anything that wasn't previously loaded to load.

Is there a way to get this to work that won't annoy the user?

For what it's worth, I've implemented the following NSBrowserDelegate methods in my app:

- (BOOL)browser:(NSBrowser *)browser isColumnValid:(NSInteger)column
- (NSString*)browser:(NSBrowser *)sender titleOfColumn:(NSInteger)column
- (void)browser:(NSBrowser *)browser willDisplayCell:(nonnull id)cell atRow:(NSInteger)row column:(NSInteger)column
- (NSInteger)browser:(NSBrowser *)sender numberOfRowsInColumn:(NSInteger)column
- (NSInteger)browser:(NSBrowser *)browser numberOfChildrenOfItem:(id)item;
- (id)browser:(NSBrowser *)browser child:(NSInteger)index ofItem:(id)item;
- (id)browser:(NSBrowser *)browser objectValueForItem:(id)item;
- (id)rootItemForBrowser:(NSBrowser *)browser;
- (BOOL)browser:(NSBrowser *)browser isLeafItem:(id)item

If it would make sense to implement other delegate methods to clear this up, I'd be interested in knowing that.

0

There are 0 best solutions below