NSTableCellView dynamic height with NSTextField multiline autolayout - macos

I have a view-based NSTableView and NSTableCellView subclass which having multiline NSTextField with word-wrap enabled. Now I want my table to have dynamic row height according to textfield content. Autolayout is also enabled.
Textfield's constraints is shown in image:
Tableview heightForRow method code :
- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row {
VerseTableCell *cell = [self getTableCellForRow:row];
[cell.txtSuraDetail invalidateIntrinsicContentSize];
[cell invalidateIntrinsicContentSize];
[cell setTranslatesAutoresizingMaskIntoConstraints:YES];
[cell layout];
[cell setNeedsDisplay:YES];
[cell setNeedsUpdateConstraints:YES];
[cell setNeedsLayout:YES];
[cell layoutSubtreeIfNeeded];
NSRect size = cell.txtSuraDetail.frame;
CGFloat height = (size.size.height) + 30;
return height;
}
Cell Layout Method :
- (void)layout {
[super layout];
self.txtSuraDetail.preferredMaxLayoutWidth = self.txtSuraDetail.frame.size.width;
}
I've tried the following links but nothing helped, textfield's text is still cutting.
Automatically adjust height of a NSTableView
View-based NSTableView with rows that have dynamic heights

Related

Width of NSTextField inside NSTableCellView

I'm trying to create a very simple NSTableCellView with a textfield and a button. My code to layout the NSTableCellView is below. I want the textfield to have a width of 100px.
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
MyTableCellView *cellView = [outlineView makeViewWithIdentifier:#"MyTableCellView" owner:self];
if (cellView == nil) {
cellView = [[MyTableCellView alloc] initWithFrame:NSMakeRect(0, 0, NSWidth(outlineView.bounds), [outlineView rowHeight])];
NSTextField *textField = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, [outlineView rowHeight])];
[cellView addSubview:textField];
cellView.textField = textField;
NSButton *button = [[NSButton alloc] initWithFrame:NSMakeRect(108, 0, 50, [outlineView rowHeight])];
[cellView addSubview:button];
cellView.button = button;
cellView.identifier = #"MyTableCellView";
}
cellView.textField.stringValue = item.stringValue;
return cellView;
}
When I do this, however, the NSTextField takes up the entire row:
What am I doing wrong?
I found the problem. I didn't think twice about setting the NSTextField I created to the NSTableCellView's textfield outlet. It turns out this should not be done because then it is automatically resized.
So I took out this line and it works as expected:
cellView.textField = textField;

Autolayout in an NSView being used as a cell for NSTableView

