123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928 |
- //
- // ReaderViewController.m
- // Reader v2.8.6
- //
- // Created by Julius Oklamcak on 2011-07-01.
- // Copyright © 2011-2015 Julius Oklamcak. All rights reserved.
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights to
- // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- // of the Software, and to permit persons to whom the Software is furnished to
- // do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in all
- // copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- #import "ReaderConstants.h"
- #import "ReaderViewController.h"
- #import "ThumbsViewController.h"
- #import "ReaderMainToolbar.h"
- #import "ReaderMainPagebar.h"
- #import "ReaderContentView.h"
- #import "ReaderThumbCache.h"
- #import "ReaderThumbQueue.h"
- #import <MessageUI/MessageUI.h>
- @interface ReaderViewController () <UIScrollViewDelegate, UIGestureRecognizerDelegate, MFMailComposeViewControllerDelegate, UIDocumentInteractionControllerDelegate,
- ReaderMainToolbarDelegate, ReaderMainPagebarDelegate, ReaderContentViewDelegate, ThumbsViewControllerDelegate>
- @end
- @implementation ReaderViewController
- {
- ReaderDocument *document;
- UIScrollView *theScrollView;
- ReaderMainToolbar *mainToolbar;
- ReaderMainPagebar *mainPagebar;
- NSMutableDictionary *contentViews;
- UIUserInterfaceIdiom userInterfaceIdiom;
- NSInteger currentPage, minimumPage, maximumPage;
- UIDocumentInteractionController *documentInteraction;
- UIPrintInteractionController *printInteraction;
- CGFloat scrollViewOutset;
- CGSize lastAppearSize;
- NSDate *lastHideTime;
- BOOL ignoreDidScroll;
- }
- #pragma mark - Constants
- #define STATUS_HEIGHT 20.0f
- #define TOOLBAR_HEIGHT 44.0f
- #define PAGEBAR_HEIGHT 48.0f
- #define SCROLLVIEW_OUTSET_SMALL 4.0f
- #define SCROLLVIEW_OUTSET_LARGE 8.0f
- #define TAP_AREA_SIZE 48.0f
- #pragma mark - Properties
- @synthesize delegate;
- #pragma mark - ReaderViewController methods
- - (void)updateContentSize:(UIScrollView *)scrollView
- {
- CGFloat contentHeight = scrollView.bounds.size.height; // Height
- CGFloat contentWidth = (scrollView.bounds.size.width * maximumPage);
- scrollView.contentSize = CGSizeMake(contentWidth, contentHeight);
- }
- - (void)updateContentViews:(UIScrollView *)scrollView
- {
- [self updateContentSize:scrollView]; // Update content size first
- [contentViews enumerateKeysAndObjectsUsingBlock: // Enumerate content views
- ^(NSNumber *key, ReaderContentView *contentView, BOOL *stop)
- {
- NSInteger page = [key integerValue]; // Page number value
- CGRect viewRect = CGRectZero; viewRect.size = scrollView.bounds.size;
- viewRect.origin.x = (viewRect.size.width * (page - 1)); // Update X
- contentView.frame = CGRectInset(viewRect, scrollViewOutset, 0.0f);
- }
- ];
- NSInteger page = currentPage; // Update scroll view offset to current page
- CGPoint contentOffset = CGPointMake((scrollView.bounds.size.width * (page - 1)), 0.0f);
- if (CGPointEqualToPoint(scrollView.contentOffset, contentOffset) == false) // Update
- {
- scrollView.contentOffset = contentOffset; // Update content offset
- }
- [mainToolbar setBookmarkState:[document.bookmarks containsIndex:page]];
- [mainPagebar updatePagebar]; // Update page bar
- }
- - (void)addContentView:(UIScrollView *)scrollView page:(NSInteger)page
- {
- CGRect viewRect = CGRectZero; viewRect.size = scrollView.bounds.size;
- viewRect.origin.x = (viewRect.size.width * (page - 1)); viewRect = CGRectInset(viewRect, scrollViewOutset, 0.0f);
- NSURL *fileURL = document.fileURL; NSString *phrase = document.password; NSString *guid = document.guid; // Document properties
- ReaderContentView *contentView = [[ReaderContentView alloc] initWithFrame:viewRect fileURL:fileURL page:page password:phrase]; // ReaderContentView
- contentView.message = self; [contentViews setObject:contentView forKey:[NSNumber numberWithInteger:page]]; [scrollView addSubview:contentView];
- [contentView showPageThumb:fileURL page:page password:phrase guid:guid]; // Request page preview thumb
- }
- - (void)layoutContentViews:(UIScrollView *)scrollView
- {
- CGFloat viewWidth = scrollView.bounds.size.width; // View width
- CGFloat contentOffsetX = scrollView.contentOffset.x; // Content offset X
- NSInteger pageB = ((contentOffsetX + viewWidth - 1.0f) / viewWidth); // Pages
- NSInteger pageA = (contentOffsetX / viewWidth); pageB += 2; // Add extra pages
- if (pageA < minimumPage) pageA = minimumPage; if (pageB > maximumPage) pageB = maximumPage;
- NSRange pageRange = NSMakeRange(pageA, (pageB - pageA + 1)); // Make page range (A to B)
- NSMutableIndexSet *pageSet = [NSMutableIndexSet indexSetWithIndexesInRange:pageRange];
- for (NSNumber *key in [contentViews allKeys]) // Enumerate content views
- {
- NSInteger page = [key integerValue]; // Page number value
- if ([pageSet containsIndex:page] == NO) // Remove content view
- {
- ReaderContentView *contentView = [contentViews objectForKey:key];
- [contentView removeFromSuperview]; [contentViews removeObjectForKey:key];
- }
- else // Visible content view - so remove it from page set
- {
- [pageSet removeIndex:page];
- }
- }
- NSInteger pages = pageSet.count;
- if (pages > 0) // We have pages to add
- {
- NSEnumerationOptions options = 0; // Default
- if (pages == 2) // Handle case of only two content views
- {
- if ((maximumPage > 2) && ([pageSet lastIndex] == maximumPage)) options = NSEnumerationReverse;
- }
- else if (pages == 3) // Handle three content views - show the middle one first
- {
- NSMutableIndexSet *workSet = [pageSet mutableCopy]; options = NSEnumerationReverse;
- [workSet removeIndex:[pageSet firstIndex]]; [workSet removeIndex:[pageSet lastIndex]];
- NSInteger page = [workSet firstIndex]; [pageSet removeIndex:page];
- [self addContentView:scrollView page:page];
- }
- [pageSet enumerateIndexesWithOptions:options usingBlock: // Enumerate page set
- ^(NSUInteger page, BOOL *stop)
- {
- [self addContentView:scrollView page:page];
- }
- ];
- }
- }
- - (void)handleScrollViewDidEnd:(UIScrollView *)scrollView
- {
- CGFloat viewWidth = scrollView.bounds.size.width; // Scroll view width
- CGFloat contentOffsetX = scrollView.contentOffset.x; // Content offset X
- NSInteger page = (contentOffsetX / viewWidth); page++; // Page number
- if (page != currentPage) // Only if on different page
- {
- currentPage = page; document.pageNumber = [NSNumber numberWithInteger:page];
- [contentViews enumerateKeysAndObjectsUsingBlock: // Enumerate content views
- ^(NSNumber *key, ReaderContentView *contentView, BOOL *stop)
- {
- if ([key integerValue] != page) [contentView zoomResetAnimated:NO];
- }
- ];
- [mainToolbar setBookmarkState:[document.bookmarks containsIndex:page]];
- [mainPagebar updatePagebar]; // Update page bar
- }
- }
- - (void)showDocumentPage:(NSInteger)page
- {
- if (page != currentPage) // Only if on different page
- {
- if ((page < minimumPage) || (page > maximumPage)) return;
- currentPage = page; document.pageNumber = [NSNumber numberWithInteger:page];
- CGPoint contentOffset = CGPointMake((theScrollView.bounds.size.width * (page - 1)), 0.0f);
- if (CGPointEqualToPoint(theScrollView.contentOffset, contentOffset) == true)
- [self layoutContentViews:theScrollView];
- else
- [theScrollView setContentOffset:contentOffset];
- [contentViews enumerateKeysAndObjectsUsingBlock: // Enumerate content views
- ^(NSNumber *key, ReaderContentView *contentView, BOOL *stop)
- {
- if ([key integerValue] != page) [contentView zoomResetAnimated:NO];
- }
- ];
- [mainToolbar setBookmarkState:[document.bookmarks containsIndex:page]];
- [mainPagebar updatePagebar]; // Update page bar
- }
- }
- - (void)showDocument
- {
- [self updateContentSize:theScrollView]; // Update content size first
- [self showDocumentPage:[document.pageNumber integerValue]]; // Show page
- document.lastOpen = [NSDate date]; // Update document last opened date
- }
- - (void)closeDocument
- {
- if (printInteraction != nil) [printInteraction dismissAnimated:NO];
- [document archiveDocumentProperties]; // Save any ReaderDocument changes
- [[ReaderThumbQueue sharedInstance] cancelOperationsWithGUID:document.guid];
- [[ReaderThumbCache sharedInstance] removeAllObjects]; // Empty the thumb cache
- if ([delegate respondsToSelector:@selector(dismissReaderViewController:)] == YES)
- {
- [delegate dismissReaderViewController:self]; // Dismiss the ReaderViewController
- }
- else // We have a "Delegate must respond to -dismissReaderViewController:" error
- {
- NSAssert(NO, @"Delegate must respond to -dismissReaderViewController:");
- }
- }
- #pragma mark - UIViewController methods
- - (instancetype)initWithReaderDocument:(ReaderDocument *)object
- {
- if ((self = [super initWithNibName:nil bundle:nil])) // Initialize superclass
- {
- if ((object != nil) && ([object isKindOfClass:[ReaderDocument class]])) // Valid object
- {
- userInterfaceIdiom = [UIDevice currentDevice].userInterfaceIdiom; // User interface idiom
- NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; // Default notification center
- [notificationCenter addObserver:self selector:@selector(applicationWillResign:) name:UIApplicationWillTerminateNotification object:nil];
- [notificationCenter addObserver:self selector:@selector(applicationWillResign:) name:UIApplicationWillResignActiveNotification object:nil];
- scrollViewOutset = ((userInterfaceIdiom == UIUserInterfaceIdiomPad) ? SCROLLVIEW_OUTSET_LARGE : SCROLLVIEW_OUTSET_SMALL);
- [object updateDocumentProperties]; document = object; // Retain the supplied ReaderDocument object for our use
- [ReaderThumbCache touchThumbCacheWithGUID:object.guid]; // Touch the document thumb cache directory
- }
- else // Invalid ReaderDocument object
- {
- self = nil;
- }
- }
- return self;
- }
- - (void)dealloc
- {
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- }
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- assert(document != nil); // Must have a valid ReaderDocument
- self.view.backgroundColor = [UIColor grayColor]; // Neutral gray
- UIView *fakeStatusBar = nil; CGRect viewRect = self.view.bounds; // View bounds
- if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) // iOS 7+
- {
- if ([self prefersStatusBarHidden] == NO) // Visible status bar
- {
- CGRect statusBarRect = viewRect; statusBarRect.size.height = STATUS_HEIGHT;
- fakeStatusBar = [[UIView alloc] initWithFrame:statusBarRect]; // UIView
- fakeStatusBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
- fakeStatusBar.backgroundColor = [UIColor blackColor];
- fakeStatusBar.contentMode = UIViewContentModeRedraw;
- fakeStatusBar.userInteractionEnabled = NO;
- viewRect.origin.y += STATUS_HEIGHT; viewRect.size.height -= STATUS_HEIGHT;
- }
- }
- CGRect scrollViewRect = CGRectInset(viewRect, -scrollViewOutset, 0.0f);
- theScrollView = [[UIScrollView alloc] initWithFrame:scrollViewRect]; // All
- theScrollView.autoresizesSubviews = NO; theScrollView.contentMode = UIViewContentModeRedraw;
- theScrollView.showsHorizontalScrollIndicator = NO; theScrollView.showsVerticalScrollIndicator = NO;
- theScrollView.scrollsToTop = NO; theScrollView.delaysContentTouches = NO; theScrollView.pagingEnabled = YES;
- theScrollView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
- theScrollView.backgroundColor = [UIColor clearColor]; theScrollView.delegate = self;
- [self.view addSubview:theScrollView];
- CGRect toolbarRect = viewRect; toolbarRect.size.height = TOOLBAR_HEIGHT;
- mainToolbar = [[ReaderMainToolbar alloc] initWithFrame:toolbarRect document:document]; // ReaderMainToolbar
- mainToolbar.delegate = self; // ReaderMainToolbarDelegate
- //TWS [self.view addSubview:mainToolbar];
- CGRect pagebarRect = self.view.bounds; pagebarRect.size.height = PAGEBAR_HEIGHT;
- pagebarRect.origin.y = (self.view.bounds.size.height - pagebarRect.size.height);
- mainPagebar = [[ReaderMainPagebar alloc] initWithFrame:pagebarRect document:document]; // ReaderMainPagebar
- mainPagebar.delegate = self; // ReaderMainPagebarDelegate
- [self.view addSubview:mainPagebar];
- if (fakeStatusBar != nil) [self.view addSubview:fakeStatusBar]; // Add status bar background view
- UITapGestureRecognizer *singleTapOne = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
- singleTapOne.numberOfTouchesRequired = 1; singleTapOne.numberOfTapsRequired = 1; singleTapOne.delegate = self;
- [self.view addGestureRecognizer:singleTapOne];
- UITapGestureRecognizer *doubleTapOne = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
- doubleTapOne.numberOfTouchesRequired = 1; doubleTapOne.numberOfTapsRequired = 2; doubleTapOne.delegate = self;
- [self.view addGestureRecognizer:doubleTapOne];
- UITapGestureRecognizer *doubleTapTwo = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
- doubleTapTwo.numberOfTouchesRequired = 2; doubleTapTwo.numberOfTapsRequired = 2; doubleTapTwo.delegate = self;
- [self.view addGestureRecognizer:doubleTapTwo];
-
- UISwipeGestureRecognizer *swipeUpDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeUpDown:)];
- swipeUpDown.direction = UISwipeGestureRecognizerDirectionDown | UISwipeGestureRecognizerDirectionUp;
- [self.view addGestureRecognizer:swipeUpDown];
- [singleTapOne requireGestureRecognizerToFail:doubleTapOne]; // Single tap requires double tap to fail
- contentViews = [NSMutableDictionary new]; lastHideTime = [NSDate date];
- minimumPage = 1; maximumPage = [document.pageCount integerValue];
- }
- - (void)viewWillAppear:(BOOL)animated
- {
- [super viewWillAppear:animated];
- if (CGSizeEqualToSize(lastAppearSize, CGSizeZero) == false)
- {
- if (CGSizeEqualToSize(lastAppearSize, self.view.bounds.size) == false)
- {
- [self updateContentViews:theScrollView]; // Update content views
- }
- lastAppearSize = CGSizeZero; // Reset view size tracking
- }
- }
- - (void)viewDidAppear:(BOOL)animated
- {
- [super viewDidAppear:animated];
- if (CGSizeEqualToSize(theScrollView.contentSize, CGSizeZero) == true)
- {
- [self performSelector:@selector(showDocument) withObject:nil afterDelay:0.0];
- }
- #if (READER_DISABLE_IDLE == TRUE) // Option
- [UIApplication sharedApplication].idleTimerDisabled = YES;
- #endif // end of READER_DISABLE_IDLE Option
- }
- - (void)viewWillDisappear:(BOOL)animated
- {
- [super viewWillDisappear:animated];
- lastAppearSize = self.view.bounds.size; // Track view size
- #if (READER_DISABLE_IDLE == TRUE) // Option
- [UIApplication sharedApplication].idleTimerDisabled = NO;
- #endif // end of READER_DISABLE_IDLE Option
- }
- - (void)viewDidDisappear:(BOOL)animated
- {
- [super viewDidDisappear:animated];
- }
- - (void)viewDidUnload
- {
- #ifdef DEBUG
- NSLog(@"%s", __FUNCTION__);
- #endif
- mainToolbar = nil; mainPagebar = nil;
- theScrollView = nil; contentViews = nil; lastHideTime = nil;
- documentInteraction = nil; printInteraction = nil;
- lastAppearSize = CGSizeZero; currentPage = 0;
- [super viewDidUnload];
- }
- - (BOOL)prefersStatusBarHidden
- {
- return YES;
- }
- - (UIStatusBarStyle)preferredStatusBarStyle
- {
- return UIStatusBarStyleLightContent;
- }
- - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
- {
- return YES;
- }
- - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
- {
- if (userInterfaceIdiom == UIUserInterfaceIdiomPad) if (printInteraction != nil) [printInteraction dismissAnimated:NO];
- ignoreDidScroll = YES;
- }
- - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
- {
- if (CGSizeEqualToSize(theScrollView.contentSize, CGSizeZero) == false)
- {
- [self updateContentViews:theScrollView]; lastAppearSize = CGSizeZero;
- }
- }
- - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
- {
- ignoreDidScroll = NO;
- }
- //TWS
- - (void)updateContentViews
- {
- if (currentPage > 0) {
- [self updateContentViews:theScrollView];
- }
- }
- - (void)didReceiveMemoryWarning
- {
- #ifdef DEBUG
- NSLog(@"%s", __FUNCTION__);
- #endif
- [super didReceiveMemoryWarning];
- }
- #pragma mark - UIScrollViewDelegate methods
- - (void)scrollViewDidScroll:(UIScrollView *)scrollView
- {
- if (ignoreDidScroll == NO) [self layoutContentViews:scrollView];
- }
- - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
- {
- [self handleScrollViewDidEnd:scrollView];
- }
- - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
- {
- [self handleScrollViewDidEnd:scrollView];
- }
- #pragma mark - UIGestureRecognizerDelegate methods
- - (BOOL)gestureRecognizer:(UIGestureRecognizer *)recognizer shouldReceiveTouch:(UITouch *)touch
- {
- if ([touch.view isKindOfClass:[UIScrollView class]]) return YES;
- return NO;
- }
- #pragma mark - UIGestureRecognizer action methods
- - (void)decrementPageNumber
- {
- if ((maximumPage > minimumPage) && (currentPage != minimumPage))
- {
- CGPoint contentOffset = theScrollView.contentOffset; // Offset
- contentOffset.x -= theScrollView.bounds.size.width; // View X--
- [theScrollView setContentOffset:contentOffset animated:YES];
- }
- }
- - (void)incrementPageNumber
- {
- if ((maximumPage > minimumPage) && (currentPage != maximumPage))
- {
- CGPoint contentOffset = theScrollView.contentOffset; // Offset
- contentOffset.x += theScrollView.bounds.size.width; // View X++
- [theScrollView setContentOffset:contentOffset animated:YES];
- }
- }
- - (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
- {
- if (recognizer.state == UIGestureRecognizerStateRecognized)
- {
- //TWS
- if ([self.delegate respondsToSelector:@selector(handleSingleTapReader)])
- [self.delegate handleSingleTapReader];
-
- CGRect viewRect = recognizer.view.bounds; // View bounds
- CGPoint point = [recognizer locationInView:recognizer.view]; // Point
- CGRect areaRect = CGRectInset(viewRect, TAP_AREA_SIZE, 0.0f); // Area rect
- if (CGRectContainsPoint(areaRect, point) == true) // Single tap is inside area
- {
- NSNumber *key = [NSNumber numberWithInteger:currentPage]; // Page number key
- ReaderContentView *targetView = [contentViews objectForKey:key]; // View
- id target = [targetView processSingleTap:recognizer]; // Target object
- if (target != nil) // Handle the returned target object
- {
- if ([target isKindOfClass:[NSURL class]]) // Open a URL
- {
- NSURL *url = (NSURL *)target; // Cast to a NSURL object
- if (url.scheme == nil) // Handle a missing URL scheme
- {
- NSString *www = url.absoluteString; // Get URL string
- if ([www hasPrefix:@"www"] == YES) // Check for 'www' prefix
- {
- NSString *http = [[NSString alloc] initWithFormat:@"http://%@", www];
- url = [NSURL URLWithString:http]; // Proper http-based URL
- }
- }
- if ([[UIApplication sharedApplication] openURL:url] == NO)
- {
- #ifdef DEBUG
- NSLog(@"%s '%@'", __FUNCTION__, url); // Bad or unknown URL
- #endif
- }
- }
- else // Not a URL, so check for another possible object type
- {
- if ([target isKindOfClass:[NSNumber class]]) // Goto page
- {
- NSInteger number = [target integerValue]; // Number
- [self showDocumentPage:number]; // Show the page
- }
- }
- }
- else // Nothing active tapped in the target content view
- {
- if ([lastHideTime timeIntervalSinceNow] < -0.75) // Delay since hide
- {
- if ((mainToolbar.alpha < 1.0f) || (mainPagebar.alpha < 1.0f)) // Hidden
- {
- [mainToolbar showToolbar]; [mainPagebar showPagebar]; // Show
- }
- }
- }
- return;
- }
- CGRect nextPageRect = viewRect;
- nextPageRect.size.width = TAP_AREA_SIZE;
- nextPageRect.origin.x = (viewRect.size.width - TAP_AREA_SIZE);
- if (CGRectContainsPoint(nextPageRect, point) == true) // page++
- {
- [self incrementPageNumber]; return;
- }
- CGRect prevPageRect = viewRect;
- prevPageRect.size.width = TAP_AREA_SIZE;
- if (CGRectContainsPoint(prevPageRect, point) == true) // page--
- {
- [self decrementPageNumber]; return;
- }
- }
- }
- - (void)handleDoubleTap:(UITapGestureRecognizer *)recognizer
- {
- if (recognizer.state == UIGestureRecognizerStateRecognized)
- {
- CGRect viewRect = recognizer.view.bounds; // View bounds
- CGPoint point = [recognizer locationInView:recognizer.view]; // Point
- CGRect zoomArea = CGRectInset(viewRect, TAP_AREA_SIZE, TAP_AREA_SIZE); // Area
- if (CGRectContainsPoint(zoomArea, point) == true) // Double tap is inside zoom area
- {
- NSNumber *key = [NSNumber numberWithInteger:currentPage]; // Page number key
- ReaderContentView *targetView = [contentViews objectForKey:key]; // View
- switch (recognizer.numberOfTouchesRequired) // Touches count
- {
- case 1: // One finger double tap: zoom++
- {
- [targetView zoomIncrement:recognizer]; break;
- }
- case 2: // Two finger double tap: zoom--
- {
- [targetView zoomDecrement:recognizer]; break;
- }
- }
- return;
- }
- CGRect nextPageRect = viewRect;
- nextPageRect.size.width = TAP_AREA_SIZE;
- nextPageRect.origin.x = (viewRect.size.width - TAP_AREA_SIZE);
- if (CGRectContainsPoint(nextPageRect, point) == true) // page++
- {
- [self incrementPageNumber]; return;
- }
- CGRect prevPageRect = viewRect;
- prevPageRect.size.width = TAP_AREA_SIZE;
- if (CGRectContainsPoint(prevPageRect, point) == true) // page--
- {
- [self decrementPageNumber]; return;
- }
- }
- }
- - (void)handleSwipeUpDown:(UITapGestureRecognizer *)recognizer
- {
- //TWS
- if ([self.delegate respondsToSelector:@selector(handleSwipeUpDown)])
- [self.delegate handleSwipeUpDown];
- }
- #pragma mark - ReaderContentViewDelegate methods
- - (void)contentView:(ReaderContentView *)contentView touchesBegan:(NSSet *)touches
- {
- if ((mainToolbar.alpha > 0.0f) || (mainPagebar.alpha > 0.0f))
- {
- if (touches.count == 1) // Single touches only
- {
- UITouch *touch = [touches anyObject]; // Touch info
- CGPoint point = [touch locationInView:self.view]; // Touch location
- CGRect areaRect = CGRectInset(self.view.bounds, TAP_AREA_SIZE, TAP_AREA_SIZE);
- if (CGRectContainsPoint(areaRect, point) == false) return;
- }
- [mainToolbar hideToolbar]; [mainPagebar hidePagebar]; // Hide
- lastHideTime = [NSDate date]; // Set last hide time
- }
- }
- #pragma mark - ReaderMainToolbarDelegate methods
- - (void)tappedInToolbar:(ReaderMainToolbar *)toolbar doneButton:(UIButton *)button
- {
- #if (READER_STANDALONE == FALSE) // Option
- [self closeDocument]; // Close ReaderViewController
- #endif // end of READER_STANDALONE Option
- }
- - (void)tappedInToolbar:(ReaderMainToolbar *)toolbar thumbsButton:(UIButton *)button
- {
- #if (READER_ENABLE_THUMBS == TRUE) // Option
- //TWS
- [[UIApplication sharedApplication] setStatusBarHidden:YES];
-
- if (printInteraction != nil) [printInteraction dismissAnimated:NO];
- ThumbsViewController *thumbsViewController = [[ThumbsViewController alloc] initWithReaderDocument:document];
- thumbsViewController.title = self.title; thumbsViewController.delegate = self; // ThumbsViewControllerDelegate
- thumbsViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
- thumbsViewController.modalPresentationStyle = UIModalPresentationFullScreen;
- [self presentViewController:thumbsViewController animated:NO completion:NULL];
- #endif // end of READER_ENABLE_THUMBS Option
- }
- - (void)tappedInToolbar:(ReaderMainToolbar *)toolbar exportButton:(UIButton *)button
- {
- if (printInteraction != nil) [printInteraction dismissAnimated:YES];
- NSURL *fileURL = document.fileURL; // Document file URL
- documentInteraction = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
- documentInteraction.delegate = self; // UIDocumentInteractionControllerDelegate
- [documentInteraction presentOpenInMenuFromRect:button.bounds inView:button animated:YES];
- }
- - (void)tappedInToolbar:(ReaderMainToolbar *)toolbar printButton:(UIButton *)button
- {
- if ([UIPrintInteractionController isPrintingAvailable] == YES)
- {
- NSURL *fileURL = document.fileURL; // Document file URL
- if ([UIPrintInteractionController canPrintURL:fileURL] == YES)
- {
- printInteraction = [UIPrintInteractionController sharedPrintController];
- UIPrintInfo *printInfo = [UIPrintInfo printInfo];
- printInfo.duplex = UIPrintInfoDuplexLongEdge;
- printInfo.outputType = UIPrintInfoOutputGeneral;
- printInfo.jobName = document.fileName;
- printInteraction.printInfo = printInfo;
- printInteraction.printingItem = fileURL;
- printInteraction.showsPageRange = YES;
- if (userInterfaceIdiom == UIUserInterfaceIdiomPad) // Large device printing
- {
- [printInteraction presentFromRect:button.bounds inView:button animated:YES completionHandler:
- ^(UIPrintInteractionController *pic, BOOL completed, NSError *error)
- {
- #ifdef DEBUG
- if ((completed == NO) && (error != nil)) NSLog(@"%s %@", __FUNCTION__, error);
- #endif
- }
- ];
- }
- else // Handle printing on small device
- {
- [printInteraction presentAnimated:YES completionHandler:
- ^(UIPrintInteractionController *pic, BOOL completed, NSError *error)
- {
- #ifdef DEBUG
- if ((completed == NO) && (error != nil)) NSLog(@"%s %@", __FUNCTION__, error);
- #endif
- }
- ];
- }
- }
- }
- }
- - (void)tappedInToolbar:(ReaderMainToolbar *)toolbar emailButton:(UIButton *)button
- {
- if ([MFMailComposeViewController canSendMail] == NO) return;
- if (printInteraction != nil) [printInteraction dismissAnimated:YES];
- unsigned long long fileSize = [document.fileSize unsignedLongLongValue];
- if (fileSize < 15728640ull) // Check attachment size limit (15MB)
- {
- NSURL *fileURL = document.fileURL; NSString *fileName = document.fileName;
- NSData *attachment = [NSData dataWithContentsOfURL:fileURL options:(NSDataReadingMapped|NSDataReadingUncached) error:nil];
- if (attachment != nil) // Ensure that we have valid document file attachment data available
- {
- MFMailComposeViewController *mailComposer = [MFMailComposeViewController new];
- [mailComposer addAttachmentData:attachment mimeType:@"application/pdf" fileName:fileName];
- [mailComposer setSubject:fileName]; // Use the document file name for the subject
- mailComposer.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
- mailComposer.modalPresentationStyle = UIModalPresentationFormSheet;
- mailComposer.mailComposeDelegate = self; // MFMailComposeViewControllerDelegate
- [self presentViewController:mailComposer animated:YES completion:NULL];
- }
- }
- }
- - (void)tappedInToolbar:(ReaderMainToolbar *)toolbar markButton:(UIButton *)button
- {
- #if (READER_BOOKMARKS == TRUE) // Option
- if (printInteraction != nil) [printInteraction dismissAnimated:YES];
- if ([document.bookmarks containsIndex:currentPage]) // Remove bookmark
- {
- [document.bookmarks removeIndex:currentPage]; [mainToolbar setBookmarkState:NO];
- }
- else // Add the bookmarked page number to the bookmark index set
- {
- [document.bookmarks addIndex:currentPage]; [mainToolbar setBookmarkState:YES];
- }
- #endif // end of READER_BOOKMARKS Option
- }
- #pragma mark - MFMailComposeViewControllerDelegate methods
- - (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
- {
- #ifdef DEBUG
- if ((result == MFMailComposeResultFailed) && (error != NULL)) NSLog(@"%@", error);
- #endif
- [self dismissViewControllerAnimated:YES completion:NULL];
- }
- #pragma mark - UIDocumentInteractionControllerDelegate methods
- - (void)documentInteractionControllerDidDismissOpenInMenu:(UIDocumentInteractionController *)controller
- {
- documentInteraction = nil;
- }
- #pragma mark - ThumbsViewControllerDelegate methods
- - (void)thumbsViewController:(ThumbsViewController *)viewController gotoPage:(NSInteger)page
- {
- #if (READER_ENABLE_THUMBS == TRUE) // Option
- [self showDocumentPage:page];
- #endif // end of READER_ENABLE_THUMBS Option
- }
- - (void)dismissThumbsViewController:(ThumbsViewController *)viewController
- {
- #if (READER_ENABLE_THUMBS == TRUE) // Option
- [self dismissViewControllerAnimated:NO completion:NULL];
- #endif // end of READER_ENABLE_THUMBS Option
- }
- #pragma mark - ReaderMainPagebarDelegate methods
- - (void)pagebar:(ReaderMainPagebar *)pagebar gotoPage:(NSInteger)page
- {
- [self showDocumentPage:page];
- }
- #pragma mark - UIApplication notification methods
- - (void)applicationWillResign:(NSNotification *)notification
- {
- [document archiveDocumentProperties]; // Save any ReaderDocument changes
- if (userInterfaceIdiom == UIUserInterfaceIdiomPad) if (printInteraction != nil) [printInteraction dismissAnimated:NO];
- }
- @end
|