Auto-resizing NSScrollView that wraps an NSTextView - objective-c

How do I tell an NSScrollView that wraps an NSTextView to grow with the NSTextView until a maximum?
== In more details:
The UI is common in many messanger/chat app. Initially, the NSTextView is empty and has just enough height to show one line of text. The NSScrollView is just enough to fit the NSTextView. As the user type in more text, the NSScrollView should grow along with the NSTextView, until reaching a maximum height, then start showing the vertical scroll bar.

Observe NSTextStorageDidProcessEditingNotification on the text storage of the text view. Then call usedRectForTextContainer on the layout manager to determine how large the text is for the view's text container.
You may also need to add extraLineFragmentRect to it, I'm not sure. That's also available from the layout manager.

Related

OS X chat app with resizable bubbles

I'm building chat application for Mac OS, similar to iMessage. I wonder, how can I implement resizable text views in bubbles. I mean, when I resize chat window bubbles with text will resize to. Any ideas, links will be very useful. Thank you for help)
For text resizing, you use auto layout. If you have an NSScrollView containing MYBubbleViews containing NSTextViews, you can add NSLayoutConstraints using the leftAnchor and rightAnchor properties of the scroll view's content view and those of the bubble view, and add constraints between all edges of the text view and bubble view. Then pin the bubble views to the top/prev view.
Also make sure you set the NSTextView to wrap. The width of the intrinsic size of the text view will be set so that it fills the width and the intrinsic height will be set to fit the whole text.
I previously thought it was about drawing the bubbles, so I first gave this answer:
If you look at Messages.app, you'll see that they're not circular bubbles. They are basically composed of several shapes overlaid on each other. A rectangle with rounded corners, plus a bezier path of the tip.
So you should be able to take a NSTextView for the text, make it a subview of a custom view that draws a rounded rectangle and the tip in its drawRect method, and then use auto layout constraints to make your bubble view resize with the text view and the text view to the window width.
You could probably also have the bubble view host a CALayer with fill and rounded corners, plus one with an image for the tip (or aCAShapeLayer for the tip), but drawRect is the easier approach.

NSTextField stops resizing when not editable

I currently have a split view and when i resize the app window i want only the right subview to get larger (so left stays exactly the same size). I have a nstextfield in the right subview where i can type stuff in. However, in certain circumstances I call [_textFieldInQuestion setEditable: NO]. After doing so, when i try to resize the app, the right will get larger up till a certain point, then the left will grow. I saw a post on SO where I should subclass the nstextfield to achieve the behavior, but i was wondering if there were any alternatives that were more elegant and if not, how does one go about override the autolayout methods to produce the behavior i described.
When a text field is non-editable, it has an intrinsic width based on its content. (When it's editable, it doesn't make sense for the text field's width to track its content because its content is not "intrinsic".)
The text field's horizontal Content Hugging priority is presumably higher than the Holding priority of the left view of the split view. So, the text field resists "stretching" to be wider than its content at a higher priority than the left view resists being increased in size.
Reduce the text field's horizontal Content Hugging priority and/or increase the left view's Holding priority so that the former is greater than the latter.

IOS 7 Approach for create container with two elements?

So, i am new to xcode and iOS7 and i'm trying to create simple container with two elements inside.
I prefer to make it 100% programmatically. (no IB)
I want to create container with two elements Image and Label.
I want to achieve variable width depends on the text element inside.
Here is example:
Based on user action i want to change text on the fly. Let's assume longer text, and main container have to change width too.
And now the question is: What is best approach to to that?
UIView with subviews or something else i'm just expecting direction.
Code examples with be gratefully appreciated.
Thank you in advance.
What you have described is exactly what a UIButton does automatically: it is a container containing an image and a title (text) and it resizes itself automatically when the text changes.
Let us assume, however, that you want to do this yourself. That is, let's say you want a UIView ("container") containing two other UIViews (subviews). Then we need to discuss this requirement:
Based on user action i want to change text on the fly. Let's assume longer text, and main container have to change width too.
This is not going to happen automatically. You can use constraints (auto layout) to describe the size / position of the subviews in relation to the superview, but it works the other way: the superview changes, and the subviews obey. So you will have to change the superview size manually after you change the text.
You can still use auto layout to help you. Let's say the text is in a UILabel. Well, a UILabel wants to change width automatically when the text changes. So far so good. But you must still change the container view width yourself. You can call systemLayoutSizeFittingSize: to learn what the size of the container should be, using constraints, working from the inside out; but then you will have to change its size yourself to that size.
(You can easily create the view, the subviews, and the auto layout constraints in code.)
If you don't want to use autolayout, then you will just calculate the sizes and positions of everything when the text changes and adjust it all yourself (in code). You can learn the size the label needs to be, to fit its text, by calling sizeThatFits: (or sizeToFit which will actually resize it correctly).

Get height of content in NSTableView

Is there a way to get the height of the content in an NSTableView. In iOS, you can use the -contentSize method of UIScrollView. However, the -contentSize method of NSScrollView seems to just return the height of only the visible section of the NSScrollView, not including whatever is offscreen.
So, how can this be done on a Mac?
- (NSSize)contentSize in Appkit returns the size of the NSClipView, and not the height of the content that scrolls inside the table view. I don't know how UIScrollViews work, but on OS X, an NSScrollView has a "content view" (more aptly named the NSClipView) that clips the actual content, which is provided by a document view (scrollable if it has a size larger than that of the clip view) that is a subview of the clip view.
As a side note, the NSScrollView scrolls by setting the document view's bounds origin (to the best of my knowledge).
It looks like what you want is the height of the document view, the height of the actual content. For that, try something like
scrollView.documentView.frame.size.height
You can get the real content height of NSTableView by
Objective-C version:
tableView.intrinsicContentSize.height
Swift version: tableView.intrinsicContentSize.height

Resize NSTableView or NSScrollView depending on number of rows in table

I have a view-based NSTableView which is embedded in an NSScrollView. It has custom cells that are x number of pixels high. The NSScrollView is the same size as the panel that it is a subview of. I want to resize the entire NSTableView depending on how many rows are in the table.
Everything is working except the resizing. Resizing the scroll view manually in IB seems to have the desired affect, but NSSrollView does not seem to have a class method to resize its view (like NSView has setFrame). Should I be resizing the scollview, the tableview, both, or something else? Does NSScrollView have a setFrame method or similar that I am missing?
Thanks.
Before you try to do it programmatically, make sure you have the outline view's autosizing masks set up properly in the nib file. It sounds like you simply want the outline view (and its scroll view) to always remain the same size as the window that it's inside.
By default, the autosizing masks of an NSScrollView/NSOutlineView combo that you place into a window looks like the following:
In other words, it's set up to always remain the same size as it is now, no matter how large you resize the window to be.
What you want to do is to change the autosizing masks to look like in the image below:
To do that, you click in the white autosizing box wherever there's a dotted red line to toggle it into a solid red line. Once it's configured that way, the scroll view (and table view) will always (automatically) be resized to be the same size as the window that it's in.
There may also be a way to achieve this using Lion's new "auto layout" feature, but I'll have to leave that to someone who has more experience with it.
In case you really need to do this (such as when you want all rows to fit in the scrollview alleviating the need to scroll) and the scroll view is only a portion of the window/view you can do:
[[myTableView enclosingScrollView] setFrame:newFrameRect];
scrollview.frame = CGRrectMake(x, y, w, h);