简体   繁体   中英

NSTextView, NSFontManager, and changeAttributes()

So I have this app that I'm writing to get familiar with Swift and programming for OSX. It's a note-taking app. The note window consists of an NSTextView and a button that brings up an NSFontPanel.

Changing the font works great. Selecting a size? No problem. Want to change attributes of the font like color, underlining, etc? I'm not at all sure how to get this to work.

Other sources ( here and here , for example) seem to suggest that NSTextView should be the target of NSFontManager and that NSTextView has it's own implementation of changeAttributes(). Making NSTextView the target, however, does nothing. When I select text in NSTextView and bring up the font panel, the first selection I make in the fontPanel results in deselection of the text.

Making my view controller the target for NSFontManager and implementing a stub for changeAttributes yields an object of type NSFontEffectsBox which I am unable to find any good documentation for.

Question is... what am I supposed to do with NSFontEffectsBox? If in the fontPanel I select blue text with double underline, I can see those attributes in the debugger but I'm unable to access them programatically.

Here's the relevant code:

override func viewDidLoad() {
    super.viewDidLoad()
    loadNoteIntoInterface()
    noteBody.keyDelegate = self  // noteBody is the NSTextView
    noteBody.delegate = self
    noteBody.usesFontPanel = true
    fontManager = NSFontManager.sharedFontManager()
    fontManager!.target = self
}

Code for changing the font. This works just fine.

override func changeFont(sender: AnyObject?) {
    let fm = sender as! NSFontManager
    if noteBody.selectedRange().length>0 {
        let theFont = fm.convertFont((noteBody.textStorage?.font)!)
        noteBody.textStorage?.setAttributes([NSFontAttributeName: theFont], range: noteBody.selectedRange())
    }
}

Stub code for changeAttributes:

func changeAttributes(sender: AnyObject) {
    print(sender)
}

So.. my goals are two:

  1. Understand what's going on here
  2. have any changes I make in the fontPanel be reflected in the NSTextView selected text.

Thank you.

So I did manage to find an answer of sorts. Here's how I implemented changeAttributes() in my program:

func changeAttributes(sender: AnyObject) {
    var newAttributes = sender.convertAttributes([String : AnyObject]())
    newAttributes["NSForegroundColorAttributeName"] = newAttributes["NSColor"]
    newAttributes["NSUnderlineStyleAttributeName"] = newAttributes["NSUnderline"]
    newAttributes["NSStrikethroughStyleAttributeName"] = newAttributes["NSStrikethrough"]
    newAttributes["NSUnderlineColorAttributeName"] = newAttributes["NSUnderlineColor"]
    newAttributes["NSStrikethroughColorAttributeName"] = newAttributes["NSStrikethroughColor"]

    print(newAttributes)

    if noteBody.selectedRange().length>0 {
        noteBody.textStorage?.addAttributes(newAttributes, range: noteBody.selectedRange())
    }
}

Calling convertAttributes() on sender returns an attribute array, but the names don't seem to be what NSAttributedString is looking for. So I just copy them from old name to new and send them on. This is a good start, but I will probably remove the old keys before adding the attributes.

The question remains, tho.. is this the right way to do things?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM