Cocoa Bindings with NSComboBox - objective-c

I have Cocoa Bindings working with a NSComboBox that shows and autocompletes values based on a Managed Object Context. My issue is trying to get the current selection after the user either selects from the dropdown or the autocomplete text is used. I know that the Array Controller class has a selected objects property, but when I try to use it to pull out the selected object I get nothing. With a NSComboBox do I have to set the selection once the text/selection of the combo box occurs or is there something I'm missing setting up the Array Controller.
Thanks

A combo box allows any arbitrary string to be entered, right? (You're not limited to the items you can autocomplete, unlike a popup menu.) So it doesn't have a concept of selected item, since the text in it might not correspond to any item in your database.
This question seems to address a similar issue, declaring it to be unsolvable using only bindings, and links to a blog post that has some hints on what code needs to be added. The gist of it is that, when the user finishes editing the combo box, you create your own fetch request in code and use the response from that to link up the model.

Related

Radio buttons used in a rad grid in batch edit mode

I am trying to find any information about using a radio button in a rad grid in batch edit mode. I have created a template column, then added the radio button control, but it doesn't work in batch edit mode (nothing saves back to the DB). Is it even possible? I can't find anything on the Telerik site so I am suspecting its not supported. Thanks.
The Radio list is not supported in the batch editing mode. Such integration simply has not been implemented. The closest available option at this time is using a dropdown list: http://demos.telerik.com/aspnet-ajax/grid/examples/data-editing/batch-editing/defaultcs.aspx. Generally speaking, the standard way of editing boolean fields is through a checkbox column and not a radio button list - check the Discontinued checkboxes column.
What the grid does is that it loops through the controls with JS code when cells are opened and closed and determines control types and the proper API to use (e.g., $get().control.get_value() for dropdownlists, or $get().value for standard inputs). You can try implementing similar logic in the batch editing events.
You can try to use a RadRadioButtonList with the two items declared in its markup and its client-side API (see the get_selectedIndex() and set_selectedIndex() method: https://docs.telerik.com/devtools/aspnet-ajax/controls/radiobuttonlist/client-side-programming/radiobuttonlist-object) together with the following approach of working with templates: https://docs.telerik.com/devtools/aspnet-ajax/controls/grid/data-editing/edit-mode/batch-editing/working-with-templates.
The idea is to have the radio button list in the edit template of the column and to select the correct item in it according to the newly opened cell value on the client, then fetch the selected item from the button list and put it in the grid data source.
You can find one example that you can try using as base in the following thread: https://www.telerik.com/forums/radiobuttonlist-in-gridtemplatecolumn.
Showing a radio button list in the item template is also something that is not supported, as the editing would basically happen in the "display" mode of the cell, and not in the edit mode of the cell. You could try using the server ItemDataBound event and FindControl() (see here: https://docs.telerik.com/devtools/aspnet-ajax/controls/grid/rows/accessing-cells-and-rows#accessing-controls-in-template-column) may let you set initial values based on the data source for the radio button lists without data binding them. Then, perhaps a hidden field or hidden checkbox can be used for the actual data binding (see the template article above). You could also try using the batch editing manager changeCellValue() method on the client-side events of the radio button list, in a fashion similar to this article: https://docs.telerik.com/devtools/aspnet-ajax/controls/grid/data-editing/edit-mode/batch-editing/how-to/editing-checkboxes.
Another approach you can consider is to use the client-side events of the radio button list and immediately upon change to call a service that will update the database. This may simplify the template handling logic (you could do this in a read-only column) but it goes against the purpose of batch editing to invoke one request with a lot of data, and you would also need to secure the service.
Another online resource to check is
https://docs.telerik.com/devtools/aspnet-ajax/controls/grid/data-editing/edit-mode/batch-editing/how-to/editing-checkboxes

Pass hidden data through XUL autocomplete textbox?

One of the controls needed in my xulrunner application is an autocompleting text box which allows the user to type a search term, then looks up completions in an array of objects (each having a generated UUID, canonical name, a list of search terms gleaned from related data, etc.) and allows the user to select just one. Currently I'm using a textbox element of type="autocomplete" and a Javascript custom search component, and it is successfully prefix searching all the search terms and providing completions below the text field, in the customary fashion.
The catch is that I'm not interested in the possibly non-unique label but the object from which the label came, and I can't see any way of passing the object or even any out-of-band UUID back into document land without modifying the XBL or rolling my own control from scratch. Essentially I'm seeking to do what could have been done in HTML with the option[value] attribute. I can't use the built-in type-to-search effect of a standalone menulist because I need to prefix search multiple fields of the object. Any recommendations? Thanks in advance.
I ended up rolling my own as a listbox inside a panel next to a textbox. Even composed into an XBL binding, this was less effort than I'd spent working with the built-in autocomplete textbox and trying to force it to handle what it wasn't intended to handle.

QInputDialog like thing in Cocoa/Xcode?

I'm fairly new to Xcode and Cocoa/Objective-C and I'm trying to implement something as simple as a QInputDialog that can be re-used throughout the program - with a unique message to the user each time it is launched and return a string as a result.
I have searched the web and found multiple methods but nothing seems to be quite clear or concise - well enough for me to understand anyway.
Is there anything out there as simple as:
Create/Launch a window from a method with a new message label to the user in the form of a string.
Has an NSTextField to receive the users input.
Close the window and return the string from the text field (if accepted) to the calling method.
??
Modal prompts for input are very un-Mac-like. It's like smashing the user's face in with a cricket bat and yelling “TELL ME THE ANSWER NOW!”
The correct solution is to put your text field into a non-modal window, so that the value is already ready when the user invokes whatever action needs the value. Beep and show the “hey, you forgot this” icon if the user hasn't filled in the field and you need a value there. If the field is not relevant in the window the user starts the action from, or if you're going to need several facts as input, then show another window, non-modally, with its own window controller, to take in all the input you'll need for the action.
A separate, non-modal window will also enable the user to fill out and/or perform multiple such actions in parallel.
If you must demand the value with a modal dialog, you can and should make it a sheet, but you'll still need to build the panel and its contents from scratch in IB or code.
See also the Sheet Programming Guide and the chapter on windows in the Human Interface Guidelines.

Interface Builder NSStaticText value needs to be updated every time anything changes in dialog

I have a modal dialog thats building a string. The string is shown to the user, and the user presses checkboxes, radio boxes, etc to build the string. The string exists nowhere - I build it for display in -()builtString; from the configuration of the self.valuesDict.
I can easily wire up the checkboxes via bindings in IB: for example to the files owner (the controller) with self.valuesDict.checkbox1
Also I bound the display of the string to "self.builtString".
But every time any checkbox changes, I want to redisplay the string that's shown to the user.
If I abandon bindings, then I think I can use the [self willChangeValueForKey:#"builtString"], for each checkbox, etc, I think, but that is some messy looking code by the time I deal with them all.
So how do you tell a nstextfield in IB to update every time say self.valuesDict changes?
Thanks for any comments/suggestions.
--Tom
You can specify dependencies between bindings. Just write a class method +(NSSet*) keyPathsForValuesAffectingBuiltString that returns a set with all key paths of properties builtString depends on. Then things bound to your string will also be updated when one of the other properties is changed. For more details and step-by-step instructions you can look at this article.

How to set value of NSComboBox by KVC?

I have several NSComboBoxes created in Interface Builder, and one created programmatically.
The NSComboBoxes created in Interface Builder are perfect. I have their Value bound to the Shared User Default Controller, and when their view is opened they are sitting there with the correct value. Importantly, this value is shown as "normal" text in the NSComboBox. In other words, the value doesn't appear selected. This is what I want.
For the NSComboBox that is created programmatically, I set the value using selectItemAtIndex:0. When I do this, the correct item is selected--but the text appears selected. I.e., it is highlighted and everything. I don't want this. Here are the workarounds I've attempted:
(i) Get the field editor and set insertion point to the end of the text. This doesn't work although, oddly, the field editor's string is either nil or empty when doing this. I'm not sure if this is correct behavior for the field editor.
(ii) Trying various other ways of setting the combo box's value, such as setObjectValue, takeStringValueFrom, etc.
(iii) Finally, and most frustratingly, I tried to set the value of the NSComboBox using [myComboBox setValue:#"The Default Item" forKey:#"value"]; This fails with objc_exception_throw, presumably because there is no such KVC key. But I know that the value of the combo box can be set by KVO, because it works in interface builder! I'm guessing that I don't know the correct key path. I tried to enumerate all the properties using introspection, but I can't get the code working right (objc_property_t isn't in the expected headers).
So, I have two questions:
First, does anyone know how to set a default value for NSComboBox programmatically, so that the text in the box isn't selected? I will go to any lengths to do this, including a new NSComboBoxCell subclass, if it comes to that.
Second, can somebody tell me what key or key path IB is using to set the value of an NSComboBox? Or alternatively, why my efforts to do this are failing?
I've been working on this for many hours now and I am truly disspirited!
THANK YOU, mustISignUp! So nice to have this fixed. A little bit of followup:
(i) Selection of the text is definitely caused by focus. Calling setRefusesFirstResponder:YES fixes the problem. Unfortunately, the window really wants to focus on this combo box, as setting refusesFirstResponder back to NO (later, after window inititation) causes text selection again (I do want the user to be able to focus on this box if he desires). Therefore, in my case, the definitive solution was to call [window makeFirstResponder:otherControl]. Oddly, though [window makeFirstResponder:nil] doesn't work. Any ideas why?
(ii) Thanks for pointing out the difference between bindings and properties. I learned a lot while looking into this question. For one, I learned that you can get a list of bindings by calling - (NSArray *)exposedBindings, which for NSComboBox returns (fontSize, alignment, toolTip, fontName, enabled, contentValues, fontFamilyName, font, hidden, fontItalic, textColor, value, content, editable, fontBold). Second, I was able to set the value using [myComboBox bind:#"value" toObject:[NSMutableString stringWithString:#"defaultValue"] withKeyPath:#"string" options:nil], where NSMutableString has a category on it that turns "string" into a property. Finally, this actually doesn't fix the text selection "problem". The difference between text selection with this combo box and those in Interface Builder must be their position in the window...I guess that this combo box is just slated to become initialFirstResponder while the others weren't.
So my only remaining question might be why [window makeFirstResponder:nil] doesn't work to take focus off the combo box. Not super-important, but I'd be curious if anybody has an idea.
Firstly, i think the text is selected because calling selectItemAtIndex: has made the comboBox the firstResponder. You could use setRefusesFirstResponder:YES or you could make another item the first responder to make the text not appear selected.
If i have understood correctly and you want to change the selection of the comboBox you are doing it the right way.
Secondly, you are confusing Bindings and KVC. NSComboBox has a binding called 'value', not a property called 'value'. It is meaningless to try to set it with setValue:forKey:, and Interface Builder definitely isn't doing this.
You would be right in thinking this is un-obvious and confusing and maybe better names could have been chosen for the bindings.