NSTableView: Displaying An Expanded Row (Resizing on the Fly) - objective-c

OK. I looked through the suggestions (which often answer my questions before I ask). I haven't found what I need.
I know that I'm doing something wrong. I do this all the time in iOS (UIKit), but tables in NS (Mac) are pretty darn different from UIKit.
I have a view-based NSTableView. Each row has exactly 1 column. This column has a view with a header (21 points high), and an expanded view (the row is 420 points high). There is a disclosure triangle on the left of the header that toggles these two modes.
The controller is also the table datasource and delegate. I have the row height callback returning the correct values for the view.
The header displays fine. I set the row heights to 21, and only the headers are shown. This clips the main view.
When a disclosure triangle is toggled, a row expands its height to reveal the entire view:
Simple enough, eh?
The problem is that B is not displayed. I just get a blank (However, A is correctly displayed). The items are there, just not being displayed. The table row is the correct height (this can be verified by using alternating row colors).
I've tried setting setNeedsLayout/Draw on the views.
Any clues on what I may be doing wrong?
I'm willing to bet that I'm doing something boneheaded, and I'll keep looking into this.

Using noteHeighOfRowsWithIndexesChanged:? It's an NSTableView function, not a delegate function.
In the documentation for the delegate function tableView:heightOfRow it declares:
Although table views may cache the returned values, you should ensure that this method is efficient. When you change a row's height you must invalidate the existing row height by calling noteHeightOfRowsWithIndexesChanged:. NSTableView automatically invalidates its entire row height cache when reloadData and noteNumberOfRowsChanged are called.
As it mentions, NSTableView's reloadData is often the lazy way to fix your sort of issue as well.
Your table controller shouldn't need the setsNeeds[whatever] methods you tried.
Also, speaking of disclosure triangles and such, on OSX there is a NSTableView subclass called NSOutlineView that handles item expansion if you mangle your data into a poorly documented tree format. I actually wouldn't recommend it if your data's not a natural tree, but you should be aware of it, even if its API sucks. Oh, and the expansion when clicking the disclosure triangle is animated.

Related

NSCollectionView cell order changes on view change

I have a macOS application that contains a tab bar design (ie: Tweetbot). There are 4 tabs that are linked to 4 different view controllers. The initial view controller (view one) contains a NSCollectionView which displays 3 cells horizontally.
This all works fine, however when I switch to another view controller and then come back to the initial view controller, the order of the collection view changes for no reason. I am not making ANY changes to the data source (which is a NSMutableArray) and I am not adding/deleting any cells, nor am I calling reloadData. I don't understand why the order of the collection view cells keep changing.
I have done some testing and can confirm that the order of the data in my data source, does NOT change at all. So it makes no sense for the collection view, to just change the order of the cells.
Another weird issue I have noticed, is that if I limit the collection view to 2 cells, this issue does not occur. This makes me wonder whether or not, the issue is down to some sort of NSCollectionView caching method that runs in the background? Perhaps when the collection view recycles a cell, it uses the incorrect data??
I have tried lots of different solutions, nothing seems to work. Does anyone have any ideas of what I can test/try out, in order to find out what's wrong?
Alternative idea
I could use NSTableView instead, because it supports multiple columns (unlike UITableView). So I could just make an NSTableView with 3 columns. Would this approach be any worse performance wise, than a NSCollectionView (especially if I wanted to add lots of cells?).
I couldn't find out what was wrong with the collection view. So I ended up using a NSTableView with multiple columns (instead of collection view rows). I set each column to have one row (index 0), which makes the table view look exactly like the collection view I was working with.
Performance wise the table view seems to be a lot better too. Even with hundreds of columns, it's still nice and smooth when scrolling/interacting.

NSTableView won't layout / resize columns until NSWindow manually resized

