123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- #import "ReaderConstants.h"
- #import "ReaderContentView.h"
- #import "ReaderContentPage.h"
- #import "ReaderThumbCache.h"
- #import <QuartzCore/QuartzCore.h>
- @interface ReaderContentView () <UIScrollViewDelegate>
- @end
- @implementation ReaderContentView
- {
- UIView *theContainerView;
- UIUserInterfaceIdiom userInterfaceIdiom;
- ReaderContentPage *theContentPage;
- ReaderContentThumb *theThumbView;
- CGFloat realMaximumZoom;
- CGFloat tempMaximumZoom;
- BOOL zoomBounced;
- }
- #pragma mark - Constants
- #define ZOOM_FACTOR 2.0f
- #define ZOOM_MAXIMUM 16.0f
- #define PAGE_THUMB_SMALL 144
- #define PAGE_THUMB_LARGE 240
- static void *ReaderContentViewContext = &ReaderContentViewContext;
- static CGFloat g_BugFixWidthInset = 0.0f;
- #pragma mark - Properties
- @synthesize message;
- #pragma mark - ReaderContentView functions
- static inline CGFloat zoomScaleThatFits(CGSize target, CGSize source)
- {
- CGFloat w_scale = (target.width / (source.width + g_BugFixWidthInset));
- CGFloat h_scale = (target.height / source.height);
- return ((w_scale < h_scale) ? w_scale : h_scale);
- }
- #pragma mark - ReaderContentView class methods
- + (void)initialize
- {
- if (self == [ReaderContentView self])
- {
- if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)
- {
- NSString *iosVersion = [UIDevice currentDevice].systemVersion;
- if ([@"8.0" compare:iosVersion options:NSNumericSearch] != NSOrderedDescending)
- {
- g_BugFixWidthInset = 2.0f * [[UIScreen mainScreen] scale];
- }
- }
- }
- }
- #pragma mark - ReaderContentView instance methods
- - (void)updateMinimumMaximumZoom
- {
- CGFloat zoomScale = zoomScaleThatFits(self.bounds.size, theContentPage.bounds.size);
- self.minimumZoomScale = zoomScale; self.maximumZoomScale = (zoomScale * ZOOM_MAXIMUM);
- realMaximumZoom = self.maximumZoomScale; tempMaximumZoom = (realMaximumZoom * ZOOM_FACTOR);
- }
- - (void)centerScrollViewContent
- {
- CGFloat iw = 0.0f; CGFloat ih = 0.0f;
- CGSize boundsSize = self.bounds.size; CGSize contentSize = self.contentSize;
- if (contentSize.width < boundsSize.width) iw = ((boundsSize.width - contentSize.width) * 0.5f);
- if (contentSize.height < boundsSize.height) ih = ((boundsSize.height - contentSize.height) * 0.5f);
- UIEdgeInsets insets = UIEdgeInsetsMake(ih, iw, ih, iw);
- if (UIEdgeInsetsEqualToEdgeInsets(self.contentInset, insets) == false) self.contentInset = insets;
- }
- - (instancetype)initWithFrame:(CGRect)frame fileURL:(NSURL *)fileURL page:(NSUInteger)page password:(NSString *)phrase
- {
- if ((self = [super initWithFrame:frame]))
- {
- self.scrollsToTop = NO;
- self.delaysContentTouches = NO;
- self.showsVerticalScrollIndicator = NO;
- self.showsHorizontalScrollIndicator = NO;
- self.contentMode = UIViewContentModeRedraw;
- self.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
- self.backgroundColor = [UIColor clearColor];
- self.autoresizesSubviews = NO;
- self.clipsToBounds = NO;
- self.delegate = self;
- userInterfaceIdiom = [UIDevice currentDevice].userInterfaceIdiom;
- theContentPage = [[ReaderContentPage alloc] initWithURL:fileURL page:page password:phrase];
- if (theContentPage != nil)
- {
- theContainerView = [[UIView alloc] initWithFrame:theContentPage.bounds];
- theContainerView.autoresizesSubviews = NO;
- theContainerView.userInteractionEnabled = NO;
- theContainerView.contentMode = UIViewContentModeRedraw;
- theContainerView.autoresizingMask = UIViewAutoresizingNone;
- theContainerView.backgroundColor = [UIColor whiteColor];
- #if (READER_SHOW_SHADOWS == TRUE)
- theContainerView.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
- theContainerView.layer.shadowRadius = 4.0f; theContainerView.layer.shadowOpacity = 1.0f;
- theContainerView.layer.shadowPath = [UIBezierPath bezierPathWithRect:theContainerView.bounds].CGPath;
- #endif
- self.contentSize = theContentPage.bounds.size; [self centerScrollViewContent];
- #if (READER_ENABLE_PREVIEW == TRUE)
- theThumbView = [[ReaderContentThumb alloc] initWithFrame:theContentPage.bounds];
- [theContainerView addSubview:theThumbView];
- #endif
- [theContainerView addSubview:theContentPage];
- [self addSubview:theContainerView];
- [self updateMinimumMaximumZoom];
- self.zoomScale = self.minimumZoomScale;
- [self addObserver:self forKeyPath:@"frame" options:0 context:ReaderContentViewContext];
- }
- self.tag = page;
- }
- return self;
- }
- - (void)dealloc
- {
- [self removeObserver:self forKeyPath:@"frame" context:ReaderContentViewContext];
- }
- - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
- {
- if (context == ReaderContentViewContext)
- {
- if ((object == self) && [keyPath isEqualToString:@"frame"])
- {
- [self centerScrollViewContent];
- CGFloat oldMinimumZoomScale = self.minimumZoomScale;
- [self updateMinimumMaximumZoom];
- if (self.zoomScale == oldMinimumZoomScale)
- {
- self.zoomScale = self.minimumZoomScale;
- }
- else
- {
- if (self.zoomScale < self.minimumZoomScale)
- {
- self.zoomScale = self.minimumZoomScale;
- }
- else
- {
- if (self.zoomScale > self.maximumZoomScale)
- {
- self.zoomScale = self.maximumZoomScale;
- }
- }
- }
- }
- }
- }
- - (void)showPageThumb:(NSURL *)fileURL page:(NSInteger)page password:(NSString *)phrase guid:(NSString *)guid
- {
- #if (READER_ENABLE_PREVIEW == TRUE)
- CGSize size = ((userInterfaceIdiom == UIUserInterfaceIdiomPad) ? CGSizeMake(PAGE_THUMB_LARGE, PAGE_THUMB_LARGE) : CGSizeMake(PAGE_THUMB_SMALL, PAGE_THUMB_SMALL));
- ReaderThumbRequest *request = [ReaderThumbRequest newForView:theThumbView fileURL:fileURL password:phrase guid:guid page:page size:size];
- UIImage *image = [[ReaderThumbCache sharedInstance] thumbRequest:request priority:YES];
- if ([image isKindOfClass:[UIImage class]]) [theThumbView showImage:image];
- #endif
- }
- - (id)processSingleTap:(UITapGestureRecognizer *)recognizer
- {
- return [theContentPage processSingleTap:recognizer];
- }
- - (CGRect)zoomRectForScale:(CGFloat)scale withCenter:(CGPoint)center
- {
- CGRect zoomRect;
- zoomRect.size.width = (self.bounds.size.width / scale);
- zoomRect.size.height = (self.bounds.size.height / scale);
- zoomRect.origin.x = (center.x - (zoomRect.size.width * 0.5f));
- zoomRect.origin.y = (center.y - (zoomRect.size.height * 0.5f));
- return zoomRect;
- }
- - (void)zoomIncrement:(UITapGestureRecognizer *)recognizer
- {
- CGFloat zoomScale = self.zoomScale;
- CGPoint point = [recognizer locationInView:theContentPage];
- if (zoomScale < self.maximumZoomScale)
- {
- zoomScale *= ZOOM_FACTOR;
- if (zoomScale > self.maximumZoomScale) zoomScale = self.maximumZoomScale;
- CGRect zoomRect = [self zoomRectForScale:zoomScale withCenter:point];
- [self zoomToRect:zoomRect animated:YES];
- }
- else
- {
- if (zoomBounced == NO)
- {
- self.maximumZoomScale = tempMaximumZoom;
- [self setZoomScale:tempMaximumZoom animated:YES];
- }
- else
- {
- zoomScale = self.minimumZoomScale;
- [self setZoomScale:zoomScale animated:YES];
- }
- }
- }
- - (void)zoomDecrement:(UITapGestureRecognizer *)recognizer
- {
- CGFloat zoomScale = self.zoomScale;
- CGPoint point = [recognizer locationInView:theContentPage];
- if (zoomScale > self.minimumZoomScale)
- {
- zoomScale /= ZOOM_FACTOR;
- if (zoomScale < self.minimumZoomScale) zoomScale = self.minimumZoomScale;
- CGRect zoomRect = [self zoomRectForScale:zoomScale withCenter:point];
- [self zoomToRect:zoomRect animated:YES];
- }
- else
- {
- zoomScale = self.maximumZoomScale;
- CGRect zoomRect = [self zoomRectForScale:zoomScale withCenter:point];
- [self zoomToRect:zoomRect animated:YES];
- }
- }
- - (void)zoomResetAnimated:(BOOL)animated
- {
- if (self.zoomScale > self.minimumZoomScale)
- {
- if (animated) [self setZoomScale:self.minimumZoomScale animated:YES]; else self.zoomScale = self.minimumZoomScale; zoomBounced = NO;
- }
- }
- #pragma mark - UIScrollViewDelegate methods
- - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
- {
- return theContainerView;
- }
- - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale
- {
- if (self.zoomScale > realMaximumZoom)
- {
- [self setZoomScale:realMaximumZoom animated:YES]; self.maximumZoomScale = realMaximumZoom; zoomBounced = YES;
- }
- else
- {
- if (self.zoomScale < realMaximumZoom) zoomBounced = NO;
- }
- }
- - (void)scrollViewDidZoom:(UIScrollView *)scrollView
- {
- [self centerScrollViewContent];
- }
- #pragma mark - UIResponder instance methods
- - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
- {
- [super touchesBegan:touches withEvent:event];
- [message contentView:self touchesBegan:touches];
- }
- - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
- {
- [super touchesCancelled:touches withEvent:event];
- }
- - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
- {
- [super touchesEnded:touches withEvent:event];
- }
- - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
- {
- [super touchesMoved:touches withEvent:event];
- }
- @end
- #pragma mark -
- @implementation ReaderContentThumb
- #pragma mark - ReaderContentThumb instance methods
- - (instancetype)initWithFrame:(CGRect)frame
- {
- if ((self = [super initWithFrame:frame]))
- {
- imageView.contentMode = UIViewContentModeScaleAspectFill;
- imageView.clipsToBounds = YES;
- }
- return self;
- }
- @end
|