Cocoaからのライブ変換(LiveConversion)の変更と監視その2

進捗があった。非公開プロトコルを適応することで、ライブ変換を制御できる。

変更と監視は出来ない。TextFieldに入力中にライブ変換を一時的に無効にすることができるだけ。

プロトコルNSTextInputClient_IncrementalSearch

NTextViewのサブクラスで、NSTextInputClient_IncrementalSearchに適合しているクラスではライブ変換は無効になる。

ヘッダは以下のようになっている。

@class NSEvent;

@protocol NSTextInputClient_IncrementalSearch
- (BOOL)wouldHandleEvent:(NSEvent *)arg1;
- (unsigned long long)incrementalSearchClientGeometry;
@end

メソッドそれぞれの詳細は不明だが、wouldHandleEventではfalseを返し、incrementalSearchClientGeometryでは0を返すことで動作した。

incrementalSearchClientGeometryで0以外の場合は、変換候補のWindowが表示されなかった。

field editor

NSWindow上にNSTextFieldを複数配置した場合を考えます。この時、Textの編集が出来るNSTextFieldは常に、その内のどれか一つです。その他のNSTextFieldは、表示されているだけです。

この特徴を特性を利用して、Cocoaフレームワークでは、NSTextFieldは表示だけを行い、編集するときは同じ場所で別のオブジェクト(NSTextView)に任せるという方式を採用しています。

この別のオブジェクトは、NSWindow上のNSTextFieldで共有されており、それをField Editorと呼びます。

昔々のNextStepの時代では、CPUのパワーは今よりも貴重でした。Cocoaフレームワークには、その時代の設計の名残があります。field editorもその名残です。

このことは、先ほどのライブ変換を制御と関係があります。ライブ変換を制御するには、NSTextFieldのサブクラスだけではなくて、NSTextInputClient_IncrementalSearchに適応したNSTextViewのサブクラスを作る必要があるのです。

さらには、上記の text field を挿げ替えて、特定のTextFieldの時だけ、こちらが指定した custom field editor を使用するように指示する必要があります。

この仕組みは、以下のようになります。

class WindowController: NSWindowController, NSWindowDelegate
{
        .
        .
        .
    @objc dynamic var custumFieldEditor: MINTLIncrementalSearchFieldEditor? = nil

    public func windowWillReturnFieldEditor(_ sender: NSWindow, to client: Any?) -> Any?
    {
        // カスタムのfieldEditorを使う
        if client is MINTLIncrementalSearchField?
        {
            if self.custumFieldEditor == nil
            {
                self.custumFieldEditor = MINTLIncrementalSearchFieldEditor()
                self.custumFieldEditor!.isFieldEditor = true
            }

            return self.custumFieldEditor
        }

        // デフォルトのfieldEditorを使う
        return nil
    }
        .
        .
        .
}

サンプルコードと感想

多分、誰の役にも立たない。

BUKURO.swift 2017-11の資料です。 https://cocoa-kanto.connpass.com/event/68404/

IncrementalSearchField.zip