Cocoa disabling a NSTextField - cocoa

Ok, I am working on a Cocoa app and I cannot get the text field to disable when the "Default Source" button is clicked. The cursor by default is in this text field when the program starts. When I click the default source button, the text field is not disabled until I manually click on another field and thus remove the cursor from the source text field. How do I make the text field disable immediately even though the cursor is there? Even if the cursor isn't there, the text field won't disable until I move the cursor there, and then back to another field.
I don't yet have 10 reputation... here is the link to the picture: http://i.stack.imgur.com/Bu0OG.png
Currently, this is the only line of code that is in the function that is called when you click "default source":
sourcePath.enabled = NO;

Try checking if your on the main thread before disabling by:
NSLog(#"is main thread: %d", [NSThread isMainThread]);
If your not, then you can:
dispatch_async(dispatch_get_main_queue(), ^{
sourcePath.enabled = NO;
});
This code may be a little inaccurate as my background comes from iOS...

Related

Make NSWindow.isMovableByWindowBackground work with NSTextField

I have a Cocoa app that shows a "quick search" window similar to Spotlight. The window contains a visual effect view and inside a NSTextField. The text field stretches across the full width of the window.
I would like to be able to move the window by dragging inside the empty area of the text field. When dragging across text in the text field, the normal editing (i.e. selection) behavior should be used instead.
In theory, moving a window by its background is easy:
window.isMovableByWindowBackground = true
However, this behavior does not work with NSTextField, because it intercepts dragging and attempts to select text instead.
Spotlight does it somehow. Here's an example:
A couple of options that I considered without success:
Tried overriding hitTest: returning nil
Tried overriding mouseDown|Up|Dragging: and forwarding to superview
Tried to use autolayout to have text field shrink to tightly wrap around its text (could not figure this one out)
For reference, I finally found a way:
Part 1: get NSTextField to grow/shrink with its content
Override intrinsicContentSize and measure its content:
private func measure(_ string:NSAttributedString) -> NSSize
{
let cell = NSTextFieldCell(textCell: stringValue)
cell.attributedStringValue = string
return cell.cellSize
}
Part 2: view setup
Add a placeholder view right after the text field
Set up auto layout to have the placeholder view to grow and shrink
Part3: all about the details
Set up the placeholder view to use the iBeam cursor to make it appear like a text field
If the user clicks in the placeholder view, make the text field the first responder
That's it.

Remove Focus from UITextField

I'm trying to remove focus from a UITextField and even though I resign it from being first responder, I'm still not able to have the cursor not focus on the text field.
I don't have any other input on the view to move the focus to and I don't want to create a dummy one either. What is a good workaround for this?
As per the documentation.
To dismiss the keyboard, send the resignFirstResponder message to the text field that is currently the first responder. Doing so causes the text field object to end the current editing session (with the delegate object’s consent) and hide the keyboard.
If you call resignFirstResponder on your textfield then it will end the editing session and the cursor wont be focussing on that textfield.
So please verify one more time whether resignFirstResponder is getting called on that textfield which you want to remove the focus.
Please try to set your current class as delegate of your UITextField. I think you forget to set the delegate that's why it's not working as you are expecting.

Binded NSTextField doesn't update the entity until it lose the focus

I have a Core Data project.
Basically I have an NSTableView where I add some entities (using the "add:" selector), double clicking on the TableView opens a new NSWindow where is possible to edit the entity using some NSTextFields.
Each text field is binded to an attribute of the entity.
Everything is working fine, except the fact that the entity's attributes are updated only when a textfield lose the focus.
If I write on the first text field and then I move to the second one my entry is saved, but if I write on the first text field and I close the window I lose my changes.
How can I update my core data entity as soon as I write something in the text field? Should I use textDidChange:?
--- UPDATE ---
Unfortunately [context save] doesn't work. If I understand correctly the entity is not modified until the NSTextField resign first responder.
The only working solution for now is something like:
(void)controlTextDidChange:(NSNotification *)aNotification
{
NSTextField *tf = [aNotification object];
[self.window makeFirstResponder:tf];
}
but this is quite inelegant, and in any case I also still need to re-set the cursor at the end of the NSTextField.
Setting NSContinuouslyUpdatesValueBindingOption will cause the model to update every time the text field changes, which sets the dirty flag properly and causes the document to save on quit.
I think you could use DidEndEditing or TextDidChange, another way of doing this is handeling in the window close event, but I would not recommend it.
If you don't have one already, you can set a delegate on the window and use -windowWillClose: or observe the NSWindowWillCloseNotification. You can then call [[notification object] makeFirstResponder:[window initialFirstResponder]] to set the window's first responder to its initial first responder as the window is closing. This will cause the control that is first responder (e.g. NSTextField) to resign the first responder status and the binding will save the changes.

Vanishing NSTextField Text

I have a custom view in a .xib file, which I use as the contentViewController for an MAAttachedWindow. The view has several NSTextFields in it.
When I open the MAAttachedWindow first time, everything is fine. Text shows up in all relevant text fields. Then, if I close the window (which sets it to nil) and then call it again (which reinitializes, using the same custom view as the contentViewController), the last firstResponder text field is now blank.
The strange thing is that if I click the "empty" text field, it shows the correct text. This can be edited, and behaves appropriately as long as this text field has focus. As soon as something else becomes firstResponder, the text vanishes again.
Updates:
Changing the color did not change the aforementioned behavior.
The text color does not change at any time during this process.
Placeholder text also is subject to the aforementioned behavior.
No errors are occurring at any time during this process.
This does not happen to NSSecureTextFields.
I first encountered this problem about 5 years ago with accessory view of a NSSavePanel.
The solution that I've found was to move the first responder to the panel itself, before it's closed. Here's my exact method:
- (void)windowDidEndSheet:(NSNotification *)notification
NSSavePanel *savePanel = [(XSDocument *)[self document] savePanel];
if (!savePanel)
return;
// this fixes a bug where on next opening one of accessory view's text field will be blank and behave strangely
[savePanel makeFirstResponder:savePanel];
}
Try changing color of textfield text to red color (or any other color) you may get what happens here.
I got it!
I simply needed to explicitly remove the viewController from its superview before closing (and subsequently deallocating) the MAAttachedWindow.
Try resigning all first responders before setting the window to nil.

How do I stop my NSbutton from being selected when the app starts by default?

I created a button, and a have a little problem: When the my app launches, the button is selected. How do I disable this selection?
Example:
Caveat: This answer is incomplete: It just hides the focus ring (without preventing the selection). There's little benefit in this solution.
Set your button's focus ring type to none:
[myButton setFocusRingType:NSFocusRingTypeNone];
You can also set this option in the XIB.
First, you should know that, by default, buttons can't get focus. A user would have to have selected System Preferences > Keyboard > Shortcuts > Full Keyboard Access: All Controls. If they've done that, they may want a button to initially have focus.
Anyway, the proper way to do this is to call [theWindow makeFirstResponder:nil] sometime after showing it the first time. When to do this depends on exactly how the window gets shown. If you show it explicitly in code, then you can make the call just after that. If it's shown because its Visible at Launch flag is set in its NIB, then you'd do it after the NIB is loaded. Etc.
Something should always be first responder in a window, if anything can be. Normally, only a few controls like text fields can become first responder, but when a user has Full Keyboard Access enabled, it's normal for a button to be selected by default.
If you don't want this particular button to start selected, set the window's initialFirstResponder to another control.
I'd advise against using -[NSWindow makeFirstResponder:nil]. The window will start with nothing selected, but the button will become selected as soon as the user hits tab. This is unusual for Mac apps because there's no way to get the window back into the "nothing selected" state as a user.

Resources