最小限データーベースその3¶
コピペとDrag&Dropのデータタイプを増やす。
今までは、自分自身が作成した、データタイプ "com.mindto01s.M3XNote" しかコピペもDrag&Dropも出来なかった。
そのため、newコマンドで項目ノートを作成してから、TextViewへデータをペーストしていた。
これを、Pasteboard に、以下のデータタイプがある場合は、ペーストコマンドで自動で項目ノートの作成とそのノートへのペーストを一手間でできるようにした。
Dropの受け入れ¶
[M3XViewController viewDidLoad] で [M3XNote pasteBoardRowsType]を[M3XNote pasteBoardRowsTypes]とするだけ。
[self.browserView registerForDraggedTypes:[M3XNote pasteBoardRowsTypes]];
[M3XNote pasteBoardRowsTypes]の方では、以下のように受け入れ可能なUTIを列挙している。
+ (NSArray<NSString*>*) pasteBoardRowsTypes
{
return @[
[self pasteBoardRowsType],
NSPasteboardTypeRTFD,
NSPasteboardTypeRTF,
NSPasteboardTypeString,
NSPasteboardTypePNG, // <-- 入力のみ
NSPasteboardTypeTIFF, // <-- 入力のみ
];
}
この変更だけで、Dropはは可能になる。もちろんDropした後のコードは何も書いていないので、Dropした瞬間に落ちるはず。
ペーストボードへの書き込み¶
この変更は、[M3XNote wreiteToPasteboard:]の中だけ。
ペーストボードには複数のデータタイプを入れられるので、今までのコードの末尾に、書き出したいデータのコードを書き足すだけ。
- (void) wreiteToPasteboard:(NSPasteboard*)pasteboard
{
.
.
.
// 以下から書き足したコード
NSAttributedString* theAttributedString = [[NSAttributedString alloc] initWithRTFD:self.memo documentAttributes:nil];
[pasteboard setData:[theAttributedString RTFDFromRange:NSMakeRange(0, theAttributedString.length)
documentAttributes:@{}]
forType:NSPasteboardTypeRTFD];
[pasteboard setData:[theAttributedString RTFFromRange:NSMakeRange(0, theAttributedString.length)
documentAttributes:@{}]
forType:NSPasteboardTypeRTF];
[pasteboard setString:theAttributedString.string
forType:NSPasteboardTypeString];
}
ペーストボードに対してsetData:forTypeなどで書き出している。
ここまでのコードを書くと、このアプリの項目ノートを他のテキストエディターなどペースト出来るようになる。
ペーストボードからの読み出し¶
読み出しのコードはかなり汚い。
上から順番に、欲しいデータが存在したら処理をしている。独自データが最優先で、次にRTFDなどの文字列系が続き、最後は画像データの順番になっている。
RTFDなどの文字列系は以下のように単純に、NSData型に変換してCoreDataに入れているだけ。
+ (instancetype) readFromPasteboard:(NSPasteboard*)pasteboard
inManagedObjectContext:(NSManagedObjectContext *)context
{
M3XNote* theResult = nil;
.
.
.
// RTFD
NSData* theRTFD = [pasteboard dataForType:NSPasteboardTypeRTFD];
if( theRTFD != nil )
{
theResult = [NSEntityDescription insertNewObjectForEntityForName:@"M3XNote"
inManagedObjectContext:context];
theResult.memo = theRTFD;
theResult.isHome = NO;
return theResult;
}
.
.
.
}
最後の画像系のデータだけ少しだけ複雑なことを行なっている。
NSTextViewはRTFDのデータを表示する機能はあるが、NSImageViewのように直接Imageを設定はできない。 そのため、NSTextAttachmentを使用して、画像を貼り付ける形になる。
+ (instancetype) readFromPasteboard:(NSPasteboard*)pasteboard
inManagedObjectContext:(NSManagedObjectContext *)context
{
M3XNote* theResult = nil;
.
.
.
// PNG or TIFF
NSData* theImageData;
theImageData = [pasteboard dataForType:NSPasteboardTypePNG];
if( theImageData == nil )
{
theImageData = [pasteboard dataForType:NSPasteboardTypeTIFF];
}
if( theImageData != nil )
{
theResult = [NSEntityDescription insertNewObjectForEntityForName:@"M3XNote"
inManagedObjectContext:context];
NSDateFormatter* theDateFormatter = [[NSDateFormatter alloc] init];
[theDateFormatter setDateFormat:@"yy/MM/dd H:mm:ss"];
NSString* theMemoString = [NSString stringWithFormat:@"画像 : %@\n", [theDateFormatter stringFromDate:[NSDate date]]];
NSMutableAttributedString* theAttributedString = [[NSMutableAttributedString alloc] initWithString:theMemoString];
NSTextAttachment* theAttachment = [[NSTextAttachment alloc] init];
theAttachment.image = [[NSImage alloc] initWithData:theImageData];
NSAttributedString* theAttatchText = [NSAttributedString attributedStringWithAttachment:theAttachment];
[theAttributedString appendAttributedString:theAttatchText];
theResult.memo = [theAttributedString RTFDFromRange:NSMakeRange(0, theAttributedString.length)
documentAttributes:@{}];
theResult.isHome = NO;
return theResult;
}
.
.
.
}
ここまで出来れば、他のアプリからこのアプリへコピー&ペーストが出来るようになる。
今後の課題¶
実装していないものとして、URLとhtmlのデータタイプがある。これがないために、SafariからURLのDrag&Dropで項目ノートを作成することは出来ない。
これは、現在のアプリのデータ構造の持ち方では、サーバーからデータを取得する時に、メインスレッドをブロックする必要がありそうなので、実装しなかった。
同じく、ファイルDropも実装しなかった。画像ファイルやRTFDファイルをDrop可能にしようかとも考えたが、サイズの大きいデータを考慮していない設計なのでこれも実装しなかった。
今回はここまで。多分続きはなし。( microMemex3.zip
)
なんか、code-blockが上手く働いてくれないなぁ。でも、眠いから寝る。
Comments
comments powered by Disqus