• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

BathyScapheで画像のインラインプレビューを可能にするプラグイン


Commit MetaInfo

Revisionbaecdb0a8f194e13b23cda570e63a2209aa306cc (tree)
Time2012-05-18 01:42:45
Authormasakih <masakih@user...>
Commitermasakih

Log Message

[New] 自動読み込み

Change Summary

Incremental Difference

--- /dev/null
+++ b/BSInlinePreviewerEx-Info.plist
@@ -0,0 +1,28 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+<plist version="1.0">
4+<dict>
5+ <key>CFBundleDevelopmentRegion</key>
6+ <string>English</string>
7+ <key>CFBundleExecutable</key>
8+ <string>${EXECUTABLE_NAME}</string>
9+ <key>CFBundleIconFile</key>
10+ <string></string>
11+ <key>CFBundleIdentifier</key>
12+ <string>com.masakih.BSInlinePreviewerEx</string>
13+ <key>CFBundleInfoDictionaryVersion</key>
14+ <string>6.0</string>
15+ <key>CFBundleName</key>
16+ <string>${PRODUCT_NAME}</string>
17+ <key>CFBundlePackageType</key>
18+ <string>BNDL</string>
19+ <key>CFBundleShortVersionString</key>
20+ <string>1.0b</string>
21+ <key>CFBundleSignature</key>
22+ <string>????</string>
23+ <key>CFBundleVersion</key>
24+ <string>1.0b</string>
25+ <key>NSPrincipalClass</key>
26+ <string>BSInlinePreviewerEx</string>
27+</dict>
28+</plist>
--- /dev/null
+++ b/BSInlinePreviewerEx.h
@@ -0,0 +1,15 @@
1+//
2+// BSInlinePreviewerEx.h
3+// BSInlinePreviewer
4+//
5+// Created by 堀 昌樹 on 12/05/17.
6+// Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
7+//
8+
9+#import "BSInlinePreviewer.h"
10+
11+@interface BSInlinePreviewerEx : BSInlinePreviewer
12+{
13+ NSMutableDictionary *tasking;
14+}
15+@end
--- /dev/null
+++ b/BSInlinePreviewerEx.m
@@ -0,0 +1,143 @@
1+//
2+// BSInlinePreviewerEx.m
3+// BSInlinePreviewer
4+//
5+// Created by 堀 昌樹 on 12/05/17.
6+// Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
7+//
8+
9+#import "BSInlinePreviewerEx.h"
10+
11+NSString *const CMRThreadViewerDidChangeThreadNotification = @"CMRThreadViewerDidChangeThreadNotification";
12+
13+static NSString *const BSInlinePreviewerPreviewed = @"BSInlinePreviewerPreviewed";
14+
15+
16+@interface BSInlinePreviewer(Private)
17+- (NSRange)linkRange;
18+- (NSImage *)downloadImageURL:(NSURL *)imageURL;
19+- (NSAttributedString *)attachmentAttributedStringWithImage:(NSImage *)image;
20+- (NSImage *)notFoundImage;
21+- (NSImage *)fitImage:(NSImage *)image toSize:(NSSize)targetSize;
22+
23+- (void)showProgressPanel;
24+- (void)closeProgressPanel;
25+@end
26+
27+
28+@implementation BSInlinePreviewerEx
29+// Designated Initializer
30+- (id)initWithPreferences:(AppDefaults *)prefs
31+{
32+ self = [super initWithPreferences:prefs];
33+ if(self) {
34+ tasking = [[NSMutableDictionary alloc] init];
35+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
36+ [nc addObserver:self
37+ selector:@selector(viewerDidEndFinishing:)
38+ name:CMRThreadViewerDidChangeThreadNotification
39+ object:nil];
40+ }
41+
42+ return self;
43+}
44+
45+- (id)keyOfObject:(id)obj
46+{
47+ return [NSString stringWithFormat:@"%p", obj];
48+}
49+- (void)insertImage:(NSDictionary *)attr
50+{
51+ NSTextView *tv = [attr objectForKey:@"View"];
52+ NSRange range = NSRangeFromString([attr objectForKey:@"Range"]);
53+ id newInsertion = [attr objectForKey:@"Image"];
54+ NSUInteger offset = [[attr objectForKey:@"Offset"] unsignedIntegerValue];
55+ range.location += offset;
56+
57+ NSTextStorage *ts = [tv textStorage];
58+ [ts beginEditing];
59+ {
60+ [ts addAttribute:BSInlinePreviewerPreviewed
61+ value:[NSNumber numberWithBool:YES]
62+ range:range];
63+
64+ [ts insertAttributedString:newInsertion atIndex:range.location];
65+ }
66+ [ts endEditing];
67+}
68+- (void)viewerDidEndFinishing:(id)no
69+{
70+ NSLog(@"CMRThreadViewerDidChangeThreadNotification %@", no);
71+ id threadViewer = [no object];
72+ NSTextView *tv = [[threadViewer textView] retain];
73+ @synchronized(tasking) {
74+ id check = [tasking objectForKey:[self keyOfObject:tv]];
75+ if(check) return;
76+ [tasking setObject:tv forKey:[self keyOfObject:tv]];
77+ }
78+
79+ dispatch_async(dispatch_get_global_queue(0,0), ^{
80+ NSUInteger i = 0;
81+ while([[tv textStorage] length] == 0) {
82+ i++;
83+ if(i > NSUIntegerMax - 5) {
84+ NSLog(@"Abort");
85+ return;
86+ }
87+ }
88+ sleep(1);
89+ NSTextStorage *ts = [[tv textStorage] copy];
90+
91+ NSMutableArray *links = [NSMutableArray array];
92+
93+ [ts enumerateAttribute:NSLinkAttributeName
94+ inRange:NSMakeRange(0, [ts length])
95+ options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
96+ usingBlock:^(id value, NSRange range, BOOL *stop) {
97+ NSURL *url = [NSURL URLWithString:value];
98+ if([self validateLink:url]) {
99+ [links addObject:[NSDictionary dictionaryWithObjectsAndKeys:url, @"Link",
100+ NSStringFromRange(range), @"Range", nil]];
101+ }
102+ }];
103+
104+ __block NSUInteger offset = 0;
105+// NSUInteger index = 0;
106+ NSUInteger count = [links count];
107+// for(index = 0; index < count; index++) {
108+ dispatch_apply(count, dispatch_get_global_queue(0,0), ^(size_t index){
109+ id dict = [links objectAtIndex:index];
110+ NSRange range = NSRangeFromString([dict objectForKey:@"Range"]);
111+ if([ts attribute:BSInlinePreviewerPreviewed atIndex:range.location longestEffectiveRange:NULL inRange:range]) {
112+ return;
113+ }
114+ // download image.
115+ self.totalDownloads = self.remainder = 1;
116+ NSImage *image = [self downloadImageURL:[dict objectForKey:@"Link"]];
117+ self.remainder = 0;
118+ if(!image) return;
119+
120+ id newInsertion = [self attachmentAttributedStringWithImage:image];
121+
122+
123+ NSDictionary *attr = [[NSDictionary alloc] initWithObjectsAndKeys:
124+ newInsertion, @"Image",
125+ [dict objectForKey:@"Range"], @"Range",
126+ tv, @"View",
127+ [NSNumber numberWithUnsignedInteger:offset], @"Offset",
128+ nil];
129+ [self performSelectorOnMainThread:@selector(insertImage:) withObject:attr waitUntilDone:NO];
130+ offset += [newInsertion length];
131+ [attr release];
132+ });
133+ [ts release];
134+ [tv release];
135+ @synchronized(tasking) {
136+ [tasking removeObjectForKey:[self keyOfObject:tv]];
137+ }
138+// NSLog(@"ts \n%@", ts);
139+ });
140+}
141+
142+
143+@end
--- /dev/null
+++ b/Ex/en.lproj/InfoPlist.strings
@@ -0,0 +1,11 @@
1+/*
2+ InfoPlist.strings
3+ BSInlinePreviewer
4+
5+ Created by 堀 昌樹 on 12/05/17.
6+ Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
7+*/
8+
9+BSPreviewerDisplayName = "BSInlinePreviewerEx";
10+CFBundleGetInfoString = "BSInlinePreviewerEx 1.0b";
11+NSHumanReadableCopyright = "© masakih, 2012";
--- /dev/null
+++ b/Ex/ja.lproj/InfoPlist.strings
@@ -0,0 +1,11 @@
1+/*
2+ InfoPlist.strings
3+ BSInlinePreviewer
4+
5+ Created by 堀 昌樹 on 12/05/17.
6+ Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
7+*/
8+
9+BSPreviewerDisplayName = "BSInlinePreviewerEx";
10+CFBundleGetInfoString = "BSInlinePreviewerEx 1.0b";
11+NSHumanReadableCopyright = "© masakih, 2012";