1 /*
2 * Copyright 2002-2008, Haiku. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Michael Pfeiffer
7 * Hartmut Reh
8 * julun <host.haiku@gmx.de>
9 */
10
11 #include "Preview.h"
12
13 #include "GraphicsDriver.h"
14 #include "PrintUtils.h"
15
16
17 #include <math.h>
18 #include <stdlib.h>
19
20
21 #include <Application.h>
22 #include <Button.h>
23 #include <Debug.h>
24 #include <Region.h>
25 #include <Screen.h>
26 #include <String.h>
27 #include <ScrollView.h>
28 #include <StringView.h>
29 #include <TextControl.h>
30
31
32 // #pragma mark - PreviewPage
33
34
PreviewPage(int32 page,PrintJobPage * pjp)35 PreviewPage::PreviewPage(int32 page, PrintJobPage* pjp)
36 : fPage(page)
37 , fStatus(B_ERROR)
38 , fNumberOfPictures(0)
39 , fRects(NULL)
40 , fPoints(NULL)
41 , fPictures(NULL)
42 {
43 fNumberOfPictures = pjp->NumberOfPictures();
44
45 fRects = new BRect[fNumberOfPictures];
46 fPoints = new BPoint[fNumberOfPictures];
47 fPictures = new BPicture[fNumberOfPictures];
48
49 for (int32 i = 0; i < fNumberOfPictures; ++i) {
50 fStatus = pjp->NextPicture(fPictures[i], fPoints[i], fRects[i]);
51 if (fStatus != B_OK)
52 break;
53 }
54 }
55
56
~PreviewPage()57 PreviewPage::~PreviewPage()
58 {
59 delete [] fRects;
60 delete [] fPoints;
61 delete [] fPictures;
62 }
63
64
65 status_t
InitCheck() const66 PreviewPage::InitCheck() const
67 {
68 return fStatus;
69 }
70
71
72 void
Draw(BView * view,const BRect & printRect)73 PreviewPage::Draw(BView* view, const BRect& printRect)
74 {
75 ASSERT(fStatus == B_OK);
76 for (int32 i = 0; i < fNumberOfPictures; i++)
77 view->DrawPicture(&fPictures[i], printRect.LeftTop() + fPoints[i]);
78 }
79
80
81 // #pragma mark - PreviewView
82
83
84 namespace {
85
86 const float kPreviewTopMargin = 10.0;
87 const float kPreviewBottomMargin = 30.0;
88 const float kPreviewLeftMargin = 10.0;
89 const float kPreviewRightMargin = 30.0;
90
91
92 // TODO share constant with JobData
93 const char *kJDOrientation = "orientation";
94 const char *kJDNup = "JJJJ_nup";
95 const char *kJDReverse = "JJJJ_reverse";
96 const char* kJDPageSelection = "JJJJ_page_selection";
97
98
99 const uint8 ZOOM_IN[] = { 16, 1, 6, 6, 0, 0, 15, 128, 48, 96, 32, 32, 66, 16,
100 66, 16, 79, 144, 66, 16, 66, 16, 32, 32, 48, 112, 15, 184, 0, 28, 0, 14, 0,
101 6, 0, 0, 15, 128, 63, 224, 127, 240, 127, 240, 255, 248, 255, 248, 255, 248,
102 255, 248, 255, 248, 127, 248, 127, 248, 63, 252, 15, 254, 0, 31, 0, 15, 0, 7 };
103
104
105 const uint8 ZOOM_OUT[] = { 16, 1, 6, 6, 0, 0, 15, 128, 48, 96, 32, 32, 64, 16,
106 64, 16, 79, 144, 64, 16, 64, 16, 32, 32, 48, 112, 15, 184, 0, 28, 0, 14, 0,
107 6, 0, 0, 15, 128, 63, 224, 127, 240, 127, 240, 255, 248, 255, 248, 255, 248,
108 255, 248, 255, 248, 127, 248, 127, 248, 63, 252, 15, 254, 0, 31, 0, 15, 0, 7 };
109
110
111 BRect
RotateRect(const BRect & rect)112 RotateRect(const BRect& rect)
113 {
114 return BRect(rect.top, rect.left, rect.bottom, rect.right);
115 }
116
117
118 BRect
ScaleDown(BRect rect,float factor)119 ScaleDown(BRect rect, float factor)
120 {
121 rect.left /= factor;
122 rect.top /= factor;
123 rect.right /= factor;
124 rect.bottom /= factor;
125 return rect;
126 }
127
128
129 BPoint
CalulateOffset(int32 numberOfPagesPerPage,int32 index,JobData::Orientation orientation,BRect printableRect)130 CalulateOffset(int32 numberOfPagesPerPage, int32 index,
131 JobData::Orientation orientation, BRect printableRect)
132 {
133 BPoint offset(0.0, 0.0);
134 if (numberOfPagesPerPage == 1)
135 return offset;
136
137 float width = printableRect.Width();
138 float height = printableRect.Height();
139
140 switch (numberOfPagesPerPage) {
141 case 2: {
142 if (index == 1) {
143 if (JobData::kPortrait == orientation)
144 offset.x = width;
145 else
146 offset.y = height;
147 }
148 } break;
149
150 case 8: {
151 if (JobData::kPortrait == orientation) {
152 offset.x = width * (index / 2);
153 offset.y = height * (index % 2);
154 } else {
155 offset.x = width * (index % 2);
156 offset.y = height * (index / 2);
157 }
158 } break;
159
160 case 32: {
161 if (JobData::kPortrait == orientation) {
162 offset.x = width * (index / 4);
163 offset.y = height * (index % 4);
164 } else {
165 offset.x = width * (index % 4);
166 offset.y = height * (index / 4);
167 }
168 } break;
169
170 case 4: {
171 case 9:
172 case 16:
173 case 25:
174 case 36:
175 case 49:
176 case 64:
177 case 81:
178 case 100:
179 case 121:
180 int32 value = int32(sqrt(double(numberOfPagesPerPage)));
181 offset.x = width * (index % value);
182 offset.y = height * (index / value);
183 } break;
184 }
185 return offset;
186 }
187
188 }
189
190
PreviewView(BFile * jobFile,BRect rect)191 PreviewView::PreviewView(BFile* jobFile, BRect rect)
192 : BView(rect, "PreviewView", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS)
193 , fPage(0)
194 , fZoom(0)
195 , fReader(jobFile)
196 , fReverse(false)
197 , fPaperRect(BRect())
198 , fPrintableRect(BRect())
199 , fTracking(false)
200 , fInsideView(true)
201 , fScrollStart(0.0, 0.0)
202 , fNumberOfPages(1)
203 , fNumberOfPagesPerPage(1)
204 , fCachedPage(NULL)
205 , fOrientation(JobData::kPortrait)
206 , fPageSelection(JobData::kAllPages)
207 {
208 int32 value32;
209 if (fReader.JobSettings()->FindInt32(kJDOrientation, &value32) == B_OK)
210 fOrientation = (JobData::Orientation)value32;
211
212 if (fReader.JobSettings()->FindInt32(kJDPageSelection, &value32) == B_OK)
213 fPageSelection = (JobData::PageSelection)value32;
214
215 bool value;
216 if (fReader.JobSettings()->FindBool(kJDReverse, &value) == B_OK)
217 fReverse = value;
218
219 if (fReader.JobSettings()->FindInt32(kJDNup, &value32) == B_OK)
220 fNumberOfPagesPerPage = value32;
221
222 fNumberOfPages = (fReader.NumberOfPages() + fNumberOfPagesPerPage - 1)
223 / fNumberOfPagesPerPage;
224
225 if (fPageSelection == JobData::kOddNumberedPages)
226 fNumberOfPages = (fNumberOfPages + 1) / 2;
227 else if (fPageSelection == JobData::kEvenNumberedPages)
228 fNumberOfPages /= 2;
229
230 fPaperRect = fReader.PaperRect();
231 fPrintableRect = fReader.PrintableRect();
232 switch (fNumberOfPagesPerPage) {
233 case 2:
234 case 8:
235 case 32:
236 case 128: {
237 fPaperRect = RotateRect(fPaperRect);
238 fPrintableRect = RotateRect(fPrintableRect);
239 } break;
240 }
241 }
242
243
~PreviewView()244 PreviewView::~PreviewView()
245 {
246 delete fCachedPage;
247 }
248
249
250 void
Show()251 PreviewView::Show()
252 {
253 BView::Show();
254 be_app->SetCursor(ZOOM_IN);
255 }
256
257
258 void
Hide()259 PreviewView::Hide()
260 {
261 be_app->SetCursor(B_HAND_CURSOR);
262 BView::Hide();
263 }
264
265
266 void
Draw(BRect rect)267 PreviewView::Draw(BRect rect)
268 {
269 if (fReader.InitCheck() == B_OK) {
270 _DrawPageFrame(rect);
271 _DrawPage(rect);
272 _DrawMarginFrame(rect);
273 }
274 }
275
276
277 void
FrameResized(float width,float height)278 PreviewView::FrameResized(float width, float height)
279 {
280 Invalidate();
281 FixScrollbars();
282 }
283
284
285 void
MouseDown(BPoint point)286 PreviewView::MouseDown(BPoint point)
287 {
288 MakeFocus(true);
289 BMessage *message = Window()->CurrentMessage();
290
291 int32 button;
292 if (message && message->FindInt32("buttons", &button) == B_OK) {
293 if (button == B_PRIMARY_MOUSE_BUTTON) {
294 int32 modifier;
295 if (message->FindInt32("modifiers", &modifier) == B_OK) {
296 if (modifier & B_SHIFT_KEY)
297 ZoomOut();
298 else
299 ZoomIn();
300 }
301 }
302
303 if (button == B_SECONDARY_MOUSE_BUTTON) {
304 fTracking = true;
305 be_app->SetCursor(B_HAND_CURSOR);
306 SetMouseEventMask(B_POINTER_EVENTS,
307 B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY);
308 fScrollStart = Bounds().LeftTop() + ConvertToScreen(point);
309 }
310 }
311 }
312
313
314 void
MouseMoved(BPoint point,uint32 transit,const BMessage * message)315 PreviewView::MouseMoved(BPoint point, uint32 transit, const BMessage* message)
316 {
317 if (fTracking) {
318 uint32 button;
319 GetMouse(&point, &button, false);
320 point = fScrollStart - ConvertToScreen(point);
321
322 float hMin, hMax;
323 BScrollBar *hBar = ScrollBar(B_HORIZONTAL);
324 hBar->GetRange(&hMin, &hMax);
325
326 float vMin, vMax;
327 BScrollBar *vBar = ScrollBar(B_VERTICAL);
328 vBar->GetRange(&vMin, &vMax);
329
330 if (point.x < 0.0) point.x = 0.0;
331 if (point.y < 0.0) point.y = 0.0;
332 if (point.x > hMax) point.x = hMax;
333 if (point.y > vMax) point.y = vMax;
334
335 ScrollTo(point);
336 } else {
337 switch (transit) {
338 case B_ENTERED_VIEW: {
339 fInsideView = true;
340 be_app->SetCursor(ZOOM_IN);
341 } break;
342
343 case B_EXITED_VIEW: {
344 fInsideView = false;
345 be_app->SetCursor(B_HAND_CURSOR);
346 } break;
347
348 default: {
349 if (modifiers() & B_SHIFT_KEY)
350 be_app->SetCursor(ZOOM_OUT);
351 else
352 be_app->SetCursor(ZOOM_IN);
353 } break;
354 }
355 }
356 }
357
358
359 void
MouseUp(BPoint point)360 PreviewView::MouseUp(BPoint point)
361 {
362 (void)point;
363 fTracking = false;
364 fScrollStart.Set(0.0, 0.0);
365 if (fInsideView && ((modifiers() & B_SHIFT_KEY) == 0))
366 be_app->SetCursor(ZOOM_IN);
367 }
368
369
370 void
KeyDown(const char * bytes,int32 numBytes)371 PreviewView::KeyDown(const char* bytes, int32 numBytes)
372 {
373 MakeFocus(true);
374 switch (bytes[0]) {
375 case '-': {
376 if (modifiers() & B_CONTROL_KEY)
377 ZoomOut();
378 } break;
379
380 case '+' : {
381 if (modifiers() & B_CONTROL_KEY)
382 ZoomIn();
383 } break;
384
385 default: {
386 BView::KeyDown(bytes, numBytes);
387 } break;
388 }
389 }
390
391
392 void
ShowFirstPage()393 PreviewView::ShowFirstPage()
394 {
395 if (!ShowsFirstPage()) {
396 fPage = 0;
397 Invalidate();
398 }
399 }
400
401
402 void
ShowPrevPage()403 PreviewView::ShowPrevPage()
404 {
405 if (!ShowsFirstPage()) {
406 fPage--;
407 Invalidate();
408 }
409 }
410
411
412 void
ShowNextPage()413 PreviewView::ShowNextPage()
414 {
415 if (!ShowsLastPage()) {
416 fPage++;
417 Invalidate();
418 }
419 }
420
421
422 void
ShowLastPage()423 PreviewView::ShowLastPage()
424 {
425 if (!ShowsLastPage()) {
426 fPage = NumberOfPages()-1;
427 Invalidate();
428 }
429 }
430
431
432 bool
ShowsFirstPage() const433 PreviewView::ShowsFirstPage() const
434 {
435 return fPage == 0;
436 }
437
438
439 bool
ShowsLastPage() const440 PreviewView::ShowsLastPage() const
441 {
442 return fPage == NumberOfPages() - 1;
443 }
444
445
446 void
ShowFindPage(int32 page)447 PreviewView::ShowFindPage(int32 page)
448 {
449 page--;
450
451 if (page < 0) {
452 page = 0;
453 } else if (page > (NumberOfPages()-1)) {
454 page = NumberOfPages()-1;
455 }
456
457 fPage = page;
458 Invalidate();
459 }
460
461
462 void
ZoomIn()463 PreviewView::ZoomIn()
464 {
465 if (CanZoomIn()) {
466 fZoom++;
467 FixScrollbars();
468 Invalidate();
469 }
470 }
471
472
473 bool
CanZoomIn() const474 PreviewView::CanZoomIn() const
475 {
476 return fZoom < 4;
477 }
478
479
480 void
ZoomOut()481 PreviewView::ZoomOut()
482 {
483 if (CanZoomOut()) {
484 fZoom--;
485 FixScrollbars();
486 Invalidate();
487 }
488 }
489
490
491 bool
CanZoomOut() const492 PreviewView::CanZoomOut() const
493 {
494 return fZoom > -2;
495 }
496
497
498 void
FixScrollbars()499 PreviewView::FixScrollbars()
500 {
501 float width = _PaperRect().Width() + kPreviewLeftMargin + kPreviewRightMargin;
502 float height = _PaperRect().Height() + kPreviewTopMargin + kPreviewBottomMargin;
503
504 BRect frame(Bounds());
505 float x = width - frame.Width();
506 if (x < 0.0)
507 x = 0.0;
508
509 float y = height - frame.Height();
510 if (y < 0.0)
511 y = 0.0;
512
513 BScrollBar * scroll = ScrollBar(B_HORIZONTAL);
514 scroll->SetRange(0.0, x);
515 scroll->SetProportion((width - x) / width);
516 float bigStep = frame.Width() - 2;
517 float smallStep = bigStep / 10.;
518 scroll->SetSteps(smallStep, bigStep);
519
520 scroll = ScrollBar(B_VERTICAL);
521 scroll->SetRange(0.0, y);
522 scroll->SetProportion((height - y) / height);
523 bigStep = frame.Height() - 2;
524 smallStep = bigStep / 10.;
525 scroll->SetSteps(smallStep, bigStep);
526 }
527
528
529 BRect
ViewRect() const530 PreviewView::ViewRect() const
531 {
532 BRect r(_PaperRect());
533 r.right += kPreviewLeftMargin + kPreviewRightMargin;
534 r.bottom += kPreviewTopMargin + kPreviewBottomMargin;
535 return r;
536 }
537
538
539 status_t
InitCheck() const540 PreviewView::InitCheck() const
541 {
542 return fReader.InitCheck();
543 }
544
545
546 int32
NumberOfPages() const547 PreviewView::NumberOfPages() const
548 {
549 return fNumberOfPages;
550 }
551
552
553 BRect
_PaperRect() const554 PreviewView::_PaperRect() const
555 {
556 return ScaleRect(fPaperRect, _ZoomFactor());
557 }
558
559
560 float
_ZoomFactor() const561 PreviewView::_ZoomFactor() const
562 {
563 const int32 b = 4;
564 int32 zoom;
565 if (fZoom > 0) {
566 zoom = (1 << b) << fZoom;
567 } else {
568 zoom = (1 << b) >> -fZoom;
569 }
570 float factor = zoom / (float)(1 << b);
571 return factor * fReader.GetScale() / 100.0;
572 }
573
574
575 BRect
_PrintableRect() const576 PreviewView::_PrintableRect() const
577 {
578 return ScaleRect(fPrintableRect, _ZoomFactor());
579 }
580
581
582 bool
_IsPageValid() const583 PreviewView::_IsPageValid() const
584 {
585 return fCachedPage && fCachedPage->InitCheck() == B_OK;
586 }
587
588
589 void
_LoadPage(int32 page)590 PreviewView::_LoadPage(int32 page)
591 {
592 delete fCachedPage;
593 fCachedPage = NULL;
594
595 PrintJobPage pjp;
596 if (fReader.GetPage(page, pjp) == B_OK)
597 fCachedPage = new PreviewPage(page, &pjp);
598 }
599
600
601 bool
_IsPageLoaded(int32 page) const602 PreviewView::_IsPageLoaded(int32 page) const
603 {
604 return fCachedPage != NULL && fCachedPage->Page() == page;
605 }
606
607
608 BRect
_ContentRect() const609 PreviewView::_ContentRect() const
610 {
611 float offsetX = kPreviewLeftMargin;
612 float offsetY = kPreviewTopMargin;
613
614 BRect rect = Bounds();
615 BRect paperRect = _PaperRect();
616
617 float min, max;
618 ScrollBar(B_HORIZONTAL)->GetRange(&min, &max);
619 if (min == max) {
620 if ((paperRect.right + 2 * offsetX) < rect.right)
621 offsetX = (rect.right - (paperRect.right + 2 * offsetX)) / 2;
622 }
623
624 ScrollBar(B_VERTICAL)->GetRange(&min, &max);
625 if (min == max) {
626 if ((paperRect.bottom + 2 * offsetY) < rect.bottom)
627 offsetY = (rect.bottom - (paperRect.bottom + 2 * offsetY)) / 2;
628 }
629
630 paperRect.OffsetTo(offsetX, offsetY);
631 return paperRect;
632 }
633
634
635 void
_DrawPageFrame(BRect rect)636 PreviewView::_DrawPageFrame(BRect rect)
637 {
638 const float kShadowIndent = 3;
639 const float kShadowWidth = 3;
640
641 const rgb_color frameColor = { 0, 0, 0, 0 };
642 const rgb_color shadowColor = { 90, 90, 90, 0 };
643
644 PushState();
645
646 // draw page border around page
647 BRect r(_ContentRect().InsetByCopy(-1, -1));
648
649 SetHighColor(frameColor);
650 StrokeRect(r);
651
652 // draw page shadow
653 SetHighColor(shadowColor);
654
655 float x = r.right + 1;
656 float right = x + kShadowWidth;
657 float bottom = r.bottom + 1 + kShadowWidth;
658 float y = r.top + kShadowIndent;
659 FillRect(BRect(x, y, right, bottom));
660
661 x = r.left + kShadowIndent;
662 y = r.bottom + 1;
663 FillRect(BRect(x, y, r.right, bottom));
664
665 PopState();
666 }
667
668
669
_DrawPage(BRect rect)670 void PreviewView::_DrawPage(BRect rect)
671 {
672 BRect printRect(_PrintableRect());
673 switch (fNumberOfPagesPerPage) {
674 case 2:
675 case 8:
676 case 32:
677 case 128: {
678 printRect = RotateRect(printRect);
679 } break;
680 }
681 printRect.OffsetBy(_ContentRect().LeftTop());
682
683 BPoint scalingXY = GraphicsDriver::GetScale(fNumberOfPagesPerPage, printRect, 100.0);
684 float scaling = min_c(scalingXY.x, scalingXY.y);
685
686 printRect = ScaleDown(printRect, _ZoomFactor() * scaling);
687 BRect clipRect(ScaleRect(printRect, scaling));
688
689 for (int32 index = 0; index < fNumberOfPagesPerPage; ++index) {
690 int32 pageNumber = _GetPageNumber(index);
691 if (pageNumber < 0)
692 continue;
693
694 if (!_IsPageLoaded(pageNumber))
695 _LoadPage(pageNumber);
696
697 if (!_IsPageValid())
698 continue;
699
700 BPoint offset(CalulateOffset(fNumberOfPagesPerPage, index, fOrientation,
701 clipRect));
702
703 clipRect.OffsetTo(printRect.LeftTop());
704 clipRect.OffsetBy(offset);
705
706 BRegion clip(clipRect);
707 ConstrainClippingRegion(&clip);
708
709 SetScale(_ZoomFactor() * scaling);
710
711 fCachedPage->Draw(this, printRect.OffsetByCopy(offset));
712
713 if (fNumberOfPagesPerPage > 1)
714 StrokeRect(clipRect.InsetByCopy(1.0, 1.0), B_MIXED_COLORS);
715
716 SetScale(1.0);
717
718 ConstrainClippingRegion(NULL);
719 }
720 }
721
722
723 void
_DrawMarginFrame(BRect rect)724 PreviewView::_DrawMarginFrame(BRect rect)
725 {
726 BRect paperRect(_ContentRect());
727 BRect printRect(_PrintableRect());
728 printRect.OffsetBy(paperRect.LeftTop());
729
730 const rgb_color highColor = HighColor();
731 const rgb_color white = { 255, 255, 255, 255 };
732
733 SetHighColor(white);
734
735 FillRect(BRect(paperRect.left, paperRect.top, printRect.left
736 , paperRect.bottom));
737 FillRect(BRect(paperRect.left, paperRect.top, paperRect.right
738 , printRect.top));
739 FillRect(BRect(printRect.right, paperRect.top, paperRect.right
740 , paperRect.bottom));
741 FillRect(BRect(paperRect.left, printRect.bottom, paperRect.right
742 , paperRect.bottom));
743
744 SetHighColor(highColor);
745
746 BeginLineArray(4);
747
748 SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
749 StrokeLine(BPoint(printRect.left, paperRect.top),
750 BPoint(printRect.left, paperRect.bottom), B_MIXED_COLORS);
751 StrokeLine(BPoint(printRect.right, paperRect.top),
752 BPoint(printRect.right, paperRect.bottom), B_MIXED_COLORS);
753 StrokeLine(BPoint(paperRect.left, printRect.top),
754 BPoint(paperRect.right, printRect.top), B_MIXED_COLORS);
755 StrokeLine(BPoint(paperRect.left, printRect.bottom),
756 BPoint(paperRect.right, printRect.bottom), B_MIXED_COLORS);
757
758 EndLineArray();
759 }
760
761
762
_GetPageNumber(int32 index) const763 int32 PreviewView::_GetPageNumber(int32 index) const
764 {
765 int32 page = fPage;
766 if (fReverse)
767 page = fNumberOfPages - fPage - 1;
768
769 if (fPageSelection == JobData::kOddNumberedPages)
770 page *= 2; // 0, 2, 4, ...
771 else if (fPageSelection == JobData::kEvenNumberedPages)
772 page = 2 * page + 1; // 1, 3, 5, ...
773
774 return page * fNumberOfPagesPerPage + index;
775 }
776
777
778 // #pragma mark - PreviewWindow
779
780
PreviewWindow(BFile * jobFile,bool showOkAndCancelButtons)781 PreviewWindow::PreviewWindow(BFile* jobFile, bool showOkAndCancelButtons)
782 : BlockingWindow(BRect(20, 24, 400, 600), "Preview", B_TITLED_WINDOW,
783 B_ASYNCHRONOUS_CONTROLS)
784 , fButtonBarHeight(0.0)
785 {
786 BRect bounds(Bounds());
787
788 BView* panel = new BBox(Bounds(), "top_panel", B_FOLLOW_ALL,
789 B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP,
790 B_PLAIN_BORDER);
791 AddChild(panel);
792
793 bounds.OffsetBy(10.0, 10.0);
794
795 fFirst = new BButton(bounds, "first", "First page", new BMessage(MSG_FIRST_PAGE));
796 panel->AddChild(fFirst);
797 fFirst->ResizeToPreferred();
798
799 bounds.OffsetBy(fFirst->Bounds().Width() + 10.0, 0.0);
800 fPrev = new BButton(bounds, "previous", "Previous page", new BMessage(MSG_PREV_PAGE));
801 panel->AddChild(fPrev);
802 fPrev->ResizeToPreferred();
803
804 bounds.OffsetBy(fPrev->Bounds().Width() + 10.0, 0.0);
805 fNext = new BButton(bounds, "next", "Next page", new BMessage(MSG_NEXT_PAGE));
806 panel->AddChild(fNext);
807 fNext->ResizeToPreferred();
808
809 bounds.OffsetBy(fNext->Bounds().Width() + 10.0, 0.0);
810 fLast = new BButton(bounds, "last", "Last page", new BMessage(MSG_LAST_PAGE));
811 panel->AddChild(fLast);
812 fLast->ResizeToPreferred();
813
814 bounds = fLast->Frame();
815 bounds.OffsetBy(fLast->Bounds().Width() + 10.0, 0.0);
816 fPageNumber = new BTextControl(bounds, "numOfPage", "99", "",
817 new BMessage(MSG_FIND_PAGE));
818 panel->AddChild(fPageNumber);
819 fPageNumber->ResizeToPreferred();
820 fPageNumber->SetDivider(0.0);
821 fPageNumber->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_RIGHT);
822 fPageNumber->MoveBy(0.0, bounds.Height() - fPageNumber->Bounds().Height());
823
824 uint32 num;
825 for (num = 0; num <= 255; num++)
826 fPageNumber->TextView()->DisallowChar(num);
827
828 for (num = 0; num <= 9; num++)
829 fPageNumber->TextView()->AllowChar('0' + num);
830 fPageNumber->TextView()-> SetMaxBytes(5);
831
832 bounds.OffsetBy(fPageNumber->Bounds().Width() + 5.0, 0.0);
833 fPageText = new BStringView(bounds, "pageText", "");
834 panel->AddChild(fPageText);
835 fPageText->ResizeTo(fPageText->StringWidth("of 99999 pages"),
836 fFirst->Bounds().Height());
837
838 bounds.OffsetBy(fPageText->Bounds().Width() + 10.0, 0.0);
839 fZoomIn = new BButton(bounds, "zoomIn", "Zoom in", new BMessage(MSG_ZOOM_IN));
840 panel->AddChild(fZoomIn);
841 fZoomIn->ResizeToPreferred();
842
843 bounds.OffsetBy(fZoomIn->Bounds().Width() + 10.0, 0.0);
844 fZoomOut = new BButton(bounds, "ZoomOut", "Zoom out", new BMessage(MSG_ZOOM_OUT));
845 panel->AddChild(fZoomOut);
846 fZoomOut->ResizeToPreferred();
847
848 fButtonBarHeight = fZoomOut->Frame().bottom + 10.0;
849
850 bounds = Bounds();
851 bounds.top = fButtonBarHeight;
852
853 if (showOkAndCancelButtons) {
854 // adjust preview height
855 bounds.bottom -= fButtonBarHeight;
856 // update the total height of both bars
857 fButtonBarHeight *= 2;
858
859 // cancel printing if user closes the preview window
860 SetUserQuitResult(B_ERROR);
861
862 BButton *printJob = new BButton(BRect(), "printJob", "Print",
863 new BMessage(MSG_PRINT_JOB), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
864 panel->AddChild(printJob);
865 printJob->ResizeToPreferred();
866 printJob->MoveTo(bounds.right - (printJob->Bounds().Width() + 10.0),
867 bounds.bottom + 10.0);
868
869 BButton *cancelJob = new BButton(BRect(), "cancelJob", "Cancel",
870 new BMessage(MSG_CANCEL_JOB), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
871 panel->AddChild(cancelJob);
872 cancelJob->ResizeToPreferred();
873 cancelJob->MoveTo(printJob->Frame().left - (10.0 + cancelJob->Bounds().Width()),
874 bounds.bottom + 10.0);
875
876 printJob->MakeDefault(true);
877 }
878
879 bounds.right -= B_V_SCROLL_BAR_WIDTH;
880 bounds.bottom -= B_H_SCROLL_BAR_HEIGHT;
881
882 fPreview = new PreviewView(jobFile, bounds);
883 fPreviewScroller = new BScrollView("PreviewScroller", fPreview, B_FOLLOW_ALL,
884 B_FRAME_EVENTS, true, true, B_FANCY_BORDER);
885 fPreviewScroller->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
886 panel->AddChild(fPreviewScroller);
887
888 if (fPreview->InitCheck() == B_OK) {
889 _ResizeToPage();
890 fPreview->FixScrollbars();
891 _UpdateControls();
892 fPreview->MakeFocus(true);
893 }
894 }
895
896
897 void
MessageReceived(BMessage * m)898 PreviewWindow::MessageReceived(BMessage* m)
899 {
900 switch (m->what) {
901 case MSG_FIRST_PAGE:
902 fPreview->ShowFirstPage();
903 break;
904
905 case MSG_NEXT_PAGE:
906 fPreview->ShowNextPage();
907 break;
908
909 case MSG_PREV_PAGE:
910 fPreview->ShowPrevPage();
911 break;
912
913 case MSG_LAST_PAGE:
914 fPreview->ShowLastPage();
915 break;
916
917 case MSG_FIND_PAGE:
918 fPreview->ShowFindPage(atoi(fPageNumber->Text())) ;
919 break;
920
921 case MSG_ZOOM_IN:
922 fPreview->ZoomIn();
923 break;
924
925 case MSG_ZOOM_OUT:
926 fPreview->ZoomOut();
927 break;
928
929 case B_MODIFIERS_CHANGED:
930 fPreview->MouseMoved(BPoint(), B_INSIDE_VIEW, m);
931 break;
932
933 case MSG_CANCEL_JOB:
934 Quit(B_ERROR);
935 break;
936
937 case MSG_PRINT_JOB:
938 Quit(B_OK);
939 break;
940
941 default:
942 BlockingWindow::MessageReceived(m);
943 return;
944 }
945 _UpdateControls();
946 }
947
948
949 status_t
Go()950 PreviewWindow::Go()
951 {
952 status_t st = InitCheck();
953 if (st == B_OK)
954 return BlockingWindow::Go();
955
956 be_app->SetCursor(B_HAND_CURSOR);
957 Quit();
958 return st;
959 }
960
961
962 void
_ResizeToPage()963 PreviewWindow::_ResizeToPage()
964 {
965 BScreen screen;
966 if (screen.Frame().right == 0.0)
967 return;
968
969 const float windowBorderWidth = 5;
970 const float windowBorderHeight = 5;
971
972 BRect rect(fPreview->ViewRect());
973 float width = rect.Width() + 1 + B_V_SCROLL_BAR_WIDTH;
974 float height = rect.Height() + 1 + fButtonBarHeight + B_H_SCROLL_BAR_HEIGHT;
975
976 rect = screen.Frame();
977 // dimensions so that window does not reach outside of screen
978 float maxWidth = rect.Width() + 1 - windowBorderWidth - Frame().left;
979 float maxHeight = rect.Height() + 1 - windowBorderHeight - Frame().top;
980
981 // width so that all buttons are visible
982 float minWidth = fZoomOut->Frame().right + 10;
983
984 if (width < minWidth) width = minWidth;
985 if (width > maxWidth) width = maxWidth;
986 if (height > maxHeight) height = maxHeight;
987
988 ResizeTo(width, height);
989 }
990
991
992 void
_UpdateControls()993 PreviewWindow::_UpdateControls()
994 {
995 fFirst->SetEnabled(!fPreview->ShowsFirstPage());
996 fPrev->SetEnabled(!fPreview->ShowsFirstPage());
997 fNext->SetEnabled(!fPreview->ShowsLastPage());
998 fLast->SetEnabled(!fPreview->ShowsLastPage());
999 fZoomIn->SetEnabled(fPreview->CanZoomIn());
1000 fZoomOut->SetEnabled(fPreview->CanZoomOut());
1001
1002 BString text;
1003 text << fPreview->CurrentPage();
1004 fPageNumber->SetText(text.String());
1005
1006 text.SetTo("of ");
1007 text << fPreview->NumberOfPages() << " Page";
1008 if (fPreview->NumberOfPages() > 1)
1009 text.Append("s");
1010 fPageText->SetText(text.String());
1011 }
1012