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 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 57 PreviewPage::~PreviewPage() 58 { 59 delete [] fRects; 60 delete [] fPoints; 61 delete [] fPictures; 62 } 63 64 65 status_t 66 PreviewPage::InitCheck() const 67 { 68 return fStatus; 69 } 70 71 72 void 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 112 RotateRect(const BRect& rect) 113 { 114 return BRect(rect.top, rect.left, rect.bottom, rect.right); 115 } 116 117 118 BRect 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 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 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 244 PreviewView::~PreviewView() 245 { 246 delete fCachedPage; 247 } 248 249 250 void 251 PreviewView::Show() 252 { 253 BView::Show(); 254 be_app->SetCursor(ZOOM_IN); 255 } 256 257 258 void 259 PreviewView::Hide() 260 { 261 be_app->SetCursor(B_HAND_CURSOR); 262 BView::Hide(); 263 } 264 265 266 void 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 278 PreviewView::FrameResized(float width, float height) 279 { 280 Invalidate(); 281 FixScrollbars(); 282 } 283 284 285 void 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 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 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 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 393 PreviewView::ShowFirstPage() 394 { 395 if (!ShowsFirstPage()) { 396 fPage = 0; 397 Invalidate(); 398 } 399 } 400 401 402 void 403 PreviewView::ShowPrevPage() 404 { 405 if (!ShowsFirstPage()) { 406 fPage--; 407 Invalidate(); 408 } 409 } 410 411 412 void 413 PreviewView::ShowNextPage() 414 { 415 if (!ShowsLastPage()) { 416 fPage++; 417 Invalidate(); 418 } 419 } 420 421 422 void 423 PreviewView::ShowLastPage() 424 { 425 if (!ShowsLastPage()) { 426 fPage = NumberOfPages()-1; 427 Invalidate(); 428 } 429 } 430 431 432 bool 433 PreviewView::ShowsFirstPage() const 434 { 435 return fPage == 0; 436 } 437 438 439 bool 440 PreviewView::ShowsLastPage() const 441 { 442 return fPage == NumberOfPages() - 1; 443 } 444 445 446 void 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 463 PreviewView::ZoomIn() 464 { 465 if (CanZoomIn()) { 466 fZoom++; 467 FixScrollbars(); 468 Invalidate(); 469 } 470 } 471 472 473 bool 474 PreviewView::CanZoomIn() const 475 { 476 return fZoom < 4; 477 } 478 479 480 void 481 PreviewView::ZoomOut() 482 { 483 if (CanZoomOut()) { 484 fZoom--; 485 FixScrollbars(); 486 Invalidate(); 487 } 488 } 489 490 491 bool 492 PreviewView::CanZoomOut() const 493 { 494 return fZoom > -2; 495 } 496 497 498 void 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 530 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 540 PreviewView::InitCheck() const 541 { 542 return fReader.InitCheck(); 543 } 544 545 546 int32 547 PreviewView::NumberOfPages() const 548 { 549 return fNumberOfPages; 550 } 551 552 553 BRect 554 PreviewView::_PaperRect() const 555 { 556 return ScaleRect(fPaperRect, _ZoomFactor()); 557 } 558 559 560 float 561 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 576 PreviewView::_PrintableRect() const 577 { 578 return ScaleRect(fPrintableRect, _ZoomFactor()); 579 } 580 581 582 bool 583 PreviewView::_IsPageValid() const 584 { 585 return fCachedPage && fCachedPage->InitCheck() == B_OK; 586 } 587 588 589 void 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 602 PreviewView::_IsPageLoaded(int32 page) const 603 { 604 return fCachedPage != NULL && fCachedPage->Page() == page; 605 } 606 607 608 BRect 609 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 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 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 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 763 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 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->SetViewColor(ui_color(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 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 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 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 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