I am trying to build an NSTableView similar to how Things does it's layout.
I assume what they are doing is using an NSTableView with a custom-drawn NSTableCell -- or perhaps it's an NSSegmentedControl. I am attempting to go down the NSTableCell route. I attempted to subclass an NSTableCellView and draw a custom cell (this is all in the init method for testing);
- (id)init {
self = [super init];
if (self) {
_checkbox = [[NSButton alloc] init];
[_checkbox setButtonType:NSSwitchButton];
_textview = [[NSTextView alloc] init];
[self addSubview:_checkbox];
[self addSubview:_textview];
[self setTranslatesAutoresizingMaskIntoConstraints:NO];
NSDictionary *views = NSDictionaryOfVariableBindings(_checkbox, _textview);
[self addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[_checkbox]-[_textview]|"
options:0
metrics:nil
views:views]];
}
return self;
}
#end
Seems pretty self-explanatory, but it doesn't actually work. I am getting errors on constraints not being able to be satisfied. Is it not possible to use autolayout inside a subclassed NSTableCellView?
It is possible although you have to introduce some additional code to the table view controller:
- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row
{
NSTableCellView *rowView = [self.tableView makeViewWithIdentifier: RVIssueSelectionTableRowViewContentKey owner: self];
[rowView setObjectValue: yourDataObject]; // or update your cell with the according data the way you prefer
[rowView setNeedsLayout: YES];
[rowView layoutSubtreeIfNeeded];
return [rowView fittingSize].height;
}
This will cause the cell to update it's layout and you can return it's desired height. Because this call can be kind of expensive you should cache the calculated cell height.
This answer has been taken from another SO answer which I could not find right now (will update the solution when I've found it).
Your error messages for the constraints are generated because you force the cell to have a height of x (through the table view datasource methods). But your constraints want to set the height of the cell so they are satisfied. Both at the same time can not work.

NSTableView: problems with title for NSButtonCell

I have the NSTableView object, that consists from one column with NSButtonCell cell.
Also I have the class, that implements the NSTableViewDataSource protocol.
The method to set the cell value:
-( id )tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
NSButtonCell* cell = [[[NSButtonCell alloc] init] autorelease];
[cell setTitle:#"Title" ];
[cell setState:NSOnState];
return cell;
}
In result the state of the button displayed properly but the title stays empty.
How I can set the title of the button?
I solved this issue by replacing the
NSButtonCell* cell = [[[NSButtonCell alloc] init] autorelease];
to
NSButtonCell* cell = [tableColumn dataCell];

Changing view in NSWindow removes contents of view

I am using an NSToolbar and NSWindowController to change the views of an NSWindow. When the toolbar items are selected, the view is successfully changed for the window and the window changes it's size according to the view size. Upon the initial loading of the window, the contents of the view appear as expected. However, once a toolbar item is selected the contents of the new view are not visible and when the view is switched back to the original view, it's contents are no longer visible either. Not sure what is causing this so any help would be appreciated.
#import <Cocoa/Cocoa.h>
#interface WindowController : NSWindowController {
IBOutlet NSView *firstView;
IBOutlet NSView *secondView;
int currentViewTag;
}
- (IBAction)switchView:(id)sender;
#end
and
#import "WindowController.h"
#interface WindowController ()
#end
#implementation WindowController
- (id)init {
self = [super initWithWindowNibName:#"WindowController"];
if (self) {
}
return self;
}
- (void)windowDidLoad {
[super windowDidLoad];
}
- (NSRect)newFrameForNewContentView:(NSView*)view {
NSWindow *window = [self window];
NSRect newFrameRect = [window frameRectForContentRect:[view frame]];
NSRect oldFrameRect = [window frame];
NSSize newSize = newFrameRect.size;
NSSize oldSize = oldFrameRect.size;
NSRect frame = [window frame];
frame.size = newSize;
frame.origin.y -= (newSize.height - oldSize.height);
return frame;
}
- (NSView *)viewForTag:(int)tag {
NSView *view = nil;
switch (tag) {
case 0:
view = firstView;
break;
case 1:
view = secondView;
break;
}
return view;
}
- (BOOL)validateToolbarItem:(NSToolbarItem *)item {
if ([item tag] == currentViewTag) return NO;
else return YES;
}
- (void)awakeFromNib {
[[self window] setContentSize:[firstView frame].size];
[[[self window] contentView] addSubview:firstView];
[[[self window] contentView] setWantsLayer:YES];
}
- (IBAction)switchView:(id)sender {
double tag = [sender tag];
NSView *view = [self viewForTag:tag];
NSView *previousView = [self viewForTag:currentViewTag];
currentViewTag = tag;
NSRect newFrame = [self newFrameForNewContentView:view];
[NSAnimationContext beginGrouping];
if ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask)
[[NSAnimationContext currentContext] setDuration:1.0];
[[[[self window] contentView] animator] replaceSubview:previousView with:view];
[[[self window] animator] setFrame:newFrame display:YES];
[NSAnimationContext endGrouping];
}
#end
I tried out your code, and what I saw was not that the views disappeared, but that they were positioned wrongly and moved out of view. I fixed this by turning off auto layout in IB, and deselecting all the struts and springs in the size inspector. I also deselected the window's "restorable" property so that if you closed the program with view 2 visible, and reopened, the window (with view 1 inside) would be the correct size for view 1.

How to right set height of NSTableCellView with NSTextField?

Greets!
I have a View-based NSTableView with Custom View as a cell (NSTableCellView class).
There is NSTextField inside custom cell.
I need to display 3 lines of text inside NSTextField and after clicking on cell content must grow up to fit full text.
So, I need to increment height of NSTextField and height of NSCTableCellView by click in other words.
Alghoritm is:
Handle click on NSTableCellView
Calculate new sizes of NSTextField and NSTableCellView
SetFrameSize to NSTextField through IBOutlet
Store new NSTableCellView height value in class and invoke function "RowHeightChanged" through Notification Center
Set new row height from class value
This is a code snippet: (i erased some unusefull things)
TickCellTableView:
#implementation TickCellTableView
// Other Constants
#synthesize textFieldInitHeight = _textFieldInitHeight;
#synthesize rowHeight = _rowHeight;
#synthesize rowIndex = _rowIndex;
- (void)mouseDown:(NSEvent *)theEvent {
if (![self.superview isKindOfClass:[NSTableCellView class]])
[super mouseDown:theEvent];
CGFloat TextFieldFitHeight = [self getHeightForStringDrawing: self.textField.stringValue
withFont:[self.textField font]
forTextWidth:[self.textField frame].size.width + 10.0];
if ([self.textField frame].size.height < TextFieldFitHeight)
{
NSSize size = [self.textField frame].size;
size.height = TextFieldFitHeight;
[self.textField setFrameSize:size];
self.rowHeight = [self frame].size.height + (TextFieldFitHeight - _textFieldInitHeight);
[[NSNotificationCenter defaultCenter] postNotificationName:#"RowHeightChanged"
object:self.rowIndex];
}
}
#end
NSTableView Delegate:
#implementation DisplayTicksView
- (void)awakeFromNib
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(RowHeightChanged:)
name: #"RowHeightChanged"
object:nil];
}
-(void)RowHeightChanged:(NSNotification *)notification
{
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:[notification.object integerValue]];
[tableView noteHeightOfRowsWithIndexesChanged:indexSet];
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
return [ticksArray count];
}
#end
The problem is when i clicked on the NSTextField it's frame grow up just for the second and return to init size, after that starts animation to set property height of cell.
In result - Cell height is up, but NSTextField none. I tried to disable animation - no result. How can i fix that?
Appologise my English :)

Resources