summaryrefslogtreecommitdiff
path: root/platform/ios/Classes/MuDocumentController.m
diff options
context:
space:
mode:
Diffstat (limited to 'platform/ios/Classes/MuDocumentController.m')
-rw-r--r--platform/ios/Classes/MuDocumentController.m1181
1 files changed, 0 insertions, 1181 deletions
diff --git a/platform/ios/Classes/MuDocumentController.m b/platform/ios/Classes/MuDocumentController.m
deleted file mode 100644
index 2a070b71..00000000
--- a/platform/ios/Classes/MuDocumentController.m
+++ /dev/null
@@ -1,1181 +0,0 @@
-#include "common.h"
-
-#import "MuPageViewNormal.h"
-#import "MuPageViewReflow.h"
-#import "MuDocumentController.h"
-#import "MuTextFieldController.h"
-#import "MuChoiceFieldController.h"
-#import "MuPrintPageRenderer.h"
-
-#define GAP 20
-#define INDICATOR_Y -44-24
-#define SLIDER_W (width - GAP - 24)
-#define SEARCH_W (width - GAP - 170)
-#define MIN_SCALE (1.0)
-#define MAX_SCALE (5.0)
-
-static NSString *const AlertTitle = @"Save Document?";
-// Correct functioning of the app relies on CloseAlertMessage and ShareAlertMessage differing
-static NSString *const CloseAlertMessage = @"Changes have been made to the document that will be lost if not saved";
-static NSString *const ShareAlertMessage = @"Your changes will not be shared unless the document is first saved";
-
-static void flattenOutline(NSMutableArray *titles, NSMutableArray *pages, fz_outline *outline, int level)
-{
- char indent[8*4+1];
- if (level > 8)
- level = 8;
- memset(indent, ' ', level * 4);
- indent[level * 4] = 0;
- while (outline)
- {
- int page = outline->page;
- if (page >= 0 && outline->title)
- {
- NSString *title = @(outline->title);
- [titles addObject: [NSString stringWithFormat: @"%s%@", indent, title]];
- [pages addObject: @(page)];
- }
- flattenOutline(titles, pages, outline->down, level + 1);
- outline = outline->next;
- }
-}
-
-static char *tmp_path(const char *path)
-{
- int f;
- char *buf = malloc(strlen(path) + 6 + 1);
- if (!buf)
- return NULL;
-
- strcpy(buf, path);
- strcat(buf, "XXXXXX");
-
- f = mkstemp(buf);
-
- if (f >= 0)
- {
- close(f);
- return buf;
- }
- else
- {
- free(buf);
- return NULL;
- }
-}
-
-static void saveDoc(const char *current_path, fz_document *doc)
-{
- char *tmp;
- pdf_document *idoc = pdf_specifics(ctx, doc);
- pdf_write_options opts = { 0 };
-
- opts.do_incremental = 1;
-
- if (!idoc)
- return;
-
- tmp = tmp_path(current_path);
- if (tmp)
- {
- int written = 0;
-
- fz_var(written);
- fz_try(ctx)
- {
- FILE *fin = fopen(current_path, "rb");
- FILE *fout = fopen(tmp, "wb");
- char buf[256];
- size_t n;
- int err = 1;
-
- if (fin && fout)
- {
- while ((n = fread(buf, 1, sizeof(buf), fin)) > 0)
- fwrite(buf, 1, n, fout);
- err = (ferror(fin) || ferror(fout));
- }
-
- if (fin)
- fclose(fin);
- if (fout)
- fclose(fout);
-
- if (!err)
- {
- pdf_save_document(ctx, idoc, tmp, &opts);
- written = 1;
- }
- }
- fz_catch(ctx)
- {
- written = 0;
- }
-
- if (written)
- {
- rename(tmp, current_path);
- }
-
- free(tmp);
- }
-}
-
-@implementation MuDocumentController
-{
- fz_document *doc;
- MuDocRef *docRef;
- NSString *key;
- NSString *_filePath;
- BOOL reflowMode;
- MuOutlineController *outline;
- UIScrollView *canvas;
- UILabel *indicator;
- UISlider *slider;
- UISearchBar *searchBar;
- UIBarButtonItem *nextButton, *prevButton, *cancelButton, *searchButton, *outlineButton, *linkButton;
- UIBarButtonItem *moreButton;
- UIBarButtonItem *shareButton, *printButton, *annotButton;
- UIBarButtonItem *highlightButton, *underlineButton, *strikeoutButton;
- UIBarButtonItem *inkButton;
- UIBarButtonItem *tickButton;
- UIBarButtonItem *deleteButton;
- UIBarButtonItem *reflowButton;
- UIBarButtonItem *backButton;
- UIBarButtonItem *sliderWrapper;
- int barmode;
- int searchPage;
- int cancelSearch;
- int showLinks;
- int width; // current screen size
- int height;
- int current; // currently visible page
- int scroll_animating; // stop view updates during scrolling animations
- float scale; // scale applied to views (only used in reflow mode)
- BOOL _isRotating;
-}
-
-- (instancetype) initWithFilename: (NSString*)filename path:(NSString *)cstr document: (MuDocRef *)aDoc
-{
- self = [super initWithNibName:nil bundle:nil];
- if (!self)
- return nil;
-
-#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
- if ([self respondsToSelector:@selector(automaticallyAdjustsScrollViewInsets)])
- self.automaticallyAdjustsScrollViewInsets = NO;
-#endif
- key = [filename copy];
- docRef = [aDoc retain];
- doc = docRef->doc;
- _filePath = [cstr copy];
-
- // this will be created right before the outline is shown
- outline = nil;
-
- dispatch_sync(queue, ^{});
-
- return self;
-}
-
-- (UIBarButtonItem *) newResourceBasedButton:(NSString *)resource withAction:(SEL)selector
-{
- if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
- {
- return [[UIBarButtonItem alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:resource ofType:@"png"]] style:UIBarButtonItemStylePlain target:self action:selector];
- }
- else
- {
- UIView *buttonView;
- BOOL iOS7Style = (([UIDevice currentDevice].systemVersion).floatValue >= 7.0f);
- UIButton *button = [UIButton buttonWithType:iOS7Style ? UIButtonTypeSystem : UIButtonTypeCustom];
- [button setImage:[UIImage imageNamed:resource] forState:UIControlStateNormal];
- [button addTarget:self action:selector forControlEvents:UIControlEventTouchUpInside];
- [button sizeToFit];
- buttonView = button;
-
- return [[UIBarButtonItem alloc] initWithCustomView:buttonView];
- }
-}
-
-- (void) addMainMenuButtons
-{
- NSMutableArray *array = [NSMutableArray arrayWithCapacity:3];
- [array addObject:moreButton];
- [array addObject:searchButton];
- if (outlineButton)
- [array addObject:outlineButton];
- [array addObject:reflowButton];
- [array addObject:linkButton];
- self.navigationItem.rightBarButtonItems = array ;
- self.navigationItem.leftBarButtonItem = backButton;
-}
-
-- (void) loadView
-{
- [[NSUserDefaults standardUserDefaults] setObject: key forKey: @"OpenDocumentKey"];
-
- current = (int)[[NSUserDefaults standardUserDefaults] integerForKey: key];
- if (current < 0 || current >= fz_count_pages(ctx, doc))
- current = 0;
-
- UIView *view = [[UIView alloc] initWithFrame: CGRectZero];
- view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
- [view setAutoresizesSubviews: YES];
- view.backgroundColor = [UIColor grayColor];
-
- canvas = [[UIScrollView alloc] initWithFrame: CGRectMake(0,0,GAP,0)];
- canvas.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
- [canvas setPagingEnabled: YES];
- [canvas setShowsHorizontalScrollIndicator: NO];
- [canvas setShowsVerticalScrollIndicator: NO];
- canvas.delegate = self;
-
- UITapGestureRecognizer *tapRecog = [[UITapGestureRecognizer alloc] initWithTarget: self action: @selector(onTap:)];
- tapRecog.delegate = self;
- [canvas addGestureRecognizer: tapRecog];
- [tapRecog release];
- // In reflow mode, we need to track pinch gestures on the canvas and pass
- // the scale changes to the subviews.
- UIPinchGestureRecognizer *pinchRecog = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(onPinch:)];
- pinchRecog.delegate = self;
- [canvas addGestureRecognizer:pinchRecog];
- [pinchRecog release];
-
- scale = 1.0;
-
- scroll_animating = NO;
-
- indicator = [[UILabel alloc] initWithFrame: CGRectZero];
- indicator.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin;
- indicator.text = @"0000 of 9999";
- [indicator sizeToFit];
- indicator.center = CGPointMake(0, INDICATOR_Y);
- indicator.textAlignment = NSTextAlignmentCenter;
- indicator.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent: 0.5];
- indicator.textColor = [UIColor whiteColor];
-
- [view addSubview: canvas];
- [view addSubview: indicator];
-
- slider = [[UISlider alloc] initWithFrame: CGRectZero];
- slider.minimumValue = 0;
- slider.maximumValue = fz_count_pages(ctx, doc) - 1;
- [slider addTarget: self action: @selector(onSlide:) forControlEvents: UIControlEventValueChanged];
-
- if ([UIDevice currentDevice].systemVersion.floatValue < 7.0)
- {
- sliderWrapper = [[UIBarButtonItem alloc] initWithCustomView: slider];
-
- self.toolbarItems = @[sliderWrapper];
- }
-
- // Set up the buttons on the navigation and search bar
-
- fz_outline *outlineRoot;
- fz_try(ctx)
- outlineRoot = fz_load_outline(ctx, doc);
- fz_catch(ctx)
- outlineRoot = NULL;
- if (outlineRoot)
- {
- // only show the outline button if there is an outline
- outlineButton = [self newResourceBasedButton:@"ic_list" withAction:@selector(onShowOutline:)];
- fz_drop_outline(ctx, outlineRoot);
- }
-
- linkButton = [self newResourceBasedButton:@"ic_link" withAction:@selector(onToggleLinks:)];
- cancelButton = [self newResourceBasedButton:@"ic_cancel" withAction:@selector(onCancel:)];
- searchButton = [self newResourceBasedButton:@"ic_magnifying_glass" withAction:@selector(onShowSearch:)];
- prevButton = [self newResourceBasedButton:@"ic_arrow_left" withAction:@selector(onSearchPrev:)];
- nextButton = [self newResourceBasedButton:@"ic_arrow_right" withAction:@selector(onSearchNext:)];
- reflowButton = [self newResourceBasedButton:@"ic_reflow" withAction:@selector(onToggleReflow:)];
- moreButton = [self newResourceBasedButton:@"ic_more" withAction:@selector(onMore:)];
- annotButton = [self newResourceBasedButton:@"ic_annotation" withAction:@selector(onAnnot:)];
- shareButton = [self newResourceBasedButton:@"ic_share" withAction:@selector(onShare:)];
- printButton = [self newResourceBasedButton:@"ic_print" withAction:@selector(onPrint:)];
- highlightButton = [self newResourceBasedButton:@"ic_highlight" withAction:@selector(onHighlight:)];
- underlineButton = [self newResourceBasedButton:@"ic_underline" withAction:@selector(onUnderline:)];
- strikeoutButton = [self newResourceBasedButton:@"ic_strike" withAction:@selector(onStrikeout:)];
- inkButton = [self newResourceBasedButton:@"ic_pen" withAction:@selector(onInk:)];
- tickButton = [self newResourceBasedButton:@"ic_check" withAction:@selector(onTick:)];
- deleteButton = [self newResourceBasedButton:@"ic_trash" withAction:@selector(onDelete:)];
- searchBar = [[UISearchBar alloc] initWithFrame: CGRectMake(0,0,50,32)];
- backButton = [self newResourceBasedButton:@"ic_arrow_left" withAction:@selector(onBack:)];
- searchBar.placeholder = @"Search";
- searchBar.delegate = self;
-
- [prevButton setEnabled: NO];
- [nextButton setEnabled: NO];
-
- [self addMainMenuButtons];
-
- // TODO: add activityindicator to search bar
-
- self.view = view;
- [view release];
-}
-
-- (void) dealloc
-{
- [docRef release]; docRef = nil; doc = NULL;
- [indicator release]; indicator = nil;
- [slider release]; slider = nil;
- [sliderWrapper release]; sliderWrapper = nil;
- [reflowButton release]; reflowButton = nil;
- [backButton release]; backButton = nil;
- [moreButton release]; moreButton = nil;
- [searchBar release]; searchBar = nil;
- [outlineButton release]; outlineButton = nil;
- [linkButton release]; linkButton = nil;
- [searchButton release]; searchButton = nil;
- [cancelButton release]; cancelButton = nil;
- [prevButton release]; prevButton = nil;
- [nextButton release]; nextButton = nil;
- [shareButton release]; shareButton = nil;
- [printButton release]; printButton = nil;
- [annotButton release]; annotButton = nil;
- [highlightButton release]; highlightButton = nil;
- [underlineButton release]; underlineButton = nil;
- [strikeoutButton release]; strikeoutButton = nil;
- [inkButton release]; inkButton = nil;
- [tickButton release]; tickButton = nil;
- [deleteButton release]; deleteButton = nil;
- [canvas release]; canvas = nil;
- [_filePath release]; _filePath = NULL;
-
- [outline release];
- [key release];
- [super dealloc];
-}
-
-- (void) viewWillAppear: (BOOL)animated
-{
- [super viewWillAppear:animated];
- self.title = key.lastPathComponent;
-
- slider.value = current;
-
- if ([UIDevice currentDevice].systemVersion.floatValue >= 7.0)
- [self.navigationController.toolbar addSubview:slider];
-
- indicator.text = [NSString stringWithFormat: @" %d of %d ", current+1, fz_count_pages(ctx, doc)];
-
- [self.navigationController setToolbarHidden: NO animated: animated];
-}
-
-- (void) viewWillLayoutSubviews
-{
- CGSize size = canvas.frame.size;
- int max_width = fz_max(width, size.width);
-
- width = size.width;
- height = size.height;
-
- canvas.contentInset = UIEdgeInsetsZero;
- canvas.contentSize = CGSizeMake(fz_count_pages(ctx, doc) * width, height);
- canvas.contentOffset = CGPointMake(current * width, 0);
-
- [sliderWrapper setWidth: SLIDER_W];
- searchBar.frame = CGRectMake(0,0,SEARCH_W,32);
- if ([UIDevice currentDevice].systemVersion.floatValue >= 7.0)
- {
- CGRect r = self.navigationController.toolbar.frame;
- r.origin.x = 0;
- r.origin.y = 0;
- slider.frame = r;
- }
-
- [self.navigationController.toolbar setNeedsLayout]; // force layout!
-
- // use max_width so we don't clamp the content offset too early during animation
- canvas.contentSize = CGSizeMake(fz_count_pages(ctx, doc) * max_width, height);
- canvas.contentOffset = CGPointMake(current * width, 0);
-
- for (UIView<MuPageView> *view in canvas.subviews) {
- if (view.number == current) {
- view.frame = CGRectMake(view.number * width, 0, width-GAP, height);
- [view willRotate];
- }
- }
- for (UIView<MuPageView> *view in canvas.subviews) {
- if (view.number != current) {
- view.frame = CGRectMake(view.number * width, 0, width-GAP, height);
- [view willRotate];
- }
- }
-}
-
-- (void) viewDidAppear: (BOOL)animated
-{
- [super viewDidAppear:animated];
- [self scrollViewDidScroll: canvas];
-}
-
-- (void) viewWillDisappear: (BOOL)animated
-{
- [super viewWillDisappear:animated];
- if ([UIDevice currentDevice].systemVersion.floatValue >= 7.0)
- [slider removeFromSuperview];
-
- self.title = @"Resume";
- [[NSUserDefaults standardUserDefaults] removeObjectForKey: @"OpenDocumentKey"];
- [self.navigationController setToolbarHidden: YES animated: animated];
-}
-
-- (void) showNavigationBar
-{
- if (self.navigationController.navigationBarHidden) {
- [sliderWrapper setWidth: SLIDER_W];
- if ([UIDevice currentDevice].systemVersion.floatValue >= 7.0)
- {
- CGRect r = self.navigationController.toolbar.frame;
- r.origin.x = 0;
- r.origin.y = 0;
- slider.frame = r;
- }
- [self.navigationController setNavigationBarHidden: NO];
- [self.navigationController setToolbarHidden: NO];
- [indicator setHidden: NO];
-
- [UIView beginAnimations: @"MuNavBar" context: NULL];
-
- self.navigationController.navigationBar.alpha = 1;
- self.navigationController.toolbar.alpha = 1;
- indicator.alpha = 1;
-
- [UIView commitAnimations];
- }
-}
-
-- (void) hideNavigationBar
-{
- if (!self.navigationController.navigationBarHidden) {
- [searchBar resignFirstResponder];
-
- [UIView beginAnimations: @"MuNavBar" context: NULL];
- [UIView setAnimationDelegate: self];
- [UIView setAnimationDidStopSelector: @selector(onHideNavigationBarFinished)];
-
- self.navigationController.navigationBar.alpha = 0;
- self.navigationController.toolbar.alpha = 0;
- indicator.alpha = 0;
-
- [UIView commitAnimations];
- }
-}
-
-- (void) onHideNavigationBarFinished
-{
- [self.navigationController setNavigationBarHidden: YES];
- [self.navigationController setToolbarHidden: YES];
- [indicator setHidden: YES];
-}
-
-- (void) onShowOutline: (id)sender
-{
- // rebuild the outline in case the layout has changed
- fz_outline *root;
- fz_try(ctx)
- root = fz_load_outline(ctx, doc);
- fz_catch(ctx)
- root = NULL;
- if (root)
- {
- NSMutableArray *titles = [[NSMutableArray alloc] init];
- NSMutableArray *pages = [[NSMutableArray alloc] init];
- flattenOutline(titles, pages, root, 0);
- [outline release];
- if (titles.count)
- outline = [[MuOutlineController alloc] initWithTarget: self titles: titles pages: pages];
- [titles release];
- [pages release];
- fz_drop_outline(ctx, root);
- }
-
- // now show it
-
- [self.navigationController pushViewController: outline animated: YES];
-}
-
-- (void) onToggleLinks: (id)sender
-{
- showLinks = !showLinks;
- for (UIView<MuPageView> *view in canvas.subviews)
- {
- if (showLinks)
- [view showLinks];
- else
- [view hideLinks];
- }
-}
-
-- (void) onToggleReflow: (id)sender
-{
- reflowMode = !reflowMode;
-
- annotButton.enabled = !reflowMode;
- searchButton.enabled = !reflowMode;
- linkButton.enabled = !reflowMode;
- moreButton.enabled = !reflowMode;
-
- [canvas.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
- [self scrollViewDidScroll:canvas];
-}
-
-- (void) showMoreMenu
-{
- NSMutableArray *rightbuttons = [NSMutableArray arrayWithObjects:printButton, shareButton, nil];
- if (docRef->interactive)
- [rightbuttons insertObject:annotButton atIndex:0];
- self.navigationItem.rightBarButtonItems = rightbuttons;
- self.navigationItem.leftBarButtonItem = cancelButton;
-
- barmode = BARMODE_MORE;
-}
-
-- (void) showAnnotationMenu
-{
- self.navigationItem.rightBarButtonItems = @[inkButton, strikeoutButton, underlineButton, highlightButton];
- self.navigationItem.leftBarButtonItem = cancelButton;
-
- for (UIView<MuPageView> *view in canvas.subviews)
- {
- if (view.number == current)
- [view deselectAnnotation];
- }
-
- barmode = BARMODE_ANNOTATION;
-}
-
-- (void) update
-{
- for (UIView<MuPageView> *view in canvas.subviews)
- [view update];
-}
-
-- (void) onMore: (id)sender
-{
- [self showMoreMenu];
-}
-
-- (void) onAnnot: (id)sender
-{
- [self showAnnotationMenu];
-}
-
-- (void) onPrint: (id)sender
-{
- UIPrintInteractionController *pic = [UIPrintInteractionController sharedPrintController];
- if (pic) {
- UIPrintInfo *printInfo = [UIPrintInfo printInfo];
- printInfo.outputType = UIPrintInfoOutputGeneral;
- printInfo.jobName = key;
- printInfo.duplex = UIPrintInfoDuplexLongEdge;
- pic.printInfo = printInfo;
- pic.showsPageRange = YES;
- pic.printPageRenderer = [[[MuPrintPageRenderer alloc] initWithDocRef:docRef] autorelease];
-
- void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) =
- ^(UIPrintInteractionController *pic, BOOL completed, NSError *error) {
- if (!completed && error)
- NSLog(@"FAILED! due to error in domain %@ with error code %u",
- error.domain, (unsigned int)error.code);
- };
- if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
- [pic presentFromBarButtonItem:printButton animated:YES
- completionHandler:completionHandler];
- } else {
- [pic presentAnimated:YES completionHandler:completionHandler];
- }
- }
-}
-
-- (void) shareDocument
-{
- NSURL *url = [NSURL fileURLWithPath:_filePath];
- UIActivityViewController *cont = [[UIActivityViewController alloc] initWithActivityItems:@[url] applicationActivities:nil];
- cont.popoverPresentationController.barButtonItem = shareButton;
- [self presentViewController:cont animated:YES completion:nil];
- [cont release];
-}
-
-- (void) onShare: (id)sender
-{
- pdf_document *idoc = pdf_specifics(ctx, doc);
- if (idoc && pdf_has_unsaved_changes(ctx, idoc))
- {
- UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:AlertTitle message:ShareAlertMessage delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Save and Share", nil];
- [alertView show];
- [alertView release];
- }
- else
- {
- [self shareDocument];
- }
-}
-
-- (void) textSelectModeOn
-{
- self.navigationItem.rightBarButtonItems = @[tickButton];
- for (UIView<MuPageView> *view in canvas.subviews)
- {
- if (view.number == current)
- [view textSelectModeOn];
- }
-}
-
-- (void) textSelectModeOff
-{
- for (UIView<MuPageView> *view in canvas.subviews)
- {
- [view textSelectModeOff];
- }
-}
-
-- (void) inkModeOn
-{
- self.navigationItem.rightBarButtonItems = @[tickButton];
- for (UIView<MuPageView> *view in canvas.subviews)
- {
- if (view.number == current)
- [view inkModeOn];
- }
-}
-
-- (void) deleteModeOn
-{
- self.navigationItem.rightBarButtonItems = @[deleteButton];
- barmode = BARMODE_DELETE;
-}
-
-- (void) inkModeOff
-{
- for (UIView<MuPageView> *view in canvas.subviews)
- {
- [view inkModeOff];
- }
-}
-
-- (void) onHighlight: (id)sender
-{
- barmode = BARMODE_HIGHLIGHT;
- [self textSelectModeOn];
-}
-
-- (void) onUnderline: (id)sender
-{
- barmode = BARMODE_UNDERLINE;
- [self textSelectModeOn];
-}
-
-- (void) onStrikeout: (id)sender
-{
- barmode = BARMODE_STRIKE;
- [self textSelectModeOn];
-}
-
-- (void) onInk: (id)sender
-{
- barmode = BARMODE_INK;
- [self inkModeOn];
-}
-
-- (void) onShowSearch: (id)sender
-{
- self.navigationItem.rightBarButtonItems = @[nextButton, prevButton];
- self.navigationItem.leftBarButtonItem = cancelButton;
- self.navigationItem.titleView = searchBar;
- [searchBar becomeFirstResponder];
- barmode = BARMODE_SEARCH;
-}
-
-- (void) onTick: (id)sender
-{
- for (UIView<MuPageView> *view in canvas.subviews)
- {
- if (view.number == current)
- {
- switch (barmode)
- {
- case BARMODE_HIGHLIGHT:
- [view saveSelectionAsMarkup:PDF_ANNOT_HIGHLIGHT];
- break;
-
- case BARMODE_UNDERLINE:
- [view saveSelectionAsMarkup:PDF_ANNOT_UNDERLINE];
- break;
-
- case BARMODE_STRIKE:
- [view saveSelectionAsMarkup:PDF_ANNOT_STRIKE_OUT];
- break;
-
- case BARMODE_INK:
- [view saveInk];
- }
- }
- }
-
- [self showAnnotationMenu];
-}
-
-- (void) onDelete: (id)sender
-{
- for (UIView<MuPageView> *view in canvas.subviews)
- {
- if (view.number == current)
- [view deleteSelectedAnnotation];
- }
- [self showAnnotationMenu];
-}
-
-- (void) onCancel: (id)sender
-{
- switch (barmode)
- {
- case BARMODE_SEARCH:
- cancelSearch = YES;
- [searchBar resignFirstResponder];
- [self resetSearch];
- /* fallthrough */
- case BARMODE_ANNOTATION:
- case BARMODE_MORE:
- [self.navigationItem setTitleView: nil];
- [self addMainMenuButtons];
- barmode = BARMODE_MAIN;
- break;
-
- case BARMODE_HIGHLIGHT:
- case BARMODE_UNDERLINE:
- case BARMODE_STRIKE:
- case BARMODE_DELETE:
- [self showAnnotationMenu];
- [self textSelectModeOff];
- break;
-
- case BARMODE_INK:
- [self showAnnotationMenu];
- [self inkModeOff];
- break;
- }
-}
-
-- (void) onBack: (id)sender
-{
- pdf_document *idoc = pdf_specifics(ctx, doc);
- if (idoc && pdf_has_unsaved_changes(ctx, idoc))
- {
- UIAlertView *saveAlert = [[UIAlertView alloc]
- initWithTitle:AlertTitle message:CloseAlertMessage delegate:self
- cancelButtonTitle:@"Discard" otherButtonTitles:@"Save", nil];
- [saveAlert show];
- [saveAlert release];
- }
- else
- {
- [self.navigationController popViewControllerAnimated:YES];
- }
-}
-
-- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
-{
- if ([CloseAlertMessage isEqualToString:alertView.message])
- {
- if (buttonIndex == 1)
- saveDoc(_filePath.UTF8String, doc);
-
- [alertView dismissWithClickedButtonIndex:buttonIndex animated:YES];
- [self.navigationController popViewControllerAnimated:YES];
- }
-
- if ([ShareAlertMessage isEqualToString:alertView.message])
- {
- [alertView dismissWithClickedButtonIndex:buttonIndex animated:NO];
- if (buttonIndex == 1)
- {
- saveDoc(_filePath.UTF8String, doc);
- [self shareDocument];
- }
- }
-}
-
-- (void) resetSearch
-{
- searchPage = -1;
- for (UIView<MuPageView> *view in canvas.subviews)
- [view clearSearchResults];
-}
-
-- (void) showSearchResults: (int)count forPage: (int)number
-{
- printf("search found match on page %d\n", number);
- searchPage = number;
- [self gotoPage: number animated: NO];
- for (UIView<MuPageView> *view in canvas.subviews)
- if (view.number == number)
- [view showSearchResults: count];
- else
- [view clearSearchResults];
-}
-
-- (void) searchInDirection: (int)dir
-{
- UITextField *searchField;
- char *needle;
- int start;
-
- [searchBar resignFirstResponder];
-
- if (searchPage == current)
- start = current + dir;
- else
- start = current;
-
- needle = strdup(searchBar.text.UTF8String);
-
- searchField = nil;
- for (id view in searchBar.subviews)
- if ([view isKindOfClass: [UITextField class]])
- searchField = view;
-
- [prevButton setEnabled: NO];
- [nextButton setEnabled: NO];
- [searchField setEnabled: NO];
-
- cancelSearch = NO;
-
- dispatch_async(queue, ^{
- for (int i = start; i >= 0 && i < fz_count_pages(ctx, doc); i += dir) {
- int n = search_page(doc, i, needle, NULL);
- if (n) {
- dispatch_async(dispatch_get_main_queue(), ^{
- [prevButton setEnabled: YES];
- [nextButton setEnabled: YES];
- [searchField setEnabled: YES];
- [self showSearchResults: n forPage: i];
- free(needle);
- });
- return;
- }
- if (cancelSearch) {
- dispatch_async(dispatch_get_main_queue(), ^{
- [prevButton setEnabled: YES];
- [nextButton setEnabled: YES];
- [searchField setEnabled: YES];
- free(needle);
- });
- return;
- }
- }
- dispatch_async(dispatch_get_main_queue(), ^{
- printf("no search results found\n");
- [prevButton setEnabled: YES];
- [nextButton setEnabled: YES];
- [searchField setEnabled: YES];
- UIAlertView *alert = [[UIAlertView alloc]
- initWithTitle: @"No matches found for:"
- message: @(needle)
- delegate: nil
- cancelButtonTitle: @"Close"
- otherButtonTitles: nil];
- [alert show];
- [alert release];
- free(needle);
- });
- });
-}
-
-- (void) onSearchPrev: (id)sender
-{
- [self searchInDirection: -1];
-}
-
-- (void) onSearchNext: (id)sender
-{
- [self searchInDirection: 1];
-}
-
-- (void) searchBarSearchButtonClicked: (UISearchBar*)sender
-{
- [self onSearchNext: sender];
-}
-
-- (void) searchBar: (UISearchBar*)sender textDidChange: (NSString*)searchText
-{
- [self resetSearch];
- if (searchBar.text.length > 0) {
- [prevButton setEnabled: YES];
- [nextButton setEnabled: YES];
- } else {
- [prevButton setEnabled: NO];
- [nextButton setEnabled: NO];
- }
-}
-
-- (void) onSlide: (id)sender
-{
- int number = slider.value;
- if (slider.tracking)
- indicator.text = [NSString stringWithFormat: @" %d of %d ", number+1, fz_count_pages(ctx, doc)];
- else
- [self gotoPage: number animated: NO];
-}
-
-- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
-{
- // For reflow mode, we load UIWebViews into the canvas. Returning YES
- // here prevents them stealing our tap and pinch events.
- return YES;
-}
-
-- (void) onTap: (UITapGestureRecognizer*)sender
-{
- CGPoint p = [sender locationInView: canvas];
- CGPoint ofs = canvas.contentOffset;
- float x0 = (width - GAP) / 5;
- float x1 = (width - GAP) - x0;
- p.x -= ofs.x;
- p.y -= ofs.y;
- __block BOOL tapHandled = NO;
- for (UIView<MuPageView> *view in canvas.subviews)
- {
- CGPoint pp = [sender locationInView:view];
- if (CGRectContainsPoint(view.bounds, pp))
- {
- MuTapResult *result = [view handleTap:pp];
- __block BOOL hitAnnot = NO;
- [result switchCaseInternal:^(MuTapResultInternalLink *link) {
- [self gotoPage:link.pageNumber animated:NO];
- tapHandled = YES;
- } caseExternal:^(MuTapResultExternalLink *link) {
- // Not currently supported
- } caseRemote:^(MuTapResultRemoteLink *link) {
- // Not currently supported
- } caseWidget:^(MuTapResultWidget *widget) {
- tapHandled = YES;
- } caseAnnotation:^(MuTapResultAnnotation *annot) {
- hitAnnot = YES;
- }];
-
- switch (barmode)
- {
- case BARMODE_ANNOTATION:
- if (hitAnnot)
- [self deleteModeOn];
- tapHandled = YES;
- break;
-
- case BARMODE_DELETE:
- if (!hitAnnot)
- [self showAnnotationMenu];
- tapHandled = YES;
- break;
-
- default:
- if (hitAnnot)
- {
- // Annotation will have been selected, which is wanted
- // only in annotation-editing mode
- [view deselectAnnotation];
- }
- break;
- }
-
- if (tapHandled)
- break;
- }
- }
- if (tapHandled) {
- // Do nothing further
- } else if (p.x < x0) {
- [self gotoPage: current-1 animated: YES];
- } else if (p.x > x1) {
- [self gotoPage: current+1 animated: YES];
- } else {
- if (self.navigationController.navigationBarHidden)
- [self showNavigationBar];
- else if (barmode == BARMODE_MAIN)
- [self hideNavigationBar];
- }
-}
-
-- (void) onPinch:(UIPinchGestureRecognizer*)sender
-{
- if (sender.state == UIGestureRecognizerStateBegan)
- sender.scale = scale;
-
- if (sender.scale < MIN_SCALE)
- sender.scale = MIN_SCALE;
-
- if (sender.scale > MAX_SCALE)
- sender.scale = MAX_SCALE;
-
- if (sender.state == UIGestureRecognizerStateEnded)
- scale = sender.scale;
-
- for (UIView<MuPageView> *view in canvas.subviews)
- {
- // Zoom only the visible page until end of gesture
- if (view.number == current || sender.state == UIGestureRecognizerStateEnded)
- [view setScale:sender.scale];
- }
-}
-
-- (void) scrollViewWillBeginDragging: (UIScrollView *)scrollView
-{
- if (barmode == BARMODE_MAIN)
- [self hideNavigationBar];
-}
-
-- (void) scrollViewDidScroll: (UIScrollView*)scrollview
-{
- // scrollViewDidScroll seems to get called part way through a screen rotation.
- // (This is possibly a UIScrollView bug - see
- // http://stackoverflow.com/questions/4123991/uiscrollview-disable-scrolling-while-rotating-on-iphone-ipad/8141423#8141423 ).
- // This ends up corrupting the current page number, because the calculation
- // 'current = x / width' is using the new value of 'width' before the
- // pages have been resized/repositioned. To avoid this problem, we filter out
- // calls to scrollViewDidScroll during rotation.
- if (_isRotating)
- return;
-
- if (width == 0)
- return; // not visible yet
-
- if (scroll_animating)
- return; // don't mess with layout during animations
-
- float x = canvas.contentOffset.x + width * 0.5f;
- current = x / width;
-
- [[NSUserDefaults standardUserDefaults] setInteger: current forKey: key];
-
- indicator.text = [NSString stringWithFormat: @" %d of %d ", current+1, fz_count_pages(ctx, doc)];
- slider.value = current;
-
- // swap the distant page views out
-
- NSMutableSet *invisiblePages = [[NSMutableSet alloc] init];
- for (UIView<MuPageView> *view in canvas.subviews) {
- if (view.number != current)
- [view resetZoomAnimated: YES];
- if (view.number < current - 2 || view.number > current + 2)
- [invisiblePages addObject: view];
- }
- for (UIView<MuPageView> *view in invisiblePages)
- [view removeFromSuperview];
- [invisiblePages release]; // don't bother recycling them...
-
- [self createPageView: current];
- [self createPageView: current - 1];
- [self createPageView: current + 1];
-
- // reset search results when page has flipped
- if (current != searchPage)
- [self resetSearch];
-}
-
-- (void) createPageView: (int)number
-{
- if (number < 0 || number >= fz_count_pages(ctx, doc))
- return;
- int found = 0;
- for (UIView<MuPageView> *view in canvas.subviews)
- if (view.number == number)
- found = 1;
- if (!found) {
- UIView<MuPageView> *view
- = reflowMode
- ? [[MuPageViewReflow alloc] initWithFrame:CGRectMake(number * width, 0, width-GAP, height) document:docRef page:number]
- : [[MuPageViewNormal alloc] initWithFrame:CGRectMake(number * width, 0, width-GAP, height) dialogCreator:self updater:self document:docRef page:number];
- [view setScale:scale];
- [canvas addSubview: view];
- if (showLinks)
- [view showLinks];
- [view release];
- }
-}
-
-- (void) gotoPage: (int)number animated: (BOOL)animated
-{
- if (number < 0)
- number = 0;
- if (number >= fz_count_pages(ctx, doc))
- number = fz_count_pages(ctx, doc) - 1;
- if (current == number)
- return;
- if (animated) {
- // setContentOffset:animated: does not use the normal animation
- // framework. It also doesn't play nice with the tap gesture
- // recognizer. So we do our own page flipping animation here.
- // We must set the scroll_animating flag so that we don't create
- // or remove subviews until after the animation, or they'll
- // swoop in from origo during the animation.
-
- scroll_animating = YES;
- [UIView beginAnimations: @"MuScroll" context: NULL];
- [UIView setAnimationDuration: 0.4];
- [UIView setAnimationBeginsFromCurrentState: YES];
- [UIView setAnimationDelegate: self];
- [UIView setAnimationDidStopSelector: @selector(onGotoPageFinished)];
-
- for (UIView<MuPageView> *view in canvas.subviews)
- [view resetZoomAnimated: NO];
-
- canvas.contentOffset = CGPointMake(number * width, 0);
- slider.value = number;
- indicator.text = [NSString stringWithFormat: @" %d of %d ", number+1, fz_count_pages(ctx, doc)];
-
- [UIView commitAnimations];
- } else {
- for (UIView<MuPageView> *view in canvas.subviews)
- [view resetZoomAnimated: NO];
- canvas.contentOffset = CGPointMake(number * width, 0);
- }
- current = number;
-}
-
-- (void) invokeTextDialog:(NSString *)aString okayAction:(void (^)(NSString *))block
-{
- MuTextFieldController *tf = [[MuTextFieldController alloc] initWithText:aString okayAction:block];
- tf.modalPresentationStyle = UIModalPresentationFormSheet;
- [self presentViewController:tf animated:YES completion:nil];
- [tf release];
-}
-
-- (void) invokeChoiceDialog:(NSArray *)anArray okayAction:(void (^)(NSArray *))block
-{
- MuChoiceFieldController *cf = [[MuChoiceFieldController alloc] initWithChoices:anArray okayAction:block];
- cf.modalPresentationStyle = UIModalPresentationFormSheet;
- [self presentViewController:cf animated:YES completion:nil];
- [cf release];
-}
-
-- (void) onGotoPageFinished
-{
- scroll_animating = NO;
- [self scrollViewDidScroll: canvas];
-}
-
-- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)o
-{
- return YES;
-}
-
-- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
-{
- _isRotating = YES;
-}
-
-- (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation)o
-{
- _isRotating = NO;
-
- // We need to set these here, because during the animation we may use a wider
- // size (the maximum of the landscape/portrait widths), to avoid clipping during
- // the rotation.
- canvas.contentSize = CGSizeMake(fz_count_pages(ctx, doc) * width, height);
- canvas.contentOffset = CGPointMake(current * width, 0);
-}
-
-@end