NSOutlineView drag line stuck + blue border

筅森魡賤 提交于 2021-02-10 04:54:09

问题


I'd like a correct behaviour from the blue drag bar, and no blue rect when dragging.

Do you know where is my mistake ?

(as you can see, the blue bar is stuck in top, like in this topic : Little circle-line bar stuck at top of NSOutlineView when rearranging using drag and drop)

import Cocoa

class ViewController: NSViewController, NSOutlineViewDataSource, NSOutlineViewDelegate, NSPasteboardItemDataProvider {

    @IBOutlet weak var outlineView: NSOutlineView!

    let REORDER_PASTEBOARD_TYPE = "com.test.calques.item"

    override func viewDidLoad() {
        super.viewDidLoad()

        //Register for the dropped object types we can accept.
        outlineView.register(forDraggedTypes: [REORDER_PASTEBOARD_TYPE])

        //Disable dragging items from our view to other applications.
        outlineView.setDraggingSourceOperationMask(NSDragOperation(), forLocal: false)

        //Enable dragging items within and into our view.
        outlineView.setDraggingSourceOperationMask(NSDragOperation.every, forLocal: true)

        outlineView.delegate = self;
        outlineView.dataSource = self;
    }

    override var representedObject: Any? {
        didSet {
            // Update the view, if already loaded.
        }
    }

    var items: [(String, NSColor)] = [
        ("Item 1",  NSColor.black),
        ("Item 2",  NSColor.red),
        ("Item 3",  NSColor.red),
        ("Item 4",  NSColor.red),
        ("Item 5",  NSColor.red),
        ("Item 6",  NSColor.red)];

    //NSOutlineViewDataSource
    func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
        return items.count;
    }

    func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
        return false
    }

    func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
        return items[index];
    }

    func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
        let image: NSImage = NSImage(size: NSSize(width: 17, height: 17));
        let calquesItem: (String, NSColor) = item as! (String, NSColor);
        let path = NSBezierPath(ovalIn: CGRect(x: 2, y: 2, width: 17 - 4, height: 17 - 4));

        image.lockFocus();
        calquesItem.1.setFill();
        path.fill();
        image.unlockFocus();

        let cell = outlineView.make(withIdentifier: "DataCell", owner: nil) as! NSTableCellView;
        cell.textField!.stringValue = calquesItem.0;
        cell.imageView!.image = image;

        return cell;
    }

    //Drag - NSOutlineViewDataSource
    var fromIndex: Int? = nil;

    func outlineView(_ outlineView: NSOutlineView, pasteboardWriterForItem item: Any) -> NSPasteboardWriting? {
        let pastBoardItem: NSPasteboardItem = NSPasteboardItem();

        pastBoardItem.setDataProvider(self, forTypes: [REORDER_PASTEBOARD_TYPE]);

        return pastBoardItem;
    }

    func outlineView(_ outlineView: NSOutlineView, draggingSession session: NSDraggingSession, willBeginAt screenPoint: NSPoint, forItems draggedItems: [Any]) {

        Swift.print("willBeginAt")

        let item = draggedItems[0] as! (String, NSColor);

        fromIndex = items.index(where: { (_item: (String, NSColor)) -> Bool in
            return _item.0 == item.0
        });

        session.draggingPasteboard.setData(Data(), forType: REORDER_PASTEBOARD_TYPE)
    }

    func outlineView(_ outlineView: NSOutlineView, acceptDrop info: NSDraggingInfo, item: Any?, childIndex index: Int) -> Bool {
        Swift.print("acceptDrop")

        if(fromIndex! != index && index != -1) {
            let toIndex: Int = fromIndex! < index ? index - 1 : index;

            outlineView.moveItem(at: fromIndex!, inParent: nil, to: toIndex, inParent: nil);

            items.insert(items.remove(at: fromIndex!), at: toIndex);

            return true;
        }

        return false;
    }

    func outlineView(_ outlineView: NSOutlineView, validateDrop info: NSDraggingInfo, proposedItem item: Any?, proposedChildIndex index: Int) -> NSDragOperation {
        if(item == nil) {
            return NSDragOperation.generic;
        }

        return [];
    }

    func outlineView(_ outlineView: NSOutlineView, draggingSession session: NSDraggingSession, endedAt screenPoint: NSPoint, operation: NSDragOperation) {
        Swift.print("Drag session ended")
        fromIndex = nil;
    }

    //NSPasteboardItemDataProvider
    func pasteboard(_ pasteboard: NSPasteboard?, item: NSPasteboardItem, provideDataForType type: String)
    {
        item.setString("Outline Pasteboard Item", forType: type)
    }

}

回答1:


From https://developer.apple.com/reference/appkit/nsoutlineview :

Each item in the outline view must be unique. In order for the collapsed state to remain consistent between reloads the item's pointer must remain the same and the item must maintain isEqual(_:) sameness.

I was using Tuples (String, NSColor). And Tuples don't conform to the hashable protocol !

After switching from Tuples items to MyClass items, everything works fine ! (correct behaviour from the blue drag bar, and no blue rect when dragging)

class MyClass {
    var name: String!
    var color: NSColor!

    init(_ _name: String, _ _color: NSColor) {
        name = _name
        color = _color
    }
}


来源:https://stackoverflow.com/questions/40471704/nsoutlineview-drag-line-stuck-blue-border

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!