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

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.

Related

Update view constraints in NSPopover OSX Objective-C

I am on Xcode 8.2, Objective C, Mac OSX, not iOS.
I have a view shown in a popover like this:
Once i select an option in the second NSPopupButton, the blue text gets replaced with another LONGER text (5 lines instead of 3) - Unfortunately the view doesn't grow to reflect the changes!
Only if i close the NSPopover and reopen it, the view is correct:
The view is completely built with autolayout and constraints. There's NO constraint limiting HEIGHT or WIDTH for any subview, just setting distances to superview. So my quesiton is, how can i update the view after a selection in the NSPopupButton. I already tried (in the viewController)
[self.view setNeedsLayout:YES];
But it seems not to work. I checked these posts but they did not help me with my issue:
Resize current view using NSLayoutConstraints
Edit:
The new text (on NSPopupButton selection) is set like this:
[self.descriptionTextField setStringValue:self.currentSequenceItem.descriptionText];
I found the solution and i'd like to share it.
Once you've set all your constraints make sure to call
[yourTextField setPreferredMaxLayoutWidth:100.0f]; // Whatever you need
Otherwise the textField will tend to scale horizontally making all your text a one liner.
If that property is set, it'll scale vertically and will update all constraints as excpected.

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

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.

Expansion for a view-based NSTableView

I have a view-based NSTableView for which some cells have enough content that it doesn't fit. I would like to be able to have the cell automatically expand when a user hovers their cursor over the cell.
In searching for this, it seems that this is the default behavior for a cell-based NSTableView. There are even methods like shouldShowCellExpansionForTableColumn, which the doc says is for cell-based table views only. Somewhere else in the doc implies that this expansion behavior is even on by default for cell-based table views?
- (BOOL)tableView:(NSTableView *)tableView shouldShowCellExpansionForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
I get the impression that I'm missing something obvious.
Goal:
Be able to put multiple rows of NSTextField objects in a view-based cell (more than there is pace to handle)
If the content overflows, put a visual indicator into the cell
When the user does a tool-tip style hover on the cell, expand the view to show all the content
You seem to be on the right track as this should work for cell based NSTableViews. You need to put tableView:shouldShowCellExpansionForTableColumn:row: in the tableView's delegate. You could reply YES for the column of interest.
With a view based table where you use NSTextFields these scroll, truncate or wrap but there is not an expand on hover option. It is possible to set the tooltip text to be the same as the content which might be a reasonable solution.
Did you try to change the row height (tableView:heightOfRow:) triggered by some mouse action? You might have to reload the tableview.

NSTableView group row text field selection

I want to make a custom text selection in my table view.
I found this awesome answer on how to set the colors, fonts, etc. of the cells.
However, there is one issue.
It does not work for group rows. I see that the method gets invoked, but I think the style gets overwritten somewhere in either the NSTableCellView, or in the NSTableView class.
How can I fix this?
EDIT
It's a view based NSTableView

Force redraw as resizing NSTableColumn in NSTableView?

I've implemented - (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row in my NSTableView's delegate to resize the height of my table's rows as the width of the leftmost column changes. The problem is that only that column redraws during the resizing (and any column that slide into view during the resize).
This results in the funky visual below after resizing. What I'd like is a way to tell the table view to completely redraw while the user is resizing a column. Right now the most I've been able to do is call setNeedsDisplay after that column finishes resizing.
Check out the NSTableView method noteHeightOfRowsWithIndexesChanged:. You'll need to make an NSIndexSet of the rows whose heights have changed.
update:
In order to have a safe place to call this, you can subclass NSTableColumn to override the setWidth: method. You can then post a custom notification that your table delegate can observe, or you can override the table view also and have the column tell the table to tell its delegate directly.
It may not be the only way, but giving the table view a Core Animation layer fixed it. It's not 100% smooth, but the average user would probably never notice.