Edit text in NSOutlineView like Finder - cocoa

If you rename a file in the Finder, the text field expands horizontally up to about the width of the column. And then it expands vertically up to three rows before scrolling. I'm assuming this has to be done in a text field outside the outline view. And I can get a text field to resize while I type. I just don't know how to place it over the outline view when necessary. And keep it pinned to the row if the outline view scrolls. Does anyone have any insights? Thanks!

Text editing is handled by a dedicated NSText and it’s called “field editor”. This shared single view is used for all text editing that happens in the window. It’s separate from what usually displays the text (when not editing).
Here are the docs:
https://developer.apple.com/documentation/appkit/nswindow/1419647-fieldeditor
As mentioned in the docs discussion section, you can use and customize another field editor. This should be a starting point for your task.
The window’s delegate can substitute a custom field editor in place of the window’s field editor by implementing windowWillReturnFieldEditor(_:to:). The custom field editor can become the default editor (common to all text-displaying objects) or specific to a particular text-displaying object (object).
NSControl docs also have a section about Field Editor that might help.

Related

Manage Undo across multiple NSTextFields in the same window

While Undo for multiple NSTextViews in a window work persistently, the same is not the case for NSTextField controls by default.
I like to make Undo behave the same for NSTextField as it works with NSTextView.
I have so far found out that NSTextField uses its own private NSUndoManager, which does enable and handle the Undo/Redo menus autmatically, but without using the window's shared undoManager, and without marking the connected document dirty ("edited"): If I provide a private NSUndoManager instance to an NSTextField, it'll behave the same.
So I've tried, by overwriting undoManagerForTextView:, to have the NSTextFields in the window use the window's shared undoManager. That will indeed lead to the effect that the text fields share the same undo stack, and I can still issue an Undo after editing and then leaving a specific text field.
However, the problem is that it'll then crash, because it appears that the Undo gets applied to the wrong (i.e. the currently active) text field and not to the one the undo action was created from.
I've provided a simple example here: https://github.com/tempelmann/Undo_shared_NSTextFields
It's a freshly created document based app, with two text fields and two text views in the main window. To enable the shared undo manager for the text fields, I've created a subclass ("CustomTextField") of NSTextField that overrides the following function to provide the shared undo manager:
-(NSUndoManager *)undoManagerForTextView:(NSTextView *)view { // NSTextViewDelegate
return view.window.undoManager;
}
And the text fields in the storyboard are set to this subclass instead of NSTextField.
When run, it looks like this:
Now, if you edit the first and the second text view, and then use Undo twice, it'll undo the changes in each text view just fine.
But if you try the same with the two text fields, e.g. by replacing the longer preset texts in the fields with something shorter (such as "1" and "2"), you'll find that Undo replaces the text in the same active text field twice:
How do I make Undo in the text fields behave correctly, i.e. the same as the text views do?

How to display elements inside NSCollectionView with various shapes

I am a rookie Cocoa guy. I need to design and implement a view which will show collection of labels on Mac OS using Xamarin. These labels will have a text and color associated with them. When shown inside the view, label should expand till it covers whole text and it will be shown with background and foreground colors.
I have attached the picture of this user control on Windows, you can see that labels inside the StackPanel are expanding till they cover the whole text. Hope this gives better idea about my ask.
The $64,000 question is "are these labels controls?" In other words, do you expect the user to click on these to do something, or are they just for display?
If your answer is "just for display", the solution is super simple: Use an NSTextField and programmatically add attributed text (NSAttributedString) to it. Attributed text attaches display properties to runs of text within the field; properties like "background color".
If you want these to be buttons that you can click on, then things get a lot more complicated.
Since you apparently want the button layout to "flow", you might look into imbedding buttons (well, button cells) into an NSTextField using attachments. This is normally how non-text content (say, an image) can be inserted, but with some fiddling it can actually be anything a control cell can draw. See How to insert a NSButton into a NSTextView? (inline).
Warning: this is not a "rookie" topic and will involve control cells and custom event handling.
If I were doing this, I'd probably just create NSButton objects for each label (choosing an appropriate style/look like NSRecessedBezelStyle), create a custom subclass of NSView to contain them, and then override the layout method to position all of the buttons the way I want.
To be thorough, I'd also override the intrinsic size methods so the whole thing could participate in auto-layout, based on the number and size of buttons it contained.

Cursor blinking when NSTextView is not the first responder?

I have an NSTextView object within a complex custom view. I need that custom view to be the first responder (for multiple reasons, e.g. to have its focus ring drawn properly). But the NSTextView cursor must still blink as if the text view was the first responder.
Here's essentially what I want to see in my application (a screenshot of the search field in Apple Mail):
Note that the text view is the empty area with the cursor located at the beginning of it. The other elements belong to the parent custom view, which has the focus ring around it. The cursor is blinking!
I couldn't implement that behavior using the standard controls. My final solution is to put the search field in another custom view with broad margins and implement a custom focus ring drawing.
Here's how my drafty control looks like:

How to change Label Font with the FontsPanel in cocoa

I made a PushButton to open up a Font Panel like they did here:Make NSButton open fonts panel
I did all of these through the Interface-Builder by dragging buttons and Labels onto the MainMenu View and i have nothing inside my AppDelegate.h and .m
Im really new to objective c and cocoa so i was wondering if anyone could give me an in depth explanation on how to use that font panel to edit the font in a Label or a Text Field.
Both label and text field are class NSTextField.
The style of the text they display is determined by the attributes on their NSAttributedString.
The Attributed String Programming Guide on Apple's developer site goes into detail on how to handle attributes. The font is one of those inside an attribute called paragraph style.
That should get you started on what to look into.
The Cocoa text architecture is pretty rich and can take some time to get familiar with.
One thing to note, when a text field is in edit mode, it uses something called the field editor for rendering , which is normally a shared instance of NSTextView that is owned by the window and basically appears in front of the text field during editing.

Placeholder Adopting from Previous Text Field

Quick question! When any NSFormCell becomes the first responder, its placeholder text becomes that of the last NSTextField to have focus. Here's an illustration: http://i.imgur.com/3dlzj.jpg
However, the NSTextFields never encounter this! Have you seen this before? This is happening in Xcode 4.3 — what thoughts do you have?
Thank you!
This isn't an answer, but just some further observations.
I did some experimenting with this, and it's not anything you're doing. If you just drag a form and a text field into a window in IB, and put a placeholder string in the text field, then that placeholder appears in the form if you first select the text field and then one of the form cells (with no code at all in the app). It doesn't matter whether you put any placeholder in the form in IB, it still gets the one from the text field. I also put a button in the window with an action that logs the placeholderString of one of the cells -- it always logs null, even though it shows the text field's placeholder. If you put a placeholder in that cell (in IB), then it logs that placeholder, but if you select the text field and then that cell, the text field's placeholder shows up, but the log still shows the original placeholder.
This looks like a bug to me. It might have something to do with the field editor? Isn't there a shared field editor for all text fields in a view?

Resources