PageRenderTime 31ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/src/PluginInstance.mm

http://firefox-mac-pdf.googlecode.com/
Objective C++ | 416 lines | 312 code | 62 blank | 42 comment | 48 complexity | 33e804b1e44de18e7ca999b23dd120ed MD5 | raw file
  1. /*
  2. * Copyright (c) 2008 Samuel Gross.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. * THE SOFTWARE.
  21. */
  22. #import "PluginInstance.h"
  23. #import "PluginPDFView.h"
  24. #import "PluginProgressView.h"
  25. #import "SelectionController.h"
  26. #import "Preferences.h"
  27. #import "PDFPluginShim.h"
  28. #include "PDFService.h"
  29. #include "nsStringAPI.h"
  30. #ifndef NSAppKitVersionNumber10_4
  31. #define NSAppKitVersionNumber10_4 824
  32. #endif
  33. @interface PluginInstance (FileInternal)
  34. - (void)_applyDefaults;
  35. @end
  36. @implementation PluginInstance
  37. - (id)initWithService:(PDFService*)pdfService plugin_id:(NSString*)plugin_id npp:(NPP)npp mimeType:(NSString*)mimeType;
  38. {
  39. if (self = [super init]) {
  40. _npp = npp;
  41. _mimeType = [mimeType retain];
  42. // load nib file
  43. [NSBundle loadNibNamed:@"PluginView" owner:self];
  44. pdfView = [pluginView pdfView];
  45. // listen to scale changes
  46. [[NSNotificationCenter defaultCenter]
  47. addObserver:self
  48. selector:@selector(updatePreferences)
  49. name:PDFViewScaleChangedNotification
  50. object:pdfView];
  51. [self _applyDefaults];
  52. selectionController = [[SelectionController forPDFView:pdfView] retain];
  53. _pdfService = pdfService;
  54. _pdfService->AddRef();
  55. _plugin_id = [plugin_id retain];
  56. _shim = new PDFPluginShim(self);
  57. _shim->AddRef();
  58. nsCAutoString idString([_plugin_id UTF8String]);
  59. nsresult r = _pdfService->Init(idString, _shim);
  60. if (r < 0) {
  61. NSLog(@"PDFService Init failed: %d", (int) r);
  62. }
  63. }
  64. return self;
  65. }
  66. - (void)dealloc
  67. {
  68. nsCAutoString idString([_plugin_id UTF8String]);
  69. if (pluginView) {
  70. [pluginView removeFromSuperview];
  71. [pluginView release];
  72. }
  73. if (progressView) {
  74. [progressView removeFromSuperview];
  75. [progressView release];
  76. }
  77. [parentView release];
  78. [selectionController release];
  79. [_searchResults release];
  80. [path release];
  81. _pdfService->CleanUp(idString);
  82. _shim->Release();
  83. _pdfService->Release();
  84. [_plugin_id release];
  85. [_url release];
  86. [_mimeType release];
  87. [_data release];
  88. [super dealloc];
  89. }
  90. - (BOOL)attached
  91. {
  92. return _attached;
  93. }
  94. - (void)attachToWindow:(NSWindow*)window at:(NSPoint)point
  95. {
  96. // find the NSView at the point
  97. NSView* hitView = [[window contentView] hitTest:NSMakePoint(point.x+1, point.y+1)];
  98. if (hitView == nil || ![[hitView className] isEqualToString:@"ChildView"]) {
  99. return;
  100. }
  101. parentView = [hitView retain];
  102. [parentView addSubview:pluginView];
  103. [pluginView setFrameSize:[parentView frame].size];
  104. [pluginView setNextResponder:pdfView];
  105. [pdfView setNextResponder:nil];
  106. if (progressView) {
  107. [parentView addSubview:progressView positioned:NSWindowAbove relativeTo:pluginView];
  108. // set the next responder to nil to prevent infinite loop
  109. // due to weirdness in event handling in nsChildView.mm
  110. [progressView setNextResponder:nil];
  111. int x = ([parentView frame].size.width - [progressView frame].size.width) / 2;
  112. int y = ([parentView frame].size.height - [progressView frame].size.height) / 2;
  113. [progressView setFrameOrigin:NSMakePoint(x, y)];
  114. }
  115. _attached = true;
  116. }
  117. - (void)print
  118. {
  119. [pdfView printWithInfo:[NSPrintInfo sharedPrintInfo] autoRotate:YES];
  120. }
  121. - (void)save
  122. {
  123. nsCAutoString idString([_plugin_id UTF8String]);
  124. nsCAutoString urlString([_url UTF8String]);
  125. _pdfService->Save(idString, urlString);
  126. }
  127. - (void)requestFocus
  128. {
  129. // if (![pluginView isHiddenOrHasHiddenAncestor]) {
  130. // [[pluginView window] makeFirstResponder:[pdfView documentView]];
  131. // }
  132. }
  133. - (void)setProgress:(int)progress total:(int)total
  134. {
  135. if (progressView) {
  136. [progressView setProgress:progress total:total];
  137. }
  138. }
  139. - (void)downloadFailed
  140. {
  141. NSLog(@"PDF plugin download failed");
  142. if (progressView) {
  143. [progressView downloadFailed];
  144. }
  145. }
  146. - (void)setData:(NSData*)data
  147. {
  148. if (progressView) {
  149. [progressView removeFromSuperview];
  150. [progressView release];
  151. progressView = nil;
  152. }
  153. // create PDF document
  154. _data = [data retain];
  155. NSData* pdfData;
  156. if ([_mimeType isEqualToString:@"application/postscript"]) {
  157. pdfData = [self convertPostScriptDataSourceToPDF:_data];
  158. } else {
  159. pdfData = _data;
  160. }
  161. PDFDocument* document = [[[PDFDocument alloc] initWithData:pdfData] autorelease];
  162. [document setDelegate:self];
  163. [pdfView setDocument:document];
  164. }
  165. - (void)_applyDefaults
  166. {
  167. bool autoScales = [Preferences getBoolPreference:"autoScales"];
  168. int displayMode = [Preferences getIntPreference:"displayMode"];
  169. [pdfView setAutoScales:autoScales];
  170. if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_4) {
  171. [pdfView setScaleFactor:1.0];
  172. } else {
  173. if (!autoScales) {
  174. float scaleFactor = [Preferences getFloatPreference:"scaleFactor"];
  175. [pdfView setScaleFactor:scaleFactor];
  176. }
  177. }
  178. [pdfView setDisplayMode:displayMode];
  179. }
  180. - (void)updatePreferences
  181. {
  182. if ([pdfView scaleFactor] == 20.0) {
  183. // Mac OS 10.4 has a bug relating to saving the zoom level that manifest
  184. // itself as zoom=20 and autoScales=false. I don't know the cause, but this
  185. // seems to work around the issue.
  186. return;
  187. }
  188. [Preferences setBoolPreference:"autoScales" value:[pdfView autoScales]];
  189. [Preferences setFloatPreference:"scaleFactor" value:[pdfView scaleFactor]];
  190. [Preferences setIntPreference:"displayMode" value:[pdfView displayMode]];
  191. }
  192. static bool selectionsAreEqual(PDFSelection* sel1, PDFSelection* sel2)
  193. {
  194. NSArray* pages1 = [sel1 pages];
  195. NSArray* pages2 = [sel2 pages];
  196. if (![pages1 isEqual:pages2]) {
  197. return false;
  198. }
  199. for (int i = 0; i < [pages1 count]; i++) {
  200. if (!NSEqualRects([sel1 boundsForPage:[pages1 objectAtIndex:i]],
  201. [sel2 boundsForPage:[pages2 objectAtIndex:i]])) {
  202. return false;
  203. }
  204. }
  205. return true;
  206. }
  207. - (int)find:(NSString*)string caseSensitive:(bool)caseSensitive forwards:(bool)forwards
  208. {
  209. const int FOUND = 0;
  210. const int NOT_FOUND = 1;
  211. const int WRAPPED = 2;
  212. int ret;
  213. PDFDocument* doc = [pdfView document];
  214. if (!doc) {
  215. return FOUND;
  216. }
  217. // only one search can take place at a time
  218. if ([doc isFinding]) {
  219. [doc cancelFindString];
  220. }
  221. if ([string length] == 0) {
  222. [selectionController setCurrentSelection:nil];
  223. return FOUND;
  224. }
  225. // see WebPDFView.mm in WebKit for general technique
  226. PDFSelection* initialSelection = [[pdfView currentSelection] copy];
  227. PDFSelection* searchSelection = [initialSelection copy];
  228. // collapse selection to before start/end
  229. int length = [[searchSelection string] length];
  230. if (forwards) {
  231. [searchSelection extendSelectionAtStart:1];
  232. [searchSelection extendSelectionAtEnd:-length];
  233. } else {
  234. [searchSelection extendSelectionAtEnd:1];
  235. [searchSelection extendSelectionAtStart:-length];
  236. }
  237. int options = 0;
  238. options |= (caseSensitive ? 0 : NSCaseInsensitiveSearch);
  239. options |= (forwards ? 0 : NSBackwardsSearch);
  240. // search!
  241. PDFSelection* result = [doc findString:string fromSelection:searchSelection withOptions:options];
  242. [searchSelection release];
  243. // advance search if we get the same selection
  244. if (result && initialSelection && selectionsAreEqual(result, initialSelection)) {
  245. result = [doc findString:string fromSelection:initialSelection withOptions:options];
  246. }
  247. [initialSelection release];
  248. // wrap search
  249. if (!result) {
  250. result = [doc findString:string fromSelection:result withOptions:options];
  251. ret = result ? WRAPPED : NOT_FOUND;
  252. } else {
  253. ret = FOUND;
  254. }
  255. // scroll to the selection
  256. [selectionController setCurrentSelection:result];
  257. return ret;
  258. }
  259. - (void)findPrevious
  260. {
  261. nsCAutoString idString([_plugin_id UTF8String]);
  262. _pdfService->FindPrevious(idString);
  263. }
  264. - (void)findAll:(NSString*)string caseSensitive:(bool)caseSensitive
  265. {
  266. PDFDocument* doc = [pdfView document];
  267. if ([doc isFinding]) {
  268. [doc cancelFindString];
  269. }
  270. if ([string length] == 0) {
  271. [selectionController setHighlightedSelections:nil];
  272. return;
  273. }
  274. if (_searchResults == NULL) {
  275. _searchResults = [[NSMutableArray arrayWithCapacity: 10] retain];
  276. }
  277. int options = (caseSensitive ? 0 : NSCaseInsensitiveSearch);
  278. [doc beginFindString:string withOptions:options];
  279. }
  280. - (void)removeHighlights
  281. {
  282. [selectionController setHighlightedSelections:nil];
  283. }
  284. - (void)documentDidBeginDocumentFind:(NSNotification *)notification
  285. {
  286. [_searchResults removeAllObjects];
  287. }
  288. - (void)documentDidEndDocumentFind:(NSNotification *)notification
  289. {
  290. [selectionController setHighlightedSelections:_searchResults];
  291. }
  292. - (void)didMatchString:(PDFSelection*)instance
  293. {
  294. [_searchResults addObject: [instance copy]];
  295. }
  296. - (void)copy
  297. {
  298. [pdfView copy:nil];
  299. }
  300. - (BOOL)zoom:(int)zoomArg
  301. {
  302. switch (zoomArg) {
  303. case -1:
  304. [pdfView zoomOut:nil];
  305. break;
  306. case 0:
  307. [pdfView setScaleFactor:1.0];
  308. break;
  309. case 1:
  310. [pdfView zoomIn:nil];
  311. break;
  312. default:
  313. return NO;
  314. }
  315. return YES;
  316. }
  317. - (void)setUrl:(NSString*)url
  318. {
  319. [_url autorelease];
  320. _url = [url retain];
  321. if (progressView && url) {
  322. NSString* filename = [[[NSURL URLWithString:url] path] lastPathComponent];
  323. [progressView setFilename:filename];
  324. }
  325. }
  326. - (void)setVisible:(bool)visible
  327. {
  328. if ([pluginView inLiveResize]) {
  329. return;
  330. }
  331. if (pluginView && _attached) {
  332. if (visible && ![pluginView superview]) {
  333. [pluginView setFrameSize:[parentView frame].size];
  334. [parentView addSubview:pluginView positioned:NSWindowBelow relativeTo:nil];
  335. } else if (!visible && [pluginView isHiddenOrHasHiddenAncestor]) {
  336. [pluginView removeFromSuperviewWithoutNeedingDisplay];
  337. }
  338. }
  339. }
  340. // PDFView delegate methods
  341. - (void)PDFViewWillClickOnLink:(PDFView *)sender withURL:(NSURL *)url
  342. {
  343. NPN_GetURL(_npp, [[url absoluteString] UTF8String], "_self");
  344. }
  345. // undocumented delegate methods
  346. - (void)PDFViewOpenPDFInNativeApplication:(PDFView*)sender
  347. {
  348. [self openWithFinder];
  349. }
  350. - (void)PDFViewSavePDFToDownloadFolder:(PDFView*)sender
  351. {
  352. [self save];
  353. }
  354. @end