Проблема с перемещением NSTextView и mouse down


#1

Добрый день!
В проекте добавляю кастомный NSTextField в NSView, чтобы затем можно было текст перемещать/вращать/редактировать . Все хорошо за исключением того что возможности для редактирования ограничены. Понятно что в NSTextView опций для редактирования текста намного больше. Попробовал использовать NSTextView вместо NSTextField. Возникла новая проблема с NSTextView. Если в случае NSTextField работала следующая схема перемещение - mouse down, проверка если mouse point внутри frame от NSTextField который собираемся перетаскивать - при это меняется вид курсора - то далее при mouse drag перетаскиваем этот NSTextField в нужное место. С NSTextView это схема перестала работать на условии проверки если mouse point внутри frame от NSTextView - вид курсора не меняется. Если это условие убираю NSTextView перемещается. Но это условие необходимо, иначе все NSTextViews будут перемещаться.

Не понимаю в чем причина. Могу только предполагать что собака зарыта в том что NSTextView находится by default внутри NSScrollView.

Посоветуйте пожалуйста как решить проблему !!!

NSTextView добавляю программно следующим образом

    let textView = ResizingNSTextView()
    let sizeOfText =  "Test text".size(withAttributes: attributesForText)
    textView.frame.size = NSMakeSize(sizeOfText.width, sizeOfText.height)
    textView.frame.origin = NSPoint(x: canvasView.frame.width / 2.0 - (sizeOfText.width / 2.0) , y: canvasView.frame.height / 2.0)
    textView.backgroundColor = NSColor.white
    textView.textStorage?.append(NSAttributedString(string: "Test text"))
    textView.isEditable = false
    textView.isSelectable = false

    canvasView.addSubview(textView)

 class ResizingNSTextView: NSTextView
{

     override  func didChangeText()
    {
         super .didChangeText()
        let contentRect = self .textContainer?.layoutManager?.usedRect(for: self.textContainer!)
        self .frame.size = NSMakeSize( self.frame.size.width, contentRect!.size.height)
    }
}

#2

Ситуация странная. NSTextView на которую нажимаем мышкой исходно добавляется как isEditable = false и isSelectable = false. В кастомном NSView, содержащем этот NSTextView, в функциях mouseDown (левая кнопка) и rightMouseDown (правая) прописал идентичный код. В том случае когда нажимаем правой кнопкой условие для проверки mouse point внутри frame от NSTextView выполняется, но в случае нажатия левой для mouseDown это же условие не выполняется.

Что за бред ?


#3

Для кастомного NSTextView надо немного по другому делать.

import Cocoa

class CustomTextView: NSView {

    var textView: NSTextView!

    lazy var textStorage: NSTextStorage = {
        return NSTextStorage(attributedString: NSAttributedString(string: ""))
    }()

    private func addCustomTextView() {
        let layoutManager = NSLayoutManager()
        textStorage.addLayoutManager(layoutManager)
        let rect = CGRect(x: 0, y: 0, width: 200, height: 40)
        let textContainer = NSTextContainer(containerSize: rect.size)

        textContainer.widthTracksTextView = true
        textContainer.heightTracksTextView = true
    
        textView = NSTextView(frame: rect, textContainer: textContainer)
        addSubview(textView)
    
        layoutManager.addTextContainer(textContainer)
    
        textView.isEditable = true
        textView.isSelectable = true
        textView.toggleRuler(nil)
        textView.usesRuler = true
        textView.isRulerVisible = true
        textView.importsGraphics = true
        textView.allowsImageEditing = true
        textView.usesFontPanel = true
        textView.isRichText = true
        textView.usesInspectorBar = true
        textView.allowsUndo = true
    
        let font = NSFont(name: "Arial", size: 12) ?? NSFont.systemFont(ofSize: 12)
        textView.font = font
    }

}

#4

Спасибо.
Возможно я не очень точно сформулировал проблему или не понял что вы предлагаете.

В проекте есть кастомный NSView. Его кастомизация связана с тем что добавляемые к нему много subviews - NSImageViews и NSTextViews можно было бы перемещать/вращать по этому NSView и в случае NSTextViews еще и редактировать текст. Все это с использованием команд mouseDown (Up, Draged) для левой и правой кнопки мыши.

Чтобы добавляемые NSTextViews при редактировании текста менялись по высоте в зависимости от размера текста делаем каждый добавляемый NSTextView кастомным (выше код для этого).

Для перемещения какого то NSTextView из многих добавленных мы используем сначала детекцию на условие если mouseDown point внутри frame этого NSTextView, т.е. проверяем для каждого NSTextView из массива в который добавляем каждый новый NSTextView добавленный в NSView.

Теперь проблема возникла в том что если такая проверка происходит для правой кнопки - когда rightMouseDown - все хорошо, следующее условие проверяется и далее код исполняется.

override func rightMouseDown(with event: NSEvent)
{
       for each in arrayOfNSTextViews
      {
             if arrayOfNSTextViews.frame.contains(mouseDownPointRight) == true
            {
            	NSCursor.closedHand.set()
                    ....
            }
      }
}

Но если для идентичного кода проверяем в методе mouseDown(with event: NSEvent) , для левой кнопки, это же условие не проверяется, курсор не меняет вид и дальше код не исполняется.

Почему ?


#5

Запостил тот же вопрос на stack overflow с кодом для простого тест проекта -

Попробуйте пожалуйста кто-нибудь, чтобы хотя бы подтвердить или опровергнуть тот же странный результат.