I've an NSTableView with several NSTableColumn objects that appear to have all the correct auto-resizing flags set. However, every time I rebuild the table's contents, the columns all return to a narrow size -- unless I click and manually resize the window.
The NSTableView is inside:
NSWindow
NSView
NSScrollView
NSTableView
(other NSTableView objects: NSTableColumn, NSTextFieldCell, NSScroller (x 2)
Column resizing mask is always:
NSTableColumnAutoresizingMask
NSTableColumnUserResizingMask
The table is created always set with:
[theNSTableView setColumnAutoresizingStyle:NSTableViewUniformColumnAutoresizingStyle];
After reloading the table with data,
[theNSTableView reloadData];
[theNSTableView tile];
...and even:
[theNSTableView setNeedsDisplay:YES];
All views are set to "autoresizesSubviews".
Neither the NSView nor the NSScrollView have any referencing outlets -- could that be the problem?
After discussing this issue at length with Apple Developer Technical Support, they believe there may be an issue with Carbon-Cocoa integration.
However, they also point out that I really should not set NSTableViewUniformColumnAutoresizingStyle and I should be calculating the widths of all my columns in my own code, and then either telling the column to remember its width, or storing the width and making sure to set the same width on each column AFTER I programmatically create the column.
While I can accept this, I had been at least hoping I could programmatically invoke the same method that is called when a user double-clicks on a column divider and the column resizes itself to fit all of its cell text contents. However, DTS tells me those functions are not available.
I have come across other solutions to this issue here on SO and I will see if they can be adapted to create an optimal solution.

iOS 6.0 UICollectionView - same cells being added multiple times

While using collection view, in cellforItemAtIndexPath, new cell instance is being added multiple times (on top of another) at same location/frame, even though correct reuseidentifier is being passed to "dequeueReusableCellWithReuseIdentifier:forIndexPath:"
The cell mentioned above is a subclass of UICollectionViewCell and contains UITextField with proper frame. When scrolling and textfield is first responder, the above said problem is occurring.
Please let me know of any pointers to address the issue.
This could be a bug in UICollectionView related to one I've already filed with decoration views. As long as your cells are opaque, it should not affect your interface
It's possible (though, imo, not very likely) that this is correct behaviour for UICollectionView and it uses those extra cells for interface orientation. At any rate, the problem seems much less pronounced that the one with decoration views, which would add dozens of copies of the decoration view. As long as it's not affecting your app, I'd say live with it.

NSOutlineView elements remain hopelessly undraggable

I have a program with a NSOutlineView (that supports single selection only) from which I'd like to be able to drag elements. These elements should either be received as text or files: for instance, dropping the item on a TextEdit window should put text, but dropping the item on the Finder should create a file. I don't want anything to be dropped over my outline view, even it it comes from itself. This seems easy enough, but for some reason, I can't get it to work.
I checked the NSOutlineView drag and drop example from Apple, and I came to implement the following methods (plus a few definitely unrelated ones):
-(BOOL)outlineView:shouldSelectItem: // I don't expect to drag unselectable items
-(NSArray*)outlineView:namesOfPromisedFilesDroppedAtDestination:forDraggedItems:
-(BOOL)outlineView:writeItems:toPasteboard:
However, when I try to drag an item from my outline view, nothing happens. Instead, it just changes the selection following the cursor.
I've put breakpoints in the two last methods, and they never get called, so their implementation is not the immediate issue.
I must be missing something really obvious here.
Also, this is not (yet) a problem, but how am I supposed to provide contents to my promised files?
I was being stupid and I implemented the methods in the delegate instead of the data source (the two are distinct in my app). Problem solved!
Are you using a custom table view cell? The result of NSCell's hitTestForEvent:inRect:ofView: determines whether a dragging operation can be initiated. It also determines whether your outlineView:writeItems:toPasteboard: should be called.
This method should return NSCellHitContentArea to initiate a drag, or NSCellHitTrackableArea to extend or change the selection.
A standard text cell returns NSCellHitContentArea when you click on the actual text of the cell, and NSCellHitTrackableArea when you click outside of the text. This produces the drag behavior you see in Finder's table view.
You can override this method and always return NSCellHitContentArea if you want all areas of the cell to initiate a drag operation.
See Hit Testing for more information.

Mouseover in NSTableView

I'm having trouble creating a mouseover function with an NSTableView. The idea is that (if the feature is selected in prefs) placing the mouse pointer above a particular row in an NSTabelView will display a small popup window with additional information regarding the entry in that particular row. The effect should not be immediate (as e.g. highliting a button when rolling over it), but come with a delay of a few seconds.
So far, I have implemented this functionality using the tooltip delegate method, but this does not allow for customization of the window and does not work well (layout wise) if more than 1-3 rows of info need to be displayed.
In Hillegass' book it is suggested that one uses the mouseEntered/mouseExited methods for rollovers, but as far as I can tell this works with pre-defined areas of a window and not rows in a table view.
Does anyone have any suggestions?
Gregor Tomasevic,
Sweden
You're on the right track with -mouseEntered: and -mouseExited:.
Look into NSView's -addTrackingRect:owner:userData:assumeInside: and -removeTrackingRect: methods. You can either set up your tableView to create trackingRects for every row that's in there whenever the contents of the tableView change, or alternatively, set up/update one tracking area on the entire tableView whenever -tile or another layout related method is called.