/* Copyright (c) 2018, Apple Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. No license is granted to the trademarks of the copyright holders even if such marks are included in this software. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @import PDFKit; #import "ORKPDFViewerStepView_Internal.h" #import "ORKFreehandDrawingView.h" #import "ORKHelpers_Internal.h" #import "ORKBorderedButton.h" #import "ORKSkin.h" const CGFloat PDFSearchBarHeight = 40.0; const CGFloat PDFActionViewHeight = 25.0; const CGFloat PDFActionItemPadding = 1.0; const CGFloat PDFThumbnailViewWidth = 60.0; const CGFloat PDFActionsViewLeftRightPadding = 20.0; const CGFloat PDFParentStackViewSpacing = 10.0; const CGFloat PDFInactiveButtonAlpha = 0.5; const CGFloat PDFhideViewAnimationDuration = 0.5; NSString * const ORKPDFViewerStepShowPDFThumbnailActionButtonAccessibilityIdentifier = @"ORKPDFViewerStep_showPDF_thumbnailActionButton"; NSString * const ORKPDFViewerStepHidePDFThumbnailActionButtonAccessibilityIdentifier = @"ORKPDFViewerStep_hidePDF_thumbnailActionButton"; NSString * const ORKPDFViewerStepAnnotationActionButtonAccessibilityIdentifier = @"ORKPDFViewerStep_annotationActionButton"; NSString * const ORKPDFViewerStepShowSearchActionButtonAccessibilityIdentifier = @"ORKPDFViewerStep_showSearchActionButton"; NSString * const ORKPDFViewerStepHideSearchActionButtonAccessibilityIdentifier = @"ORKPDFViewerStep_hideSearchActionButton"; NSString * const ORKPDFViewerStepShareActionButtonAccessibilityIdentifier = @"ORKPDFViewerStep_shareActionButton"; NSString * const ORKPDFViewerActionViewExitButtonAccessibilityIdentifier = @"ORKPDFViewerActionView_exitButton"; NSString * const ORKPDFViewerActionViewApplyButtonAccessibilityIdentifier = @"ORKPDFViewerActionView_applyButton"; NSString * const ORKPDFViewerActionViewClearButtonAccessibilityIdentifier = @"ORKPDFViewerActionView_clearButton"; @interface ORKPDFViewerActionsView: UIView @property (nonatomic, nonnull) UIView *thumbnailActionView; @property (nonatomic, nonnull) UIView *annotationActionView; @property (nonatomic, nonnull) UIView *searchActionView; @property (nonatomic, nonnull) UIView *shareActionView; @property (nonatomic, nonnull) UIView *clearButtonView; @property (nonatomic, nonnull) UIView *applyButtonView; @property (nonatomic, nonnull) UIView *exitButtonView; @property (nonatomic, nonnull) UIStackView *stackView; @property (nonatomic, nonnull) UIButton *thumbnailActionButton; @property (nonatomic, nonnull) UIButton *annotationActionButton; @property (nonatomic, nonnull) UIButton *searchActionButton; @property (nonatomic, nonnull) UIButton *shareActionButton; @property (nonatomic, nonnull) ORKBorderedButton *clearAnnotationsButton; @property (nonatomic, nonnull) ORKBorderedButton *applyAnnotationsButton; @property (nonatomic, nonnull) UIButton *exitAnnotationsButton; @end @implementation ORKPDFViewerActionsView - (instancetype)init { self = [super init]; if (self) { } [self setupStackView]; [self setupConstraints]; return self; } - (void)setupStackView { if (!_stackView) { _stackView = [[UIStackView alloc] init]; } _stackView.translatesAutoresizingMaskIntoConstraints = NO; _stackView.spacing = 0.0; _stackView.layoutMargins = UIEdgeInsetsMake(0.0, PDFActionsViewLeftRightPadding, 0.0, PDFActionsViewLeftRightPadding); [_stackView setLayoutMarginsRelativeArrangement:YES]; _stackView.axis = UILayoutConstraintAxisHorizontal; _stackView.distribution = UIStackViewDistributionFillEqually; [self setupThumbnailAction]; [self setupAnnotationAction]; [self setupSearchAction]; [self setupShareAction]; [self setupClearAnnotationsButton]; [self setupApplyAnnotationsButton]; [self setupExitAnnotationsButton]; [self addSubview:_stackView]; } - (void)setupThumbnailAction { if (!_thumbnailActionButton) { _thumbnailActionButton = [UIButton buttonWithType:UIButtonTypeCustom]; } [_thumbnailActionButton setImage:[[UIImage imageNamed:@"pdfThumbnail" inBundle:ORKBundle() compatibleWithTraitCollection:nil] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; _thumbnailActionView = [UIView new]; _thumbnailActionView.translatesAutoresizingMaskIntoConstraints = NO; _thumbnailActionButton.translatesAutoresizingMaskIntoConstraints = NO; [_thumbnailActionView addSubview:_thumbnailActionButton]; [_stackView insertArrangedSubview:_thumbnailActionView atIndex:0]; [self activateConstraintsForButton:_thumbnailActionButton withView:_thumbnailActionView]; } - (void)setupAnnotationAction { if (!_annotationActionButton) { _annotationActionButton = [UIButton buttonWithType:UIButtonTypeCustom]; } [_annotationActionButton setImage:[[UIImage imageNamed:@"annotation" inBundle:ORKBundle() compatibleWithTraitCollection:nil] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; _annotationActionView = [UIView new]; _annotationActionView.translatesAutoresizingMaskIntoConstraints = NO; _annotationActionButton.translatesAutoresizingMaskIntoConstraints = NO; [_annotationActionView addSubview:_annotationActionButton]; [_stackView addArrangedSubview:_annotationActionView]; [self activateConstraintsForButton:_annotationActionButton withView:_annotationActionView]; } - (void)setupSearchAction { if (!_searchActionButton) { _searchActionButton = [UIButton buttonWithType:UIButtonTypeCustom]; } [_searchActionButton setImage:[[UIImage imageNamed:@"search" inBundle:ORKBundle() compatibleWithTraitCollection:nil] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; _searchActionView = [UIView new]; _searchActionView.translatesAutoresizingMaskIntoConstraints = NO; _searchActionButton.translatesAutoresizingMaskIntoConstraints = NO; [_searchActionView addSubview:_searchActionButton]; [_stackView addArrangedSubview:_searchActionView]; [self activateConstraintsForButton:_searchActionButton withView:_searchActionView]; } - (void)setupShareAction { if (!_shareActionButton) { _shareActionButton = [UIButton buttonWithType:UIButtonTypeCustom]; } [_shareActionButton setImage:[[UIImage imageNamed:@"share" inBundle:ORKBundle() compatibleWithTraitCollection:nil] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; _shareActionView = [UIView new]; _shareActionView.translatesAutoresizingMaskIntoConstraints = NO; _shareActionButton.translatesAutoresizingMaskIntoConstraints = NO; [_shareActionView addSubview:_shareActionButton]; [_stackView addArrangedSubview:_shareActionView]; [self activateConstraintsForButton:_shareActionButton withView:_shareActionView]; } - (void)setupClearAnnotationsButton { if (!_clearAnnotationsButton) { _clearAnnotationsButton = [ORKBorderedButton new]; } _clearAnnotationsButton.contentEdgeInsets = (UIEdgeInsets){.left = 6, .right = 6}; _clearAnnotationsButton.translatesAutoresizingMaskIntoConstraints = NO; _clearButtonView = [UIView new]; _clearButtonView.translatesAutoresizingMaskIntoConstraints = NO; _clearButtonView.accessibilityIdentifier = ORKPDFViewerActionViewClearButtonAccessibilityIdentifier; [_clearAnnotationsButton setTitle:ORKLocalizedString(@"BUTTON_CLEAR", nil) forState:UIControlStateNormal]; [_clearButtonView addSubview:_clearAnnotationsButton]; [_stackView addArrangedSubview:_clearButtonView]; [NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint constraintWithItem:_clearAnnotationsButton attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:_clearButtonView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0], [NSLayoutConstraint constraintWithItem:_clearAnnotationsButton attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:_clearButtonView attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0], [NSLayoutConstraint constraintWithItem:_clearAnnotationsButton attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:_clearButtonView attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0.0] ]]; } - (void)setupApplyAnnotationsButton { if (!_applyAnnotationsButton) { _applyAnnotationsButton = [ORKBorderedButton new]; } _applyAnnotationsButton.contentEdgeInsets = (UIEdgeInsets){.left = 6, .right = 6}; _applyAnnotationsButton.translatesAutoresizingMaskIntoConstraints = NO; _applyButtonView = [UIView new]; _applyButtonView.translatesAutoresizingMaskIntoConstraints = NO; _applyButtonView.accessibilityIdentifier = ORKPDFViewerActionViewApplyButtonAccessibilityIdentifier; [_applyAnnotationsButton setTitle:ORKLocalizedString(@"BUTTON_APPLY", nil) forState:UIControlStateNormal]; [_applyButtonView addSubview:_applyAnnotationsButton]; [_stackView addArrangedSubview:_applyButtonView]; [NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint constraintWithItem:_applyAnnotationsButton attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:_applyButtonView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0], [NSLayoutConstraint constraintWithItem:_applyAnnotationsButton attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:_applyButtonView attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0], [NSLayoutConstraint constraintWithItem:_applyAnnotationsButton attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:_applyButtonView attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0.0] ]];} - (void)setupExitAnnotationsButton { if (!_exitAnnotationsButton) { _exitAnnotationsButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; } [_exitAnnotationsButton setTitle:@"X" forState:UIControlStateNormal]; [_exitAnnotationsButton.titleLabel setAdjustsFontSizeToFitWidth:YES]; [_exitAnnotationsButton.titleLabel setFont:[UIFont boldSystemFontOfSize:[UIFont systemFontSize]]]; _exitAnnotationsButton.translatesAutoresizingMaskIntoConstraints = NO; _exitButtonView = [UIView new]; _exitButtonView.translatesAutoresizingMaskIntoConstraints = NO; _exitButtonView.accessibilityIdentifier = ORKPDFViewerActionViewExitButtonAccessibilityIdentifier; [_exitButtonView addSubview:_exitAnnotationsButton]; [_stackView addArrangedSubview:_exitButtonView]; [self activateConstraintsForButton:_exitAnnotationsButton withView:_exitButtonView]; [self setExitAnnotationsButtonStyle]; } - (void)activateConstraintsForButton:(UIButton *)button withView:(UIView *)view { [NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:PDFActionViewHeight], [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:PDFActionViewHeight], [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0], [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]]]; } - (void)setExitAnnotationsButtonStyle { [_exitAnnotationsButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [_exitAnnotationsButton setBackgroundColor:[[self tintColor] colorWithAlphaComponent:PDFInactiveButtonAlpha]]; [_exitAnnotationsButton.layer setCornerRadius:PDFActionViewHeight/2.0]; } - (void)setupConstraints { NSMutableArray *constraints = [NSMutableArray new]; NSDictionary *views = NSDictionaryOfVariableBindings(_stackView); [constraints addObjectsFromArray: [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_stackView]|" options:(NSLayoutFormatOptions)0 metrics:nil views:views]]; [constraints addObjectsFromArray: [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_stackView]|" options:(NSLayoutFormatOptions)0 metrics:nil views:views]]; [NSLayoutConstraint activateConstraints:constraints]; } @end @interface ORKPDFViewerStepView () @end @implementation ORKPDFViewerStepView { UIStackView *_parentStackView, *_pdfStackView; UISearchBar *_searchBar; ORKPDFViewerActionsView *_pdfActionsView; PDFView *_pdfView; PDFThumbnailView *_pdfThumbnailView; ORKFreehandDrawingView *_freehandDrawingView; BOOL _isFreehandDrawingActive; BOOL _isShareActive; BOOL _annotationsAdded; UIView *_keyboardUnderlapView; } - (instancetype)init { self = [super init]; if (self) { [self setupParentStackView]; [self setupSearchBar]; [self setupPDFActionsView]; [self setupPDFStackView]; [self setupKeyboardUnderlapView]; [self setupConstraints]; } return self; } - (void)setupParentStackView { if (!_parentStackView) { _parentStackView = [[UIStackView alloc] init]; } _parentStackView.translatesAutoresizingMaskIntoConstraints = NO; _parentStackView.spacing = PDFParentStackViewSpacing; _parentStackView.axis = UILayoutConstraintAxisVertical; _parentStackView.distribution = UIStackViewDistributionFill; [self addSubview:_parentStackView]; } - (void)setupSearchBar { if (!_searchBar) { _searchBar = [[UISearchBar alloc] init]; } [NSLayoutConstraint constraintWithItem:_searchBar attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:PDFSearchBarHeight].active = YES; _searchBar.hidden = YES; _searchBar.delegate = self; _searchBar.barTintColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.3]; _searchBar.translatesAutoresizingMaskIntoConstraints = NO; [_parentStackView insertArrangedSubview:_searchBar atIndex:0]; } - (void)setupPDFActionsView { if (!_pdfActionsView) { _pdfActionsView = [ORKPDFViewerActionsView new]; } [NSLayoutConstraint constraintWithItem:_pdfActionsView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:PDFActionViewHeight].active = YES; [self setupClearApplyExitButtons]; [_pdfActionsView.thumbnailActionButton addTarget:self action:@selector(thumbnailButtonAction) forControlEvents:UIControlEventTouchUpInside]; [_pdfActionsView.annotationActionButton addTarget:self action:@selector(annotationButtonAction) forControlEvents:UIControlEventTouchUpInside]; [_pdfActionsView.searchActionButton addTarget:self action:@selector(searchButtonAction) forControlEvents:UIControlEventTouchUpInside]; [_pdfActionsView.shareActionButton addTarget:self action:@selector(shareButtonAction) forControlEvents:UIControlEventTouchUpInside]; _pdfActionsView.translatesAutoresizingMaskIntoConstraints = NO; [_parentStackView addArrangedSubview:_pdfActionsView]; [self updateActionButtonAccessibilityLabels]; } - (void)setupPDFStackView { if (!_pdfStackView) { [self setupPDFView]; _pdfStackView = [[UIStackView alloc] initWithArrangedSubviews:@[_pdfThumbnailView, _pdfView]]; } _pdfStackView.translatesAutoresizingMaskIntoConstraints = NO; _pdfStackView.spacing = 10.0; _pdfStackView.axis = UILayoutConstraintAxisHorizontal; _pdfStackView.distribution = UIStackViewDistributionFill; [_parentStackView addArrangedSubview:_pdfStackView]; } - (void)setupPDFView { if (!_pdfView) { _pdfView = [PDFView new]; } PDFDocument *document; if (_pdfURL) { document = [[PDFDocument alloc] initWithURL:_pdfURL]; _pdfView.document = document; _pdfView.document.delegate = self; } if (document) { [self setEnableAllButtons:!document.isLocked]; } else { [self setEnableAllButtons:document]; } _pdfView.autoScales = YES; _pdfView.displayMode = kPDFDisplaySinglePageContinuous; _pdfView.translatesAutoresizingMaskIntoConstraints = NO; _pdfThumbnailView = [PDFThumbnailView new]; _pdfThumbnailView.translatesAutoresizingMaskIntoConstraints = NO; _pdfThumbnailView.thumbnailSize = CGSizeMake(40, 40); [NSLayoutConstraint constraintWithItem:_pdfThumbnailView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:PDFThumbnailViewWidth].active = YES; _pdfThumbnailView.layoutMode = PDFThumbnailLayoutModeVertical; _pdfThumbnailView.PDFView = _pdfView; _pdfThumbnailView.hidden = YES; [self updateActionButtonsAppearance]; } - (void)setupClearApplyExitButtons { [_pdfActionsView.clearButtonView setHidden:YES]; [_pdfActionsView.applyButtonView setHidden:YES]; [_pdfActionsView.exitButtonView setHidden:YES]; [self updateClearApplyAnnotationButtons]; [_pdfActionsView.clearAnnotationsButton addTarget:self action:@selector(clearButtonAction) forControlEvents:UIControlEventTouchUpInside]; [_pdfActionsView.applyAnnotationsButton addTarget:self action:@selector(applybuttonAction) forControlEvents:UIControlEventTouchUpInside]; [_pdfActionsView.exitAnnotationsButton addTarget:self action:@selector(exitButtonAction) forControlEvents:UIControlEventTouchUpInside]; } - (void)updateClearApplyAnnotationButtons { [_pdfActionsView.clearAnnotationsButton setEnabled:_freehandDrawingView.freehandDrawingExists]; [_pdfActionsView.applyAnnotationsButton setEnabled:_freehandDrawingView.freehandDrawingExists]; } - (void)thumbnailButtonAction { [self animateViews:@[_pdfThumbnailView] setHidden:!_pdfThumbnailView.isHidden]; [self updateActionButtonsAppearance]; [_pdfView setAutoScales:YES]; } - (void)annotationButtonAction { [self setPDFViewDisplayModeSinglePage:_isFreehandDrawingActive]; if (!_isFreehandDrawingActive && !_freehandDrawingView) { [self addFreehandDrawingView]; } [self setIsScibbleActive:YES]; [self updateActionButtonsAppearance]; } - (void)addAnnotations: (PDFAnnotation *)annotations { [_pdfView.currentPage addAnnotation:annotations]; } - (void)setPDFViewDisplayModeSinglePage:(BOOL) isContinuous { PDFPage *currentPage = _pdfView.currentPage; [_pdfView setScaleFactor:[_pdfView minScaleFactor]]; [_pdfView setDisplayMode:isContinuous ? kPDFDisplaySinglePageContinuous : kPDFDisplaySinglePage]; [_pdfView setScaleFactor:[_pdfView scaleFactorForSizeToFit]]; [_pdfView goToPage:currentPage]; } - (void)searchButtonAction { [UIView animateWithDuration:0.5 animations:^{ if (!_searchBar.isHidden) { [self searchBarDismissKeyboard]; } _searchBar.hidden = !_searchBar.isHidden; }]; [self updateActionButtonsAppearance]; } - (void)setEnableAllButtons:(BOOL)enable { [_pdfActionsView.thumbnailActionButton setEnabled:enable]; [_pdfActionsView.annotationActionButton setEnabled:enable]; [_pdfActionsView.searchActionButton setEnabled:enable]; [_pdfActionsView.shareActionButton setEnabled:enable]; } - (void)updateActionButtonsAppearance { _pdfActionsView.thumbnailActionButton.alpha = _pdfThumbnailView.isHidden ? PDFInactiveButtonAlpha : 1.0; _pdfActionsView.annotationActionButton.alpha = !_isFreehandDrawingActive ? PDFInactiveButtonAlpha : 1.0; _pdfActionsView.searchActionButton.alpha = _searchBar.isHidden ? PDFInactiveButtonAlpha : 1.0; _pdfActionsView.shareActionButton.alpha = PDFInactiveButtonAlpha; [self updateActionButtonAccessibilityLabels]; } - (void)updateActionButtonAccessibilityLabels { _pdfActionsView.thumbnailActionButton.accessibilityLabel = _pdfThumbnailView.isHidden ?ORKLocalizedString(@"AX_BUTTON_SHOW_PDF_THUMBNAIL" , nil) : ORKLocalizedString(@"AX_BUTTON_HIDE_PDF_THUMBNAIL", nil); _pdfActionsView.annotationActionButton.accessibilityLabel = ORKLocalizedString(@"AX_BUTTON_ANNOTATE" , nil); _pdfActionsView.searchActionButton.accessibilityLabel = _searchBar.isHidden ? ORKLocalizedString(@"AX_BUTTON_SHOW_SEARCH", nil) : ORKLocalizedString(@"AX_BUTTON_HIDE_SEARCH", nil); _pdfActionsView.shareActionButton.accessibilityLabel = ORKLocalizedString(@"AX_BUTTON_SHARE", nil); _pdfActionsView.thumbnailActionButton.accessibilityIdentifier = _pdfThumbnailView.isHidden ?ORKPDFViewerStepShowPDFThumbnailActionButtonAccessibilityIdentifier : ORKPDFViewerStepHidePDFThumbnailActionButtonAccessibilityIdentifier; _pdfActionsView.annotationActionButton.accessibilityIdentifier = ORKPDFViewerStepAnnotationActionButtonAccessibilityIdentifier; _pdfActionsView.searchActionButton.accessibilityIdentifier = _searchBar.isHidden ? ORKPDFViewerStepShowSearchActionButtonAccessibilityIdentifier : ORKPDFViewerStepHideSearchActionButtonAccessibilityIdentifier; _pdfActionsView.shareActionButton.accessibilityIdentifier = ORKPDFViewerStepShareActionButtonAccessibilityIdentifier; } - (void)shareButtonAction { if (_isShareActive) { } else { if (self.delegate && [self.delegate respondsToSelector:@selector(didSelectShareButton:)]) { [self.delegate didSelectShareButton:_pdfActionsView.shareActionButton]; } } _isShareActive = !_isShareActive; [self updateActionButtonsAppearance]; } - (void)setPdfURL:(NSURL *)pdfURL { if (_pdfURL != pdfURL) { _pdfURL = pdfURL; _pdfView.document = nil; PDFDocument *document; if (pdfURL) { document = [[PDFDocument alloc] initWithURL:pdfURL]; _pdfView.document = document; _pdfView.document.delegate = self; } if (document) { [self setEnableAllButtons:!document.isLocked]; _annotationsAdded = NO; } else { [self setEnableAllButtons:document]; } } } - (void)addFreehandDrawingView { if (!_freehandDrawingView) { _freehandDrawingView = [[ORKFreehandDrawingView alloc] initWithPDFView:_pdfView]; _freehandDrawingView.translatesAutoresizingMaskIntoConstraints = NO; _freehandDrawingView.backgroundColor = [UIColor clearColor]; _freehandDrawingView.opaque = NO; _freehandDrawingView.delegate = self; [self addSubview:_freehandDrawingView]; [NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint constraintWithItem:_freehandDrawingView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_pdfView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0], [NSLayoutConstraint constraintWithItem:_freehandDrawingView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:_pdfView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0.0], [NSLayoutConstraint constraintWithItem:_freehandDrawingView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:_pdfView attribute:NSLayoutAttributeRight multiplier:1.0 constant:0.0], [NSLayoutConstraint constraintWithItem:_freehandDrawingView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_pdfView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0] ]]; } } - (void)setupKeyboardUnderlapView { if (!_keyboardUnderlapView) { _keyboardUnderlapView = [UIView new]; } _keyboardUnderlapView.translatesAutoresizingMaskIntoConstraints = NO; _keyboardUnderlapView.hidden = YES; [_keyboardUnderlapView setBackgroundColor:[UIColor clearColor]]; [_parentStackView addArrangedSubview:_keyboardUnderlapView]; } - (void)setIsScibbleActive:(BOOL)isActive { _isFreehandDrawingActive = isActive; if (isActive) { [self searchBarDismissKeyboard]; [_pdfActionsView.thumbnailActionButton setHidden:YES]; [_pdfActionsView.annotationActionButton setHidden:YES]; [_pdfActionsView.searchActionButton setHidden:YES]; [_pdfActionsView.shareActionButton setHidden:YES]; [_pdfActionsView.clearAnnotationsButton setHidden:NO]; [_pdfActionsView.applyAnnotationsButton setHidden:NO]; [_pdfActionsView.exitAnnotationsButton setHidden:NO]; [self animateViews:@[ _pdfThumbnailView, _pdfActionsView.thumbnailActionView, _pdfActionsView.annotationActionView, _searchBar, _pdfActionsView.searchActionView, _pdfActionsView.shareActionView ] setHidden:YES]; [self animateViews:@[ _pdfActionsView.clearButtonView, _pdfActionsView.applyButtonView, _pdfActionsView.exitButtonView ] setHidden:NO]; } else { NSMutableArray *allowedViews = [[NSMutableArray alloc] init]; [_pdfActionsView.thumbnailActionButton setHidden:NO]; [_pdfActionsView.annotationActionButton setHidden:NO]; [_pdfActionsView.clearAnnotationsButton setHidden:YES]; [_pdfActionsView.applyAnnotationsButton setHidden:YES]; [_pdfActionsView.exitAnnotationsButton setHidden:YES]; [allowedViews addObjectsFromArray:@[_pdfActionsView.thumbnailActionView, _pdfActionsView.annotationActionView]]; if (!_hideSearchButton) { [_pdfActionsView.searchActionButton setHidden:NO]; [allowedViews addObject:_pdfActionsView.searchActionView]; } if (!_hideShareButton) { [_pdfActionsView.shareActionButton setHidden:NO]; [allowedViews addObject:_pdfActionsView.shareActionView]; } [self animateViews:allowedViews setHidden:NO]; [self animateViews:@[_pdfActionsView.clearButtonView, _pdfActionsView.applyButtonView, _pdfActionsView.exitButtonView] setHidden:YES]; } [self updateActionButtonsAppearance]; } - (void)clearButtonAction { if (_freehandDrawingView.freehandDrawingPath && _freehandDrawingView.freehandDrawingExists) { [_freehandDrawingView clear]; } [self updateClearApplyAnnotationButtons]; } - (void)applybuttonAction { if (_freehandDrawingView.freehandDrawingPath && _freehandDrawingView.freehandDrawingExists) { CGRect annotationRect = _pdfView.documentView.bounds; PDFAnnotation *annotation = [[PDFAnnotation alloc] initWithBounds:annotationRect forType:PDFAnnotationSubtypeInk withProperties:nil]; annotation.border.lineWidth = 2.0; for (UIBezierPath *path in _freehandDrawingView.freehandDrawingPath) { [annotation addBezierPath:path]; } [_pdfView.currentPage addAnnotation:annotation]; [_freehandDrawingView clear]; _annotationsAdded = YES; } [self updateClearApplyAnnotationButtons]; } - (void)exitButtonAction { [self setPDFViewDisplayModeSinglePage:_isFreehandDrawingActive]; if (_isFreehandDrawingActive && _freehandDrawingView) { [_freehandDrawingView removeFromSuperview]; _freehandDrawingView = nil; [self setIsScibbleActive:NO]; } } - (void)setHideThumbnailButton:(BOOL)hideThumbnailButton { if (hideThumbnailButton) { [_pdfActionsView.thumbnailActionView setHidden:YES]; [_pdfThumbnailView setHidden:YES]; } } - (void)setHideAnnotationButton:(BOOL)hideAnnotationButton { if (hideAnnotationButton) { [_pdfActionsView.annotationActionView setHidden:YES]; [_pdfActionsView.clearButtonView setHidden:YES]; [_pdfActionsView.applyButtonView setHidden:YES]; [_pdfActionsView.exitButtonView setHidden:YES]; } } - (void)setHideSearchButton:(BOOL)hideSearchButton { if (hideSearchButton) { [_pdfActionsView.searchActionView setHidden:YES]; [_searchBar setHidden:YES]; } } - (void)setHideShareButton:(BOOL)hideShareButton { [_pdfActionsView.shareActionView setHidden:hideShareButton]; } - (void)setupConstraints { NSMutableArray *constraints = [NSMutableArray new]; NSDictionary *views = NSDictionaryOfVariableBindings(_parentStackView); [constraints addObjectsFromArray: [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_parentStackView]|" options:(NSLayoutFormatOptions)0 metrics:nil views:views]]; [constraints addObjectsFromArray: [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_parentStackView]|" options:(NSLayoutFormatOptions)0 metrics:nil views:views]]; [NSLayoutConstraint activateConstraints:constraints]; } - (void)searchBarDismissKeyboard { [_searchBar resignFirstResponder]; if (_keyboardUnderlapView) { _keyboardUnderlapView.hidden = YES; } } - (BOOL)pdfModified { return _annotationsAdded; } - (void)animateViews:(NSArray *)views setHidden:(BOOL)hidden { [UIView animateWithDuration:PDFhideViewAnimationDuration animations:^{ for (UIView *view in views) { [view setHidden:hidden]; } }]; } - (PDFDocument *)getDocument { return _pdfView.document; } #pragma mark UISearchBarDelegate - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { [_pdfView.document beginFindString:searchText withOptions:NSCaseInsensitiveSearch]; } - (void)didMatchString:(PDFSelection *)instance { instance.color = [UIColor yellowColor]; [_pdfView setCurrentSelection:instance animate:YES]; } - (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar { [_pdfView.document beginFindString:searchBar.text withOptions:NSCaseInsensitiveSearch]; [self searchBarDismissKeyboard]; } - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { [searchBar resignFirstResponder]; } - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillAppear:) name:UIKeyboardWillShowNotification object:nil]; } - (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar { if (_keyboardUnderlapView) { _keyboardUnderlapView.hidden = YES; } } // Called when the UIKeyboardDidShowNotification is sent. - (void)keyboardWillAppear:(NSNotification *)aNotification { NSDictionary *userInfo = aNotification.userInfo; CGSize keyboardSize = ((NSValue *)userInfo[UIKeyboardFrameEndUserInfoKey]).CGRectValue.size; // Offset with assumed view controller's navigation container's height. keyboardSize.height = keyboardSize.height - 200.0; if (_keyboardUnderlapView && _keyboardUnderlapView.isHidden) { [_keyboardUnderlapView removeFromSuperview]; [NSLayoutConstraint constraintWithItem:_keyboardUnderlapView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:keyboardSize.height].active = YES; _keyboardUnderlapView.hidden = NO; [_parentStackView insertArrangedSubview:_keyboardUnderlapView atIndex:[[_parentStackView subviews] count]]; } } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (void)updateShareButton { _isShareActive = NO; [self updateActionButtonsAppearance]; } #pragma mark ORKFreehandDrawingViewDelegate - (void)freehandDrawingViewDidEditImage:(ORKFreehandDrawingView *)freehandDrawingView { [self updateClearApplyAnnotationButtons]; } #pragma mark PDFDocumentDelegate - (void)documentDidUnlock:(NSNotification *)notification { [self setEnableAllButtons:YES]; } @end