Updating an NSTextField while controlling an NSTableView [duplicate] - swift

What's the easiest way to have an NSTextField with a "recommendation list" dynamically shown below it as the user types? Just like Safari's address bar that has a menu of some sorts (I'm pretty confident Safari's address bar suggestions is menu since it has rounded corners, blue gradient selection, and background blurring).
I've tried using NSTextView's autocompletion facility but found it was inadequate:
It tries to complete words instead of the whole text fields – in other words, selecting an autocomplete suggestion will only replace the current word.
It nudges the autocompletion list forward and align it with the insertion point instead of keeping it align with the text field.
In the sample screenshot above whenever I selected the autocomplete suggestion the text field only replaces K with the suggested item in the list, which results in Abadi Abadi Kurniawan.
These are what I'd like to achieve:
Whenever a suggestion is selected, the entire text field is replaced with the suggestion.
Keep the suggestion list aligned with the text field's left side.
Note: This is not a question about adding progress indicator behind a text field.

The Safari address bar uses a separate window. Apple has example project CustomMenus and it only takes an hour or two to customize it.
Developer session explaining what has to be done Key Event Handling in Cocoa Applications
If you want to be able to select multiple words you need to provide own FieldEditor (credits should go for someone else)
- (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(nullable id)client;
{
if ([client isKindOfClass:[NSSearchField class]])
{
if (!_mlFieldEditor)
{
_mlFieldEditor = [[MLFieldEditor alloc] init];
[_mlFieldEditor setFieldEditor:YES];
}
return _mlFieldEditor;
}
return nil;
}
- (void)insertCompletion:(NSString *)word forPartialWordRange:(NSRange)charRange movement:(NSInteger)movement isFinal:(BOOL)flag
{
// suppress completion if user types a space
if (movement == NSRightTextMovement) return;
// show full replacements
if (charRange.location != 0) {
charRange.length += charRange.location;
charRange.location = 0;
}
[super insertCompletion:word forPartialWordRange:charRange movement:movement isFinal:flag];
if (movement == NSReturnTextMovement)
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"MLSearchFieldAutocompleted" object:self userInfo:nil];
}
}

This only addresses half of your answer, but I believe you need to subclass NSTextView and implement the - (NSRange)rangeForUserCompletion method, returning the range of the entire string in the text field. This should make sure that it doesn't just autocomplete the most recently entered word.
If you want a custom menu, you're going to have to do that yourself, probably by implementing the -controlTextDidChange: method and displaying a custom view with a table when appropriate.

Related

XCUITest - neither element nor descendant has keyboard focus

I am testing adding a comment to my app, on my other UI tests I have used the typeText function and everything works perfectly fine. I have also clicked to make Connect hardware keyboard' is off. The app terminates testing and shows the error UI Testing Failure - Neither element nor any descendant has keyboard focus during the addComment method. Any ideas?
func testAddComment() {
let featuredPage = self.app.tabBars["Featured"]
if featuredPage.exists {
featuredPage.tap()
}
sleep(2)
let featuredOffer = self.app.tables.cells.elementBoundByIndex(1)
if featuredOffer.exists {
featuredOffer.tap()
}
sleep(2)
let addComment = self.app.staticTexts["Add a comment"]
if addComment.exists {
addComment.tap()
addComment.typeText("Test comment")
}
sleep(2)
let postComment = self.app.buttons["Send"]
if postComment.exists {
postComment.tap()
}
sleep(2)
}
Likely cause:
An extremely common cause of this symptom is to have enabled a parent view of the field in question as an accessibility element. Ensure that none of the parents of the field are enabled as accessibility elements, and the problem is likely to be resolved.
Explanation
This error message can be particularly confusing when you can see that a previous step in the XCUITest has correctly activated a text field or similar as the first responder, the keyboard has appeared, and functionally the field has keyboard focus.
Essentially, the error message is slightly misleading as the tendency is to focus on the keyboard focus part and think that it is telling you that nothing has keyboard focus. Instead, what the message is telling you is that none of the accessibility elements that XCUITest can access have the keyboard focus. And so it can't direct text to the field in question.
Accessibility elements cannot have children that are also accessibility elements. Therefore, if you place a number of fields inside a view, but then mark that parent view as being an accessibility element, all of the field as its subviews become invisible to the accessibility frameworks. You can see and verify this is what is happening using the Accessibility Inspector app on the Mac alongside the simulator: the fields you are trying to target will not be selectable, and instead there will be a parent view that is.
I found the way around this best was to use menuItem and to paste what I wanted to the textField . This was a strange problem as both textField and staticText both didn't allow the test to run functionally. This is an issue I have reported to apple.
Here is my fix
let addComment = self.app.staticTexts["Add a comment"]
if addComment.exists {
addComment.tap()
UIPasteboard.generalPasteboard().string = "Test Comment"
let commentTextField = self.app.staticTexts["Add a comment"]
commentTextField.pressForDuration(1.1)
sleep(1)
app.menuItems.elementBoundByIndex(2).tap()
}
You can only use .typeText() on an input element. Static texts are not input elements - they're just text. Your addComment constant is probably the placeholder text within your text field. Tapping on the placeholder text probably activates the text field and keyboard, but you cannot call .typeText() on the placeholder text as the text field is its parent, not its descendant.
You need to call .typeText() on your text field, which should have focus after you tap in it.
let addComment = self.app.textFields["addCommentIdentifier"]
if addComment.exists {
addComment.tap()
addComment.typeText("Test comment")
}
You can try solving this issue by using .doubletap() before you & enter the value in .typeText(string) it worked for me.
let addComment = self.app.staticTexts["Add a comment"]
if addComment.exists {
addComment.doubleTap()
addComment.typeText("Test comment")
Turn off I/O -> Keyboard -> Connect Hardware Keyboard in the Simulator menu.
When this option is on, the Simulator doesn't bring up the soft keyboard, so the OS (sometimes) thinks the text field is not focused. Most of my tests have no problem typing in text fields with this option on, but some fail, especially search bars.

How to remove/disable On-Keyboard Textbox when Using UIInput NGUI?

I am using NGUI's UIInput class to accept text input from user. when i start typing in text box in mobile devices. a key board appears and it has an another textbox within it self, with "OK"/"Done" button (Like a keyboard accessory view, if we're talking about iPhone).
Can i disable that text box appearing within keyboard ? Or its not even possible and i am shooting just blanks ?
From what i could gather by search for a while is, the appearance of keyboard is handled buy Unity's "TouchScreenKeyboard" class. but according to Unity Scripting reference there is nothing which could hide the textfield inside the keyboard.
Unity Scripting reference: TouchInputKeyboard
PS:- I should still be able to put input in textbox by directly typing into them, i just want an extra textbox within the key board to be removed.
TO be more clear i have attached images explaining this
This is the screen.
When i start typing in one of the textbox. a keyboard appears like the following.
as you can see the text box just above the keyboard is not the original one.
Did you try checking "Hide Input Check box" in Inspector view of that UIInput Textbox ?
private void OnGUI()
{
TouchScreenKeyboard.hideInput=true;
}
I don't know why it is, but I have had this problem as well and the "hide input" checkbox for some reason doesn't seem to do really anything other then change the keyboard text box from one line to multi line.
I did a little bit of digging and came across a quick lead that will enable that hide input check box.
This fix is Update() in UIInput.cs around 650
else if (inputType == InputType.Password)
{
TouchScreenKeyboard.hideInput = true;
kt = TouchScreenKeyboardType.Default;
val = mValue;
mSelectionStart = mSelectionEnd;
}
else
{
if(hideInput)
{
TouchScreenKeyboard.hideInput = true;
}
else
{
TouchScreenKeyboard.hideInput = false;
}
kt = (TouchScreenKeyboardType)((int)keyboardType);
val = mValue;
mSelectionStart = mSelectionEnd;
}
I added a check in the else statement

How i can fetch what is typed between 2 UITextViews on iphone?

i have two UITextView items, how can i fetch what is written using a button on iphone?
Imagine something like a translate app, the user enters a word in UITextView 1 and by pressing the button the UITextView 2 is getting filled with data.
UITextView has a property text. Simply use this.
Set up IBOutlets for textView1 and textView2. Then have the button do something along these lines:
-(IBAction)moveTextOver:(id)sender {
[textView2 setText:textView1.text];
}
To get fancier, you can have a method -(NSString *)transformText:(NSString *)text that translates or does whatever you like. Then use
-(IBAction)moveTextOver:(id)sender {
[textView2 setText:[self transformText:textView1.text]];
}
Create an IBAction method that is linked to a button and in that method read the "text" property of the textView or textField, do your calculations on it and assign the results to the text property of thee second field.

Can I not remove the return key on the keyboard? Or at least change its text to "Set"?

I am creating a sign up page for my iphone app and am having some problems making the way the input views work for the different kinds of fields consistent. The fields are listed as cells in a table view and the editing is supposed to take place directly in the table by having appropriate input views sliding up from the bottom.
Let me focus on only two of the fields here, namely the username field and the birthday field: for the username field it makes sense to have an ASCII capable keyboard sliding up when the user presses the field whereas a date picker seems more useful in the birthday field case.
For both the keyboard and the date picker the cancel button could be located in a tool bar just above the input view. But what about the set button? If I put that in the toolbar as well I need the return key in the keyboard to go away! But that is not possible is it?
If the return key cannot be removed then I might have to live with the set button in the toolbar only in the birthday case and then use the return key as the set button in the username case - but can I then at least change the text on the return key to "Set"?
No it's not possible* to hide the "Return" key.
It is not possible to set the string to "Set" either, but could use the .returnKeyType property to change it to a limited set of strings.
theTextField.returnKeyType = UIReturnKeyDone;
(* Well you could put an opaque UIView directly above it but it's a very bad practice and generally breaks if the user chooses a different input method)

Drawing the UIPicker values from multiple components?

I have the UIPicker setup with multiple components and a button below it. Depending on what the user has chosen with the UIPicker determines which new view will be loaded but I am having trouble determining how to extrapolate the information from the picker itself. Right now I have this method being called when the button is pressed:
- (IBAction) buttonPressed {
if (component:1 == 1 && component:2 == 1) {
//Load the view number 1.
} else if (component:1 == 2 && component:2 == 1) {
//Load the view number 2.
} else {
//Load the view number 3.
}
}
I obviously know that my code is wrong but I hope it gets the point across. I have multiple components and I need to figure out how to use the information that the user is scrolling to on the picker to determine which view to move to. (I know how to load the views, I just commented those in the code to illuminate the problem areas better.)
How do I go about using the pickerViews to extrapolate the information IN the buttonPressed IBAction method?
To respond directly to picker manipulation, use the delegate's pickerView:didSelectRow:inComponent:.
To obtain the view corresponding to user selection, use viewForRow:forComponent:. From that view you can obtain information about what it displays (if it's a UILabel, inspect its text property).
Also, you can obtain this information directly from the data source, referring to the piece of information you would return in the delegate's pickerView:titleForRow:forComponent: or pickerView:viewForRow:forComponent:reusingView:, for the currently selected row and component.