2
* Copyright (C) 2005 Stefan Kleine Stegemann
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License
6
* as published by the Free Software Foundation; either version 2
7
* of the License, or (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
#import "Controller.h"
21
#import "CenteringClipView.h"
26
@interface Controller (Private)
27
- (Document*) _myDocument;
28
- (void) _updatePage: (NSNotification*)aNotification;
29
- (void) _zoomFactorUpdated: (NSNotification*)aNotification;
30
- (void) _toggleResizePolicy: (ResizePolicy)aPolicy;
31
- (void) _setResizePolicy: (ResizePolicy)aPolicy;
32
- (void) _setupScrollView;
33
- (void) _addDocumentTools;
34
- (void) _createSinglePageView;
35
- (void) _setInitialWindowSize;
36
- (NSRect) _calcPreferredFrameInFrame: (NSRect)maxFrame withPDFSize: (NSSize)aPDFSize;
37
- (NSSize) _calcPDFContentSize: (NSSize)aSize add: (BOOL)addToSize;
41
@implementation Controller
43
- (id) initWithWindow: (NSWindow*)aWindow
45
self = [super initWithWindow: aWindow];
60
NSLog(@"dealloc Controller");
62
[[NSNotificationCenter defaultCenter] removeObserver: self];
64
[singlePageView release];
68
- (void) windowDidLoad
70
[super windowDidLoad];
72
[self _setupScrollView];
73
[self _addDocumentTools];
74
[self _createSinglePageView];
75
[self goSinglePage: nil];
77
// initialize the SinglePageView with the document's
79
[singlePageView setDocument: [self _myDocument]];
81
[[NSNotificationCenter defaultCenter]
83
selector: @selector(_zoomFactorUpdated:)
84
name: kZoomFactorChangedNotification
85
object: singlePageView];
87
[[NSNotificationCenter defaultCenter]
89
selector: @selector(_updatePage:)
90
name: kDocumentPageChangedNotification
91
object: [self _myDocument]];
93
// setup the multipageview
94
//multipageview = [[MultiPageView alloc] initWithFrame: [pdfview frame]
96
//[multipageview setDocument: [[self _myDocument] pdfDocument]];
97
//[scrollview setDocumentView: multipageview];
99
[self _setInitialWindowSize];
101
// trigger initial setup
102
[[self _myDocument] setPageByIndex: 1];
104
// display initial zoom factor & page count
105
[tools setZoom: [singlePageView zoom]];
106
[tools setPageCount: [[self _myDocument] countPages]];
108
// setup a delegate that keeps track of the menu's state
109
menuState = [[MenuState alloc] initWithDocument: [self _myDocument]
110
contentView: singlePageView];
113
- (void) windowDidBecomeMain: (NSNotification*)aNotification
115
// We need to ensure, that the top of the content is visible
116
// right after the window appears on the screen for the first
117
// time. windowDidLoad here doesn"t work because the window manager
118
// may decide to change the window size when it is put on the
119
// screen (which takes place AFTER windowDidLoad)
120
if (!windowIsVisible)
122
[singlePageView displayContentTop];
123
windowIsVisible = YES;
126
[menuState stateChanged];
129
- (NSRect) windowWillUseStandardFrame: (NSWindow*)aWindow defaultFrame: (NSRect)aFrame
131
return [self _calcPreferredFrameInFrame: aFrame
132
withPDFSize: [singlePageView preferredSize]];
135
- (IBAction) nextPage: (id)aSender
137
[[self _myDocument] nextPage];
140
- (IBAction) previousPage: (id)aSender
142
[[self _myDocument] previousPage];
145
- (IBAction) firstPage: (id)aSender
147
[[self _myDocument] setPageByIndex: 1];
150
- (IBAction) lastPage: (id)aSender
152
[[self _myDocument] setPageByIndex: [[self _myDocument] countPages]];
155
- (IBAction) takePageFrom: (id)aSender
157
int page = [aSender intValue];
158
if ((page > 0) && (page <= [[self _myDocument] countPages]))
160
[[self _myDocument] setPageByIndex: page];
164
// if the user entered "0", go to last page
165
NSString* test = [[aSender stringValue] stringByTrimmingCharactersInSet:
166
[NSCharacterSet whitespaceCharacterSet]];
167
if ([test hasPrefix: @"0"])
169
[self lastPage: nil];
173
[self _updatePage: nil];
178
- (IBAction) enterPageNumber: (id)aSender
180
[tools focusPageField];
183
- (IBAction) takeZoomFrom: (id)aSender
185
float zoom = [aSender floatValue];
188
[singlePageView setZoom: zoom];
192
[self _zoomFactorUpdated: nil];
196
- (IBAction) zoomIn: (id)aSender
198
[self _setResizePolicy: ResizePolicyNone];
199
[singlePageView zoomIn];
202
- (IBAction) zoomOut: (id)aSender
204
[self _setResizePolicy: ResizePolicyNone];
205
[singlePageView zoomOut];
208
- (IBAction) zoomActualSize: (id)aSender
210
[self _setResizePolicy: ResizePolicyNone];
211
[singlePageView setZoom: 100.0];
214
- (IBAction) zoomToFit: (id)aSender
216
[self _setResizePolicy: ResizePolicyNone];
217
[singlePageView zoomContentToFit: [scrollView contentSize]];
220
- (IBAction) toggleFitWidth: (id)aSender
222
[self _toggleResizePolicy: ResizePolicyFitWidth];
225
- (IBAction) toggleFitHeight: (id)aSender
227
[self _toggleResizePolicy: ResizePolicyFitHeight];
230
- (IBAction) toggleFitPage: (id)aSender
232
[self _toggleResizePolicy: ResizePolicyFitPage];
235
- (IBAction) scrollPageUp: (id)aSender
237
[singlePageView scrollUpOnePage];
240
- (IBAction) scrollPageDown: (id)aSender
242
[singlePageView scrollDownOnePage];
245
- (IBAction) scrollLineUp: (id)aSender
247
[singlePageView scrollUpOneLine];
250
- (IBAction) scrollLineDown: (id)aSender
252
[singlePageView scrollDownOneLine];
255
- (IBAction) scrollToTop: (id)aSender
257
[singlePageView displayContentTop];
260
- (IBAction) scrollToBottom: (id)aSender
262
[singlePageView displayContentBottom];
265
- (IBAction) scrollLineLeft: (id)aSender
267
[singlePageView scrollLeftOneLine];
270
- (IBAction) scrollLineRight: (id)aSender
272
[singlePageView scrollRightOneLine];
275
- (IBAction) scrollToLeftEdge: (id)aSender
277
[singlePageView displayContentLeft];
280
- (IBAction) scrollToRightEdge: (id)aSender;
282
[singlePageView displayContentRight];
285
- (IBAction) goSinglePage: (id)aSender
287
[scrollView setDocumentView: singlePageView];
288
NSAssert([singlePageView paperColor], @"content view does not have a paper color");
289
[scrollView setBackgroundColor: [singlePageView paperColor]];
292
- (IBAction) close: (id)aSender
299
/* ----------------------------------------------------- */
300
/* Category Private */
301
/* ----------------------------------------------------- */
303
@implementation Controller (Private)
305
- (Document*) _myDocument
307
return (Document*)[self document];
310
- (void) _updatePage: (NSNotification*)aNotification
312
[tools setPage: [[self _myDocument] pageIndex]];
313
[singlePageView update];
316
- (void) _zoomFactorUpdated: (NSNotification*)aNotification
318
[tools setZoom: [singlePageView zoom]];
319
[singlePageView update];
322
- (void) _toggleResizePolicy: (ResizePolicy)aPolicy
324
ResizePolicy newPolicy;
326
if ([singlePageView resizePolicy] == aPolicy)
328
newPolicy = ResizePolicyNone;
335
[self _setResizePolicy: newPolicy];
338
- (void) _setResizePolicy: (ResizePolicy)aPolicy
340
if ([singlePageView resizePolicy] == aPolicy)
345
[singlePageView setResizePolicy: aPolicy];
346
[tools setResizePolicy: [singlePageView resizePolicy]];
347
[menuState stateChanged];
350
- (void) _setupScrollView
352
NSAssert(scrollView, @"scrollview not set");
354
// make the scrollview center it's document view
355
id docView = [[scrollView documentView] retain];
356
NSRect clipViewFrame = [[scrollView contentView] frame];
357
NSClipView* newClipView = [[CenteringClipView alloc] initWithFrame: clipViewFrame];
358
[newClipView setBackgroundColor: [NSColor windowBackgroundColor]];
359
[scrollView setContentView: newClipView];
360
[scrollView setDocumentView: docView];
361
[newClipView release];
364
[scrollView setHasVerticalScroller: YES];
365
[scrollView setHasHorizontalScroller: YES];
366
[scrollView setDrawsBackground: YES];
369
- (void) _addDocumentTools
371
tools = [[DocumentTools alloc] initWithFrame: NSMakeRect(0, 0, 0, 0) target: self];
373
// we need to re-frame the scrollview such that the tools view
374
// fits underneath it
375
NSRect scrollViewF = [scrollView frame];
376
[scrollView setFrame:
377
NSMakeRect(NSMinX(scrollViewF), NSMinY(scrollViewF) + NSHeight([tools frame]),
378
NSWidth(scrollViewF), NSHeight(scrollViewF) - NSHeight([tools frame]))];
380
[[[self window] contentView] addSubview: tools];
384
- (void) _createSinglePageView
386
NSSize viewSize = [scrollView contentSize];
387
NSRect frame = NSMakeRect(0, 0, viewSize.width, viewSize.height);
388
singlePageView = [[SinglePageView alloc] initWithFrame: frame];
391
- (void) _setInitialWindowSize
393
NSRect screenFrame = [[NSScreen mainScreen] frame];
396
// Reserve a little space at the top such that the window
397
// does not appear "glued" to the menu bar
398
screenFrame.size.height = NSHeight(screenFrame) - 30;
401
NSRect winFrame = [self _calcPreferredFrameInFrame: screenFrame
402
withPDFSize: [singlePageView preferredSize]];
404
NSRect contentRect = [NSWindow contentRectForFrameRect: winFrame
405
styleMask: [[self window] styleMask]];
407
NSSize availableSize = [self _calcPDFContentSize: contentRect.size add: NO];
408
NSSize usedSize = [singlePageView zoomContentToFit: availableSize];
409
// recalc frame with actually used size
410
winFrame = [self _calcPreferredFrameInFrame: screenFrame
411
withPDFSize: usedSize];
413
[[self window] setFrame: winFrame display: YES];
416
- (NSRect) _calcPreferredFrameInFrame: (NSRect)maxFrame withPDFSize: (NSSize)aPDFSize
419
// Reserve a little extra space at the top of the screen. This is necessary
420
// if GNUstep does not draw the window decorations but the window manager.
421
// Otherwise, the window might appear with the titlebar off-screen
422
maxFrame.size.height = NSHeight(maxFrame) - 40;
425
NSSize newContentSize = [self _calcPDFContentSize: aPDFSize add: YES];
427
NSRect contentRect = [NSWindow contentRectForFrameRect: [[self window] frame]
428
styleMask: [[self window] styleMask]];
429
contentRect.size = newContentSize;
431
NSRect newFrame = [NSWindow frameRectForContentRect: contentRect
432
styleMask: [[self window] styleMask]];
434
// constrain the computed frame inside the screen dimensions (aFrame)
435
// (OSX works fine without, but I guess, with GNUstep, we're better of
436
// taking care of this)
438
//NSLog(@"NEW FRAME 1: %f @ %f - %f @ %f",
439
// NSMinX(newFrame), NSMinY(newFrame), NSMaxX(newFrame), NSMaxY(newFrame));
442
if (NSMinY(newFrame) < NSMinY(maxFrame))
444
newFrame.origin.x = NSMinY(maxFrame);
446
if (NSMaxY(newFrame) > NSHeight(maxFrame))
448
newFrame.origin.y = NSHeight(maxFrame) - NSHeight(newFrame);
449
if (NSMinY(newFrame) < NSMinY(maxFrame))
451
newFrame.origin.y = NSMinY(maxFrame);
452
newFrame.size.height = NSHeight(maxFrame);
457
if (NSMinX(newFrame) < NSMinX(maxFrame))
459
newFrame.origin.y = NSMinX(maxFrame);
461
if (NSMaxX(newFrame) > NSWidth(maxFrame))
463
newFrame.origin.x = NSWidth(maxFrame) - NSWidth(newFrame);
464
if (NSMinX(newFrame) < NSMinX(maxFrame))
466
newFrame.origin.x = NSMinX(maxFrame);
467
newFrame.size.width = NSWidth(maxFrame);
471
// if the new frame has any anomalies, and return the maximum frame
472
// (otherwise, the window may dissapear from the screen)
473
if ((NSWidth(newFrame) <= 0) || (NSHeight(newFrame) <= 0))
478
//NSLog(@"NEW FRAME 2: %f @ %f - %f @ %f",
479
// NSMinX(newFrame), NSMinY(newFrame), NSMaxX(newFrame), NSMaxY(newFrame));
484
/** Add or subtract the size of additional components in the window (tools, scroller)
485
to or from a rectangle. */
486
- (NSSize) _calcPDFContentSize: (NSSize)aSize add: (BOOL)addToSize
488
float factor = (addToSize ? 1 : -1);
490
NSSize newSize = aSize;
492
newSize.height += NSHeight([tools frame]) * factor;
493
newSize.height += NSHeight([[scrollView horizontalScroller] frame]) * factor;
494
newSize.width += NSWidth([[scrollView verticalScroller] frame]) * factor;
497
// add a little extra space, otherwise scrollbars appear
499
float additionalSpace = 2 * (addToSize ? 1 : -1);
500
newSize.width += additionalSpace;
501
newSize.height += additionalSpace;