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

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.

Related

Cocoa Bindings with NSComboBox

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.

Capital Only Edit Control

Having a bit of a problem doing this and not sure of it can be done. I have an edit control that a user types into, I would like for the input to be all in capital letters. I tried having a custom action on the edit control to get the property, convert to capital letters and set the property again each time a letter is set but it does not work. I guessed it wouldn't but no harm in trying..:)
Has anyone else solved this? I would like to do it without having a button to press if possible. The dialog in question is a twin dialog if that helps at all.
Thanks for your help
It's not possible using the native built-in Windows Installer UI. The underlying MaskedEdit Control is primitive. There are no events to tie into to validate and modify as the characters are entered. You can only ToUpper() the property when the user clicks Back or Next.
The alternative would be to go with an external UI handler which is a lot of learning and work.

How do I create a "wizard" style ui using vb.net?

The idea is that I would have a set of forms, users would click through a "forward" and "back" button, and the current form would change to a different one. My issue is that I can write code that just pops up a new form, but im not sure how to do a "replacement" of my current form. How is this usually done?
What I did recently was to create a form with buttons already in place and a large panel to contain each step. The dialog would accept an initial step in the form of a IWizStep instance, and the things would roll from there.
Each step was a class exposing a UserControl responsible for the visual aspect of the step, while the logic itself was handled by the class (it was a little more complicated that that, but that was the general idea).
The IWizStep interface, implemented by the step and accepted by the dialog, was on the lines of:
Interface IWizStep
Event StateChanged As EventHandler
ReadOnly Property Control As Control
ReadOnly Property Title As String
ReadOnly Property CanMovePrevious As Boolean
ReadOnly Property CanMoveNext As Boolean
Function MovePrevious As IWizStep
Function MoveNext As IWizStep
End Interface
To put everything together, a controller class would know how to compose the steps necessary for each given action. Therefore I had a controller for, say, "Emit Order", which needed some 10 steps, and a controller for "Emit Orders in Batch", which needed only a couple of steps.
Create a set of UserControls, and add and remove them from a Panel in a single form. (and set Dock to Fill)
You could define a user control which acts as a "wizard". It just needs the buttons you have and an array of content panels, just have it switch through the panels when the buttons are pressed assuming a certain condition is met within the controls on the panel. There's no real definitive "wizard" maker, since it's pretty easy to roll your own wizard.
You don't need to do a "replacement" of your current form really, you could just add a new one to the project. If you do need to for whatever reason, just grab the control collection with Me.Controls, copy that somewhere, and put the new controls up. When you don't need the wizard, swap them out again. It's generally best practice to make a new form however!

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.

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.