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 bounds.OffsetBy(10.0, 10.0); 788 789 fFirst = new BButton(bounds, "first", "First Page", new BMessage(MSG_FIRST_PAGE)); 790 AddChild(fFirst); 791 fFirst->ResizeToPreferred(); 792 793 bounds.OffsetBy(fFirst->Bounds().Width() + 10.0, 0.0); 794 fPrev = new BButton(bounds, "previous", "Previous Page", new BMessage(MSG_PREV_PAGE)); 795 AddChild(fPrev); 796 fPrev->ResizeToPreferred(); 797 798 bounds.OffsetBy(fPrev->Bounds().Width() + 10.0, 0.0); 799 fNext = new BButton(bounds, "next", "Next Page", new BMessage(MSG_NEXT_PAGE)); 800 AddChild(fNext); 801 fNext->ResizeToPreferred(); 802 803 bounds.OffsetBy(fNext->Bounds().Width() + 10.0, 0.0); 804 fLast = new BButton(bounds, "last", "Last Page", new BMessage(MSG_LAST_PAGE)); 805 AddChild(fLast); 806 fLast->ResizeToPreferred(); 807 808 bounds = fLast->Frame(); 809 bounds.OffsetBy(fLast->Bounds().Width() + 10.0, 0.0); 810 fPageNumber = new BTextControl(bounds, "numOfPage", "99", "", 811 new BMessage(MSG_FIND_PAGE)); 812 AddChild(fPageNumber); 813 fPageNumber->ResizeToPreferred(); 814 fPageNumber->SetDivider(0.0); 815 fPageNumber->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_RIGHT); 816 fPageNumber->MoveBy(0.0, bounds.Height() - fPageNumber->Bounds().Height()); 817 818 uint32 num; 819 for (num = 0; num <= 255; num++) 820 fPageNumber->TextView()->DisallowChar(num); 821 822 for (num = 0; num <= 9; num++) 823 fPageNumber->TextView()->AllowChar('0' + num); 824 fPageNumber->TextView()-> SetMaxBytes(5); 825 826 bounds.OffsetBy(fPageNumber->Bounds().Width() + 5.0, 0.0); 827 fPageText = new BStringView(bounds, "pageText", ""); 828 AddChild(fPageText); 829 fPageText->ResizeTo(fPageText->StringWidth("of 99999 Pages"), 830 fFirst->Bounds().Height()); 831 832 bounds.OffsetBy(fPageText->Bounds().Width() + 10.0, 0.0); 833 fZoomIn = new BButton(bounds, "zoomIn", "Zoom In", new BMessage(MSG_ZOOM_IN)); 834 AddChild(fZoomIn); 835 fZoomIn->ResizeToPreferred(); 836 837 bounds.OffsetBy(fZoomIn->Bounds().Width() + 10.0, 0.0); 838 fZoomOut = new BButton(bounds, "ZoomOut", "Zoom Out", new BMessage(MSG_ZOOM_OUT)); 839 AddChild(fZoomOut); 840 fZoomOut->ResizeToPreferred(); 841 842 fButtonBarHeight = fZoomOut->Frame().bottom + 10.0; 843 844 bounds = Bounds(); 845 bounds.top = fButtonBarHeight; 846 847 if (showOkAndCancelButtons) { 848 // adjust preview height 849 bounds.bottom -= fButtonBarHeight; 850 // update the total height of both bars 851 fButtonBarHeight *= 2; 852 853 // cancel printing if user closes the preview window 854 SetUserQuitResult(B_ERROR); 855 856 BButton *printJob = new BButton(BRect(), "printJob", "Print", 857 new BMessage(MSG_PRINT_JOB), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 858 AddChild(printJob); 859 printJob->ResizeToPreferred(); 860 printJob->MoveTo(bounds.right - (printJob->Bounds().Width() + 10.0), 861 bounds.bottom + 10.0); 862 863 BButton *cancelJob = new BButton(BRect(), "cancelJob", "Cancel", 864 new BMessage(MSG_CANCEL_JOB), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 865 AddChild(cancelJob); 866 cancelJob->ResizeToPreferred(); 867 cancelJob->MoveTo(printJob->Frame().left - (10.0 + cancelJob->Bounds().Width()), 868 bounds.bottom + 10.0); 869 870 printJob->MakeDefault(true); 871 } 872 873 bounds.right -= B_V_SCROLL_BAR_WIDTH; 874 bounds.bottom -= B_H_SCROLL_BAR_HEIGHT; 875 876 fPreview = new PreviewView(jobFile, bounds); 877 fPreviewScroller = new BScrollView("PreviewScroller", fPreview, B_FOLLOW_ALL, 878 B_FRAME_EVENTS, true, true, B_FANCY_BORDER); 879 fPreviewScroller->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 880 AddChild(fPreviewScroller); 881 882 if (fPreview->InitCheck() == B_OK) { 883 _ResizeToPage(); 884 fPreview->FixScrollbars(); 885 _UpdateControls(); 886 fPreview->MakeFocus(true); 887 } 888 } 889 890 891 void 892 PreviewWindow::MessageReceived(BMessage* m) 893 { 894 switch (m->what) { 895 case MSG_FIRST_PAGE: 896 fPreview->ShowFirstPage(); 897 break; 898 899 case MSG_NEXT_PAGE: 900 fPreview->ShowNextPage(); 901 break; 902 903 case MSG_PREV_PAGE: 904 fPreview->ShowPrevPage(); 905 break; 906 907 case MSG_LAST_PAGE: 908 fPreview->ShowLastPage(); 909 break; 910 911 case MSG_FIND_PAGE: 912 fPreview->ShowFindPage(atoi(fPageNumber->Text())) ; 913 break; 914 915 case MSG_ZOOM_IN: 916 fPreview->ZoomIn(); 917 break; 918 919 case MSG_ZOOM_OUT: 920 fPreview->ZoomOut(); 921 break; 922 923 case B_MODIFIERS_CHANGED: 924 fPreview->MouseMoved(BPoint(), B_INSIDE_VIEW, m); 925 break; 926 927 case MSG_CANCEL_JOB: 928 Quit(B_ERROR); 929 break; 930 931 case MSG_PRINT_JOB: 932 Quit(B_OK); 933 break; 934 935 default: 936 BlockingWindow::MessageReceived(m); 937 return; 938 } 939 _UpdateControls(); 940 } 941 942 943 status_t 944 PreviewWindow::Go() 945 { 946 status_t st = InitCheck(); 947 if (st == B_OK) 948 return BlockingWindow::Go(); 949 950 be_app->SetCursor(B_HAND_CURSOR); 951 Quit(); 952 return st; 953 } 954 955 956 void 957 PreviewWindow::_ResizeToPage() 958 { 959 BScreen screen; 960 if (screen.Frame().right == 0.0) 961 return; 962 963 const float windowBorderWidth = 5; 964 const float windowBorderHeight = 5; 965 966 BRect rect(fPreview->ViewRect()); 967 float width = rect.Width() + 1 + B_V_SCROLL_BAR_WIDTH; 968 float height = rect.Height() + 1 + fButtonBarHeight + B_H_SCROLL_BAR_HEIGHT; 969 970 rect = screen.Frame(); 971 // dimensions so that window does not reach outside of screen 972 float maxWidth = rect.Width() + 1 - windowBorderWidth - Frame().left; 973 float maxHeight = rect.Height() + 1 - windowBorderHeight - Frame().top; 974 975 // width so that all buttons are visible 976 float minWidth = fZoomOut->Frame().right + 10; 977 978 if (width < minWidth) width = minWidth; 979 if (width > maxWidth) width = maxWidth; 980 if (height > maxHeight) height = maxHeight; 981 982 ResizeTo(width, height); 983 } 984 985 986 void 987 PreviewWindow::_UpdateControls() 988 { 989 fFirst->SetEnabled(!fPreview->ShowsFirstPage()); 990 fPrev->SetEnabled(!fPreview->ShowsFirstPage()); 991 fNext->SetEnabled(!fPreview->ShowsLastPage()); 992 fLast->SetEnabled(!fPreview->ShowsLastPage()); 993 fZoomIn->SetEnabled(fPreview->CanZoomIn()); 994 fZoomOut->SetEnabled(fPreview->CanZoomOut()); 995 996 BString text; 997 text << fPreview->CurrentPage(); 998 fPageNumber->SetText(text.String()); 999 1000 text.SetTo("of "); 1001 text << fPreview->NumberOfPages() << " Page"; 1002 if (fPreview->NumberOfPages() > 1) 1003 text.Append("s"); 1004 fPageText->SetText(text.String()); 1005 } 1006