Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drag and drop function swift OSX

This is a bit complex but I hope that someone can help me. I am trying to build a drag and drop function for my OSX application.

enter image description here

This is how it is looking at the moment. So there is just a single textfield which the user can drag and drop around the view. It is simple enough with just one textfield but if there are several textfields it is getting complicated and I don't know how to approach. This is what I currently have:

@IBOutlet weak var test: NSTextField!

@IBAction override func mouseDragged(theEvent: NSEvent) {
    NSCursor.closedHandCursor().set()
    var event_location = theEvent.locationInWindow

    test.frame.origin.x = event_location.x - 192
    test.frame.origin.y = event_location.y
}

Test is the name of my NSTextField. I know the name of it so it is simple to move it arround. But if the user adds more textfields (see on the left pane) then I don't know how to address this textfield because I have no name of it (like "test" for the first input).

I am adding the textfields via this code:

    let input = NSTextField(frame: CGRectMake(width, height, 100, 22))
    self.MainView.addSubview(input)

How can I determine which textfield (if there are multiple on the view) was selected and then move the appropriate via drag and drop?

The drag and drop is working for that single static textfield

like image 782
Tom el Safadi Avatar asked May 08 '16 20:05

Tom el Safadi


People also ask

What is drag and drop functionality?

In computer graphical user interfaces, drag and drop is a pointing device gesture in which the user selects a virtual object by "grabbing" it and dragging it to a different location or onto another virtual object.

What is an Nsitemprovider?

An item provider for conveying data or a file between processes during drag-and-drop or copy-and-paste activities, or from a host app to an app extension.


1 Answers

I have prepared a sample app, so consider this:

https://github.com/melifaro-/DraggableNSTextFieldSample

The idea is to introduce SelectableTextField which inherits NSTextField. SelectableTextField provides facility for subscription of interested listener on text field selection event. It has didSelectCallback block variable, where you need to set you handling code. Something like this:

textField.didSelectCallback = { (textField) in
    //this peace of code will be performed once mouse down event
    //was detected on the text field
    self.currentTextField = textField
}

By using mentioned callback mechanism, once text field selected, we can store it in currentTextField variable. So that when mouseDragged function of ViewController is called we are aware of currentTextField and we can handle it appropriatelly. In case of sample app we need adjust currentTextField origin according drag event shift. Hope it became better now.

P.S. NSTextField is opened for inheriting from it, so you can freely use our SelectableTextField everywhere where you use NSTextField, including Interface Builder.

EDIT

I have checked out your sample. Unfortuantly I am not able to commit /create pull request into you repository, so find my suggestion here:

override func viewDidLoad() {
    super.viewDidLoad()

    didButtonSelectCallback = { (button) in

        if let currentButton = self.currentButton {

            currentButton.highlighted = !currentButton.highlighted

            if currentButton == button {
                self.currentButton = nil
            } else {
                self.currentButton = button
            }
        } else {
            self.currentButton = button
        }

        button.highlighted = !button.highlighted
    }

    addButtonAtRandomePlace()
    addButtonAtRandomePlace()

    didButtonSelectCallback(button: addButtonAtRandomePlace())
}

override func mouseDragged(theEvent: NSEvent) {

    guard let button = currentButton else {
        return
    }

    NSCursor.closedHandCursor().set()

    button.frame.origin.x += theEvent.deltaX
    button.frame.origin.y -= theEvent.deltaY
}

private func addButtonAtRandomePlace() -> SelectableButton {

    let viewWidth = self.view.bounds.size.width
    let viewHeight = self.view.bounds.size.height

    let x = CGFloat(rand() % Int32((viewWidth - ButtonWidth)))
    let y = CGFloat(rand() % Int32((viewHeight - ButtonHeight)))

    let button = SelectableButton(frame: CGRectMake(x, y, ButtonWidth, ButtonHeight))
    button.setButtonType(NSButtonType.ToggleButton)
    button.alignment = NSCenterTextAlignment
    button.bezelStyle = NSBezelStyle.RoundedBezelStyle
    button.didSelectCallback = didButtonSelectCallback
    self.view.addSubview(button)

    return button
}
like image 83
Igor B. Avatar answered Oct 23 '22 04:10

Igor B.