Changing editability of NSTextfield and multi line text - swift

I have an NSTextField that is used as either a label or an editable text field depending on whether the application is in edit mode or in view mode.
The code to change the editability of the text field is:
var editable : Bool = false {
didSet {
if editable {
titleTextField?.editable = true
titleTextField?.bezeled = true
titleTextField?.drawsBackground = true
titleTextField?.cell?.usesSingleLineMode = false
titleTextField?.cell?.wraps = true
editButton?.state = NSOnState
} else {
titleTextField?.editable = false
titleTextField?.bezeled = false
titleTextField?.drawsBackground = false
titleTextField?.cell?.usesSingleLineMode = false
titleTextField?.cell?.wraps = true
editButton?.state = NSOffState
}
}
}
#IBAction func editButtonPushed(sender : NSButton) {
if sender.state == NSOnState {
self.editable = true
}else{
self.editable = false
}
}
I've defined the NSTextField in Interface Builder as editable and 'Uses Single Line Mode' is not selected. The text field is in a custom view which is the right view in a NSSplitView. The custom view also contains a button with which the user can toggle the edit mode (it is connected to the action in the above code).
When the title in the text field is long (i.e. more than one line) the title is displayed correctly in the editable text field. When I click the Edit button (turning of Edit mode) the text field is made non-editable (the else statement above).
The problem is that in non-edit mode the NSTextField (and the parent custom view) resizes so that the full title fits into the NSTextField (now a label) on ONE LINE. I want the text field to remain the same size and use two lines to display the title.
How can I prevent the resizing of the text field? I've tried using titleTextField?.cell?.usesSingleLineMode = false and titleTextField?.cell?.wraps = true, but neither solution works.

Related

How to make a NSTextView, that is added programmatically, active?

I am making an app where a user can click anywhere on the window and a NSTextView is added at the mouse location. I have got it working with the below code but I am not able to make it active (in focus) after adding it to the view (parent view). I have to click on the NSTextView to make it active but this is not what I want. I want it to automatically become active when its added to the parent view.
Code in my ViewController to add the NSTextView to its view:
private func addText(at point: NSPoint) {
let textView = MyTextView(frame: NSRect(origin: point, size: CGSize(width: 150.0, height: 40.0)))
view.addSubview(textView)
}
MyTextView class looks like below:
class MyTextView: NSTextView {
override var shouldDrawInsertionPoint: Bool {
true
}
override var canBecomeKeyView: Bool {
true
}
override func viewWillDraw() {
isHorizontallyResizable = true
isVerticallyResizable = true
insertionPointColor = .red
drawsBackground = false
isRichText = false
allowsUndo = true
font = NSFont.systemFont(ofSize: 40.0)
}
}
Also, I want it to lose focus (become inactive) when some other elements (view) are clicked. Right now, once a NSTextView becomes active, it stays active no matter what other elements I click except when I click on an empty space to create yet another NSTextView.
I have gone through the Apple docs multiple times but I think I am missing something. Any help would be much appreciated.
Get the NSWindow instance of the NSViewController's view and call makeFirstResponder passing the text view as parameter.
To lose focus call makeFirstResponder passing nil.

Why does a NSTextField's field editor inherit the text color of it's target field when it's configured otherwise?

My NSTextField's textColor is white and non-editable. When I click on the label, I set the NSTextField to isEditable = true. Performing a second click on the label places it into edit mode. I get a field editor etc.
Prior or editing it looks like this:
I am subclassing my NSTextField to configure that field editor like so:
override func becomeFirstResponder() -> Bool {
let value = super.becomeFirstResponder()
if value == false {
return value
}
if let fieldEditor = currentEditor() as? NSTextView {
fieldEditor.backgroundColor = NSColor.white
fieldEditor.drawsBackground = true
fieldEditor.textColor = NSColor.black
}
return value
}
You can see from the code above I am setting the textColor of the field editor to black. When I enter editing mode I get the expected behavior:
So far so good. Enter the issue: Any new keystrokes are reflected as white text:
In the sample below I have highlighted the contents of the field to show the white text:
So it would seem that even though I am setting the fieldEditor.textColor = NSColor.black and I see that black color, the field editor is inheriting the NSTextField's text color for new input?
If, in my editor configuration I do this, keep in mind this is in a NSTextField subclass:
fieldEditor.backgroundColor = NSColor.white
fieldEditor.drawsBackground = true
fieldEditor.textColor = NSColor.black
textColor = NSColor.black // <-------
Then text input while in editing mode does come though as black. I understand the field editor is a proxy to the NSTextField:
https://developer.apple.com/library/content/documentation/TextFonts/Conceptual/CocoaTextArchitecture/TextEditing/TextEditing.html#//apple_ref/doc/uid/TP40009459-CH3-SW29
So is the flow:
field editor shows
becomes first responder
has some kind of view for the first render
sends keystrokes to the underlying NSTextField
updates itself using the NSTextField settings?

Select next NSTextField with Tab key in Swift

Is there a way to change the responder or select another textfield by pressing tab on the keyboard, in Swift?
Notes:
It's for a fill in the blank type application.
My VC creates a list of Words [Word], and each of those words has its own WordView - word.wordView. The WordView is what is displayed. WordView is a child of NSTextField.
I tried to override keydown but it doesn't allow me to type anything in the text view.
You have to connect your textField nextKeyView to the next textField through the IB or programmatically:
textField1.nextKeyView = textField2
Assuming you want to go from textView1 to textView2. First set the delegate:
self.textView1.delegate = self
Then implement the delegate method:
func textView(textView: NSTextView, doCommandBySelector commandSelector: Selector) -> Bool {
if commandSelector == "insertTab:" && textView == self.textView1 {
self.window.makeFirstResponder(self.textView2)
return true
}
return false
}
If you want some control over how your field tabs or moves with arrow keys between fields in Swift, you can add this to your delegate along with some move meaningful code to do the actual moving like move next by finding the control on the superview visibly displayed below or just to the right of the control and can accept focus.
public func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
switch commandSelector {
case #selector(NSResponder.insertTab(_:)), #selector(NSResponder.moveDown(_:)):
// Move to the next field
Swift.print("Move next")
return true
case #selector(NSResponder.moveUp(_:)):
// Move to the previous field
Swift.print("Move previous")
return true
default:
return false
}
return false // I didn't do anything
}
I had the same or a similar problem, in that I wanted to use an NSTextView field, to allow multiple lines of text to be entered, but it was the sort of field where entering a tab character would make no sense. I found an easy fix for this: NSTextView has an instance property of isFieldEditor, which is set to false by default; simply set this to true, and tabs will now skip to the next field.

Show tagged user names on image using Swift

I want to show tagged user names on image in my iPhone application. When I click on image It needs to show all tagged users. When I click again I need to hide those tags.
I'm using table view cell as media item. Is it possible to use another cell on top of table view cell which I can use to show tags on image?
If there is any better way to proceed with it, please let me konw.
Add button on the image and let a bool variable for this.
Set variable default false.
And check if it false set to true and vice versa.
and take the decision according to bool if it true show all tagged otherwise hide all tagged.
isShow = !isShow
Add Button On Image And make button toggle like
var lblTag: UILabel!
var i=0
let arrTags : NSArray! // Add your tangs in this Array
#IBAction func btnImageTapped(sender : UIButton)
{
if (sender.selected)
{
sender.selected=false
// Display All tags
for(i=0;i<arrTags.count;i++)
{
// set random x , y coordinate
lblTag = UILabel(frame: CGRectMake(CGFloat(i)+1.0,CGFloat(i)+6.0,25,25))
lblTag.tag=i;
lblTemp.text = arrTags.objectAtIndex(i) as? String
self.view.addSubview(lblTag)
}
}
else
{
sender.selected=true
// Hide All Tags
let lblTemp : UILabel!
for(i=0;i<arrTags.count;i++)
{
lblTemp = self.view.viewWithTag(i) as! UILabel
lblTemp.hidden = true
}
}
}

Swift hide just one button on tabbar

I have seen lots of code to hide the whole tabbar. I am using tab bar controller in storyboard.
If I had third and fourth buttons how could I hide just the second but still have 1, 3 and 4 buttons shown?
Well just hide the button itself.
button2.hidden = true
You will need to create an outlet.
#IBOutlet var button2 : UIButton!
And link it to the button in Interface Builder
Ok to hide the button the following can be done. I used this code in a table view to add the editing function and change the title of the button based on the the click. But I modified it for this post just to show that when I clicked on the button again it would make it disappear.
var condition: Bool = true
#IBAction func buttonEdit(sender: UIBarButtonItem) {
if(condition == true) {
tableView.editing = true
sender.title = "Done"
condition = false
} else {
tableView.editing = false
sender.title = "" // This clears the title
sender.enabled = false // This disables the button
sender.image = UIImage() // This would clear the image
condition = true
}
}