How to configure a view-based NSTableView to behave like so:
Rows are selectable
The user are unable to trigger edit mode by clicking a cell
Edit mode can be triggered by calling NSTableView-editColumn:row:withEvent:select: programmatically
The table view is dragged from the object library of Xcode interface builder, i.e., it uses an NSTableCellView (with an NSImageView and an NSTextField as its subviews) as the table view's cell view.
For view-based table views, -editColumn:row:withEvent:select: is relatively ineffective. It attempts to make the cell view the first responder for the window, but only certain views will accept first responder status. NSTableCellView does not, because it is not itself editable.
If you want to programmatically initiate editing in the text field within an NSTableCellView, you can do something like:
NSTableCellView* cellView = (NSTableCellView*)[tableView viewAtColumn:col row:row makeIfNecessary:YES];
if ([cellView.textField acceptsFirstResponder])
[cellView.window makeFirstResponder:cellView.textField];
To disable the user from starting editing through the UI, I think you will need to set the text field to not be editable. You would make it editable just before you initiate editing programmatically. For example, add a line cellView.textField.editable = YES; between the above two lines.
Then, you'll want to set it back to non-editable after editing ends. To do this, you can set the delegate of the text field to your controller object and implement -controlTextDidEndEditing:. Or, similarly, you can add an observer of the NSControlTextDidEndEditingNotification notification from the text field. Either way, when your code is called, you set the text field's editable property back to false. (If you don't otherwise have a reference to the text field in question, you can obtain it from the NSNotification's object property.)
Related
I have a Cocoa app with an NSOutlineView (view-based) showing a directory tree very much like Finder.
Basic cell editing works, i.e. I can select a cell representing a file and press Return to edit its name.
Now I'd like to pre-select the file name excluding the file extension like in this example:
However, by default, everything in the text field is selected. How can I select only a specific portion of the value?
I could not figure out how to intercept when editing a table cell view begins to set the selection. I made my outline view the delegate of the NSTextField in the NSTableCellView, but control(_ control: NSControl, textShouldBeginEditing fieldEditor: NSText) and controlTextDidBeginEditing() are only called when the user types the first letter.
Again, my outline view is view-based. What am I missing here?
I'm working on an app that presents an NSPopover containing a number of NSTextFields. While I can tab between these fields as I expect, the popover is selecting a particular text field to be in the editing state when it appears, and it's not the field I want to edit; I'd like to be able to define which text field is editing on popover appearance programmatically (or in Interface Builder). How can I do this?
I've set up the appropriate key view loop by connecting IB outlets for all the various text fields involved, and I've hooked up the popover's nextResponder property to the text field I want to edit first, but that doesn't seem to have an effect - the popover will still select its preferred text field instead of mine. The Window Programming Guide suggests that I set the initialFirstResponder outlet of the window to the view I want selected, but an NSPopover is not an NSWindow and has no initialFirstResponder property (unless I'm missing something obvious).
Is there any way to specify which NSTextField I want to be editing when an NSPopover appears?
I think you said you tried using -makeFirstResponder: and passing the text field. This will set the window's firstResponder, but that's not the same as initialFirstResponder and the window must have initialFirstResponder set to something other than nil in order to respect the key view loop. (Source) A slight tweak to what you tried worked for me:
- (void)popoverWillShow:(NSNotification *)notification
{
// Set the window's initialFirstResponder so that the key view loop isn't auto-recalculated.
[[myField window] setInitialFirstResponder:myField];
}
I think you can make this work by setting all the text field's that you don't want to have focus to "selectable" instead of "Editable" in IB, this should leave the one text field you want to start with as the first responder. Then, in your popoverDidShow: method, set them all back to editable, and you should be able to tab between them as usual.
I set NSButtonCell as a cell type in a Table Column in my NSTableView.
I implemented an IBAction method, but I can't wire it with NSButtonCell in IB - the wire don't want to highlight a button from NSTableView.
How to connect a method with NSButtonCell? Or maybe there'se another way to handle its click event?
Thanks
You should be able to wire up a connection from the cell by control+dragging to any object in your NIB. Just make sure the cell is actually selected, and that your action is defined as an IBAction in the object's header file. In your action method you can determine which row was selected by calling [tableView clickedRow].
Edit: Here's a demonstration. Make sure you click at least four times on the check box to get it selected, hold down the control key and drag from the cell to your object.
I've just created my first view-based NSTableView in Interface Builder and I've correctly set up the data source and the bindings to update the views in the tableview. Each view has two labels and a NSProgressIndicator. Updating the progress indicator through the bindings and the data source works perfectly, but I'd like to change its state from determinate to indeterminate at some time. As my NSTableCellView subclass has access to the progress indicator, how can I get access to the cell view at a given row index? I've tried calling viewAtColumn:row:makeIfNecessary: on the tableview with both NO and YES for the makeIfNecessary argument, but neither seems to work.
Solution 1: In your NSTableCellView subclass add a property (IBOutlet) for your NSProgressIndicator control. Wire it in IB to set the property when the view is loaded. You can then access the progress control in your cell view subclass by using the property.
Solution 2: In IB give your NSProgressIndicator a unique integer tag. In your cell view subclass use [self viewWithTag:] to get the object.
I am not sure about the answer to your main question but you can bind the indeterminate state as well. In IB Is Indeterminate is listed in the Parameters section.
I made a Cocoa application that has an NSTableView, an NSTextField, and an NSButton. The user enters text into the text field and clicks the button. When the user does this, I want the text in the textfield to be placed in the NSTableView. I find that I can't even bind an IBOutlet to a cell in the NSTableView. What should be done?
The Model-View-Controller pattern, which is used extensively in Cocoa is your friend here.
What you need to do is to bind the NSTableView to an array (The model). Then configure the button so that a click tells the controller to add the content of the text field to the array and if the bindings are set up correctly the NSTableView (The View) will be updated.
What I think you need to do is make a class, AppController for instance which will be your data source and the delegate of the NSTableView. So you need the following.
Two IBOutlets (one for the NSTextField and one for the NSTableView)
An IBAction for the NSButton.
Make those connections in Interface Builder.
Remember to use the mandatory delegate methods (there are two of them) so you can add the data from your data source (usually a collection class..an array, dictionary...etc.