1 /* 2 * JobSetupDlg.cpp 3 * Copyright 1999-2000 Y.Takagi. All Rights Reserved. 4 */ 5 6 #include <cstdio> 7 #include <cstring> 8 #include <cstdlib> 9 #include <string> 10 #include <fcntl.h> 11 #include <unistd.h> 12 #include <sys/stat.h> 13 #include <math.h> 14 15 #include <Alert.h> 16 #include <Bitmap.h> 17 #include <Box.h> 18 #include <Button.h> 19 #include <CheckBox.h> 20 #include <Debug.h> 21 #include <GridView.h> 22 #include <GroupLayout.h> 23 #include <GroupLayoutBuilder.h> 24 #include <Looper.h> 25 #include <MessageFilter.h> 26 #include <MenuField.h> 27 #include <MenuItem.h> 28 #include <Message.h> 29 #include <Point.h> 30 #include <PopUpMenu.h> 31 #include <PrintJob.h> 32 #include <RadioButton.h> 33 #include <Rect.h> 34 #include <Slider.h> 35 #include <String.h> 36 #include <TextControl.h> 37 #include <TextView.h> 38 #include <View.h> 39 40 #include "HalftoneView.h" 41 #include "JobSetupDlg.h" 42 #include "JobData.h" 43 #include "JSDSlider.h" 44 #include "PagesView.h" 45 #include "PrinterData.h" 46 #include "PrinterCap.h" 47 #include "DbgMsg.h" 48 49 50 using namespace std; 51 52 53 struct NupCap : public BaseCap { 54 NupCap(const string &label, bool isDefault, int nup) 55 : 56 BaseCap(label, isDefault), 57 fNup(nup) 58 {} 59 60 int32 ID() const { return fNup; } 61 62 int fNup; 63 }; 64 65 66 struct DitherCap : public BaseCap { 67 DitherCap(const string &label, bool isDefault, 68 Halftone::DitherType ditherType) 69 : 70 BaseCap(label, isDefault), 71 fDitherType(ditherType) 72 {} 73 74 int32 ID() const { return fDitherType; } 75 76 Halftone::DitherType fDitherType; 77 }; 78 79 80 static const NupCap gNup1("1", true, 1); 81 static const NupCap gNup2("2", false, 2); 82 static const NupCap gNup4("4", false, 4); 83 static const NupCap gNup8("8", false, 8); 84 static const NupCap gNup9("9", false, 9); 85 static const NupCap gNup16("16", false, 16); 86 static const NupCap gNup25("25", false, 25); 87 static const NupCap gNup32("32", false, 32); 88 static const NupCap gNup36("36", false, 36); 89 90 91 static const DitherCap gDitherType1("Crosshatch", false, Halftone::kType1); 92 static const DitherCap gDitherType2("Grid", false, Halftone::kType2); 93 static const DitherCap gDitherType3("Stipple", false, Halftone::kType3); 94 static const DitherCap gDitherFloydSteinberg("Floyd-Steinberg", false, 95 Halftone::kTypeFloydSteinberg); 96 97 98 const BaseCap *gNups[] = { 99 &gNup1, 100 &gNup2, 101 &gNup4, 102 &gNup8, 103 &gNup9, 104 &gNup16, 105 &gNup25, 106 &gNup32, 107 &gNup36 108 }; 109 110 111 const BaseCap *gDitherTypes[] = { 112 &gDitherType1, 113 &gDitherType2, 114 &gDitherType3, 115 &gDitherFloydSteinberg 116 }; 117 118 119 enum { 120 kMsgRangeAll = 'JSdl', 121 kMsgRangeSelection, 122 kMsgPreview, 123 kMsgCancel, 124 kMsgOK, 125 kMsgQuality, 126 kMsgCollateChanged, 127 kMsgReverseChanged, 128 kMsgDuplexChanged, 129 kMsgNone = 0 130 }; 131 132 133 JobSetupView::JobSetupView(JobData* jobData, PrinterData* printerData, 134 const PrinterCap *printerCap) 135 : 136 BView("jobSetup", B_WILL_DRAW), 137 fCopies(NULL), 138 fFromPage(NULL), 139 fToPage(NULL), 140 fJobData(jobData), 141 fPrinterData(printerData), 142 fPrinterCap(printerCap), 143 fColorType(NULL), 144 fDitherType(NULL), 145 fGamma(NULL), 146 fInkDensity(NULL), 147 fHalftone(NULL), 148 fAll(NULL), 149 fCollate(NULL), 150 fReverse(NULL), 151 fPages(NULL), 152 fPaperFeed(NULL), 153 fDuplex(NULL), 154 fNup(NULL), 155 fAllPages(NULL), 156 fOddNumberedPages(NULL), 157 fEvenNumberedPages(NULL) 158 { 159 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 160 } 161 162 163 BRadioButton* 164 JobSetupView::CreatePageSelectionItem(const char* name, const char* label, 165 JobData::PageSelection pageSelection) 166 { 167 BRadioButton* button = new BRadioButton(name, label, NULL); 168 if (fJobData->getPageSelection() == pageSelection) { 169 button->SetValue(B_CONTROL_ON); 170 } 171 return button; 172 } 173 174 175 void 176 JobSetupView::AllowOnlyDigits(BTextView* textView, int maxDigits) 177 { 178 int num; 179 for (num = 0; num <= 255; num++) { 180 textView->DisallowChar(num); 181 } 182 for (num = 0; num <= 9; num++) { 183 textView->AllowChar('0' + num); 184 } 185 textView->SetMaxBytes(maxDigits); 186 } 187 188 189 void 190 JobSetupView::AttachedToWindow() 191 { 192 // quality 193 BBox* qualityBox = new BBox("quality"); 194 qualityBox->SetLabel("Quality"); 195 196 // color 197 fColorType = new BPopUpMenu("color"); 198 fColorType->SetRadioMode(true); 199 FillCapabilityMenu(fColorType, kMsgQuality, PrinterCap::kColor, 200 fJobData->getColor()); 201 BMenuField* colorMenuField = new BMenuField("color", "Color:", fColorType); 202 fColorType->SetTargetForItems(this); 203 204 if (IsHalftoneConfigurationNeeded()) 205 CreateHalftoneConfigurationUI(); 206 207 // page range 208 209 BBox* pageRangeBox = new BBox("pageRange"); 210 pageRangeBox->SetLabel("Page Range"); 211 212 fAll = new BRadioButton("all", "Print all Pages", new BMessage(kMsgRangeAll)); 213 214 BRadioButton *range = new BRadioButton("selection", "Print selected Pages:", 215 new BMessage(kMsgRangeSelection)); 216 217 fFromPage = new BTextControl("from", "From:", "", NULL); 218 fFromPage->SetAlignment(B_ALIGN_LEFT, B_ALIGN_RIGHT); 219 AllowOnlyDigits(fFromPage->TextView(), 6); 220 221 fToPage = new BTextControl("to", "To:", "", NULL); 222 fToPage->SetAlignment(B_ALIGN_LEFT, B_ALIGN_RIGHT); 223 AllowOnlyDigits(fToPage->TextView(), 6); 224 225 int first_page = fJobData->getFirstPage(); 226 int last_page = fJobData->getLastPage(); 227 228 if (first_page <= 1 && last_page <= 0) { 229 fAll->SetValue(B_CONTROL_ON); 230 } else { 231 range->SetValue(B_CONTROL_ON); 232 if (first_page < 1) 233 first_page = 1; 234 if (first_page > last_page) 235 last_page = -1; 236 237 BString oss1; 238 oss1 << first_page; 239 fFromPage->SetText(oss1.String()); 240 241 BString oss2; 242 oss2 << last_page; 243 fToPage->SetText(oss2.String()); 244 } 245 246 fAll->SetTarget(this); 247 range->SetTarget(this); 248 249 // paper source 250 fPaperFeed = new BPopUpMenu(""); 251 fPaperFeed->SetRadioMode(true); 252 FillCapabilityMenu(fPaperFeed, kMsgNone, PrinterCap::kPaperSource, 253 fJobData->getPaperSource()); 254 BMenuField* paperSourceMenufield = new BMenuField("paperSource", 255 "Paper Source:", fPaperFeed); 256 257 // Pages per sheet 258 fNup = new BPopUpMenu(""); 259 fNup->SetRadioMode(true); 260 FillCapabilityMenu(fNup, kMsgNone, gNups, sizeof(gNups) / sizeof(gNups[0]), 261 (int)fJobData->getNup()); 262 BMenuField* pagesPerSheet = new BMenuField("pagesPerSheet", 263 "Pages Per Sheet:", fNup); 264 265 // duplex 266 if (fPrinterCap->isSupport(PrinterCap::kPrintStyle)) { 267 fDuplex = new BCheckBox("duplex", "Duplex", 268 new BMessage(kMsgDuplexChanged)); 269 if (fJobData->getPrintStyle() != JobData::kSimplex) { 270 fDuplex->SetValue(B_CONTROL_ON); 271 } 272 fDuplex->SetTarget(this); 273 } else { 274 fDuplex = NULL; 275 } 276 277 // copies 278 fCopies = new BTextControl("copies", "Number of Copies:", "", NULL); 279 AllowOnlyDigits(fCopies->TextView(), 3); 280 281 BString copies; 282 copies << fJobData->getCopies(); 283 fCopies->SetText(copies.String()); 284 285 // collate 286 fCollate = new BCheckBox("collate", "Collate", 287 new BMessage(kMsgCollateChanged)); 288 if (fJobData->getCollate()) { 289 fCollate->SetValue(B_CONTROL_ON); 290 } 291 fCollate->SetTarget(this); 292 293 // reverse 294 fReverse = new BCheckBox("reverse", "Reverse Order", 295 new BMessage(kMsgReverseChanged)); 296 if (fJobData->getReverse()) { 297 fReverse->SetValue(B_CONTROL_ON); 298 } 299 fReverse->SetTarget(this); 300 301 // pages view 302 // TODO make layout API compatible 303 fPages = new PagesView(BRect(0, 0, 150, 40), "pages", B_FOLLOW_ALL, 304 B_WILL_DRAW); 305 fPages->setCollate(fJobData->getCollate()); 306 fPages->setReverse(fJobData->getReverse()); 307 fPages->SetExplicitMinSize(BSize(150, 40)); 308 fPages->SetExplicitMaxSize(BSize(150, 40)); 309 310 // page selection 311 BBox* pageSelectionBox = new BBox("pageSelection"); 312 pageSelectionBox->SetLabel("Page Selection"); 313 314 fAllPages = CreatePageSelectionItem("allPages", "All Pages", 315 JobData::kAllPages); 316 fOddNumberedPages = CreatePageSelectionItem("oddPages", 317 "Odd-Numbered Pages", JobData::kOddNumberedPages); 318 fEvenNumberedPages = CreatePageSelectionItem("evenPages", 319 "Even-Numbered Pages", JobData::kEvenNumberedPages); 320 321 // separator line 322 BBox *separator = new BBox("separator"); 323 separator->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 1)); 324 325 // buttons 326 BButton* preview = new BButton("preview", "Preview" B_UTF8_ELLIPSIS, 327 new BMessage(kMsgPreview)); 328 BButton* cancel = new BButton("cancel", "Cancel", 329 new BMessage(kMsgCancel)); 330 BButton* ok = new BButton("ok", "OK", new BMessage(kMsgOK)); 331 ok->MakeDefault(true); 332 333 if (IsHalftoneConfigurationNeeded()) { 334 BGroupView* halftoneGroup = new BGroupView(B_VERTICAL, 0); 335 BGroupLayout* halftoneLayout = halftoneGroup->GroupLayout(); 336 halftoneLayout->AddView(fHalftone); 337 fHalftoneBox->AddChild(halftoneGroup); 338 } 339 340 BGridView* qualityGrid = new BGridView(); 341 BGridLayout* qualityGridLayout = qualityGrid->GridLayout(); 342 qualityGridLayout->AddItem(colorMenuField->CreateLabelLayoutItem(), 0, 0); 343 qualityGridLayout->AddItem(colorMenuField->CreateMenuBarLayoutItem(), 1, 0); 344 if (IsHalftoneConfigurationNeeded()) { 345 qualityGridLayout->AddItem(fDitherMenuField->CreateLabelLayoutItem(), 346 0, 1); 347 qualityGridLayout->AddItem(fDitherMenuField->CreateMenuBarLayoutItem(), 348 1, 1); 349 qualityGridLayout->AddView(fGamma, 0, 2, 2); 350 qualityGridLayout->AddView(fInkDensity, 0, 3, 2); 351 qualityGridLayout->AddView(fHalftoneBox, 0, 4, 2); 352 } else { 353 AddDriverSpecificSettings(qualityGridLayout, 1); 354 } 355 qualityGridLayout->SetSpacing(0, 0); 356 qualityGridLayout->SetInsets(5, 5, 5, 5); 357 qualityBox->AddChild(qualityGrid); 358 359 BGridView* pageRangeGrid = new BGridView(); 360 BGridLayout* pageRangeLayout = pageRangeGrid->GridLayout(); 361 pageRangeLayout->AddItem(fFromPage->CreateLabelLayoutItem(), 0, 0); 362 pageRangeLayout->AddItem(fFromPage->CreateTextViewLayoutItem(), 1, 0); 363 pageRangeLayout->AddItem(fToPage->CreateLabelLayoutItem(), 0, 1); 364 pageRangeLayout->AddItem(fToPage->CreateTextViewLayoutItem(), 1, 1); 365 pageRangeLayout->SetInsets(0, 0, 0, 0); 366 pageRangeLayout->SetSpacing(0, 0); 367 368 BGroupView* pageRangeGroup = new BGroupView(B_VERTICAL, 0); 369 BGroupLayout* pageRangeGroupLayout = pageRangeGroup->GroupLayout(); 370 pageRangeGroupLayout->AddView(fAll); 371 pageRangeGroupLayout->AddView(range); 372 pageRangeGroupLayout->AddView(pageRangeGrid); 373 pageRangeGroupLayout->SetInsets(5, 5, 5, 5); 374 pageRangeBox->AddChild(pageRangeGroup); 375 376 BGridView* settings = new BGridView(); 377 BGridLayout* settingsLayout = settings->GridLayout(); 378 settingsLayout->AddItem(paperSourceMenufield->CreateLabelLayoutItem(), 0, 379 0); 380 settingsLayout->AddItem(paperSourceMenufield->CreateMenuBarLayoutItem(), 1, 381 0); 382 settingsLayout->AddItem(pagesPerSheet->CreateLabelLayoutItem(), 0, 1); 383 settingsLayout->AddItem(pagesPerSheet->CreateMenuBarLayoutItem(), 1, 1); 384 int row = 2; 385 if (fDuplex != NULL) { 386 settingsLayout->AddView(fDuplex, 0, row, 2); 387 row ++; 388 } 389 settingsLayout->AddItem(fCopies->CreateLabelLayoutItem(), 0, row); 390 settingsLayout->AddItem(fCopies->CreateTextViewLayoutItem(), 1, row); 391 settingsLayout->SetSpacing(0, 0); 392 393 394 BGroupView* pageSelectionGroup = new BGroupView(B_VERTICAL, 0); 395 BGroupLayout* groupLayout = pageSelectionGroup->GroupLayout(); 396 groupLayout->AddView(fAllPages); 397 groupLayout->AddView(fOddNumberedPages); 398 groupLayout->AddView(fEvenNumberedPages); 399 groupLayout->SetInsets(5, 5, 5, 5); 400 pageSelectionBox->AddChild(pageSelectionGroup); 401 402 SetLayout(new BGroupLayout(B_VERTICAL)); 403 AddChild(BGroupLayoutBuilder(B_VERTICAL, 0) 404 .AddGroup(B_HORIZONTAL, 10, 1.0f) 405 .AddGroup(B_VERTICAL, 10, 1.0f) 406 .Add(qualityBox) 407 .Add(pageRangeBox) 408 .AddGlue() 409 .End() 410 .AddGroup(B_VERTICAL, 0, 1.0f) 411 .Add(settings) 412 .AddStrut(5) 413 .Add(fCollate) 414 .Add(fReverse) 415 .Add(fPages) 416 .AddStrut(5) 417 .Add(pageSelectionBox) 418 .AddGlue() 419 .End() 420 .End() 421 .AddGlue() 422 .Add(separator) 423 .AddGroup(B_HORIZONTAL, 10, 1.0f) 424 .AddGlue() 425 .Add(cancel) 426 .Add(preview) 427 .Add(ok) 428 .End() 429 .SetInsets(0, 0, 0, 0) 430 ); 431 432 UpdateHalftonePreview(); 433 434 UpdateButtonEnabledState(); 435 } 436 437 438 bool 439 JobSetupView::IsHalftoneConfigurationNeeded() 440 { 441 return fPrinterCap->isSupport(PrinterCap::kHalftone); 442 } 443 444 445 void 446 JobSetupView::CreateHalftoneConfigurationUI() 447 { 448 // dither type 449 fDitherType = new BPopUpMenu(""); 450 fDitherType->SetRadioMode(true); 451 FillCapabilityMenu(fDitherType, kMsgQuality, gDitherTypes, 452 sizeof(gDitherTypes) / sizeof(gDitherTypes[0]), 453 (int)fJobData->getDitherType()); 454 fDitherMenuField = new BMenuField("dithering", "Dot Pattern:", 455 fDitherType); 456 fDitherType->SetTargetForItems(this); 457 458 // halftone preview view 459 fHalftoneBox = new BBox("halftoneBox"); 460 fHalftoneBox->SetBorder(B_PLAIN_BORDER); 461 462 // TODO make layout compatible 463 BSize size(240, 14 * 4); 464 BRect rect(0, 0, size.width, size.height); 465 fHalftone = new HalftoneView(rect, "halftone", 466 B_FOLLOW_ALL, B_WILL_DRAW); 467 fHalftone->SetExplicitMinSize(size); 468 fHalftone->SetExplicitMaxSize(size); 469 470 // gamma 471 fGamma = new JSDSlider("gamma", "Gamma", new BMessage(kMsgQuality), 472 -300, 300); 473 474 fGamma->SetLimitLabels("Lighter", "Darker"); 475 fGamma->SetValue((int32)(100 * log(fJobData->getGamma()) / log(2.0))); 476 fGamma->SetHashMarks(B_HASH_MARKS_BOTH); 477 fGamma->SetHashMarkCount(7); 478 fGamma->SetModificationMessage(new BMessage(kMsgQuality)); 479 fGamma->SetTarget(this); 480 481 // ink density 482 fInkDensity = new JSDSlider("inkDensity", "Ink Usage", 483 new BMessage(kMsgQuality), 0, 127); 484 485 fInkDensity->SetLimitLabels("Min", "Max"); 486 fInkDensity->SetValue((int32)fJobData->getInkDensity()); 487 fInkDensity->SetHashMarks(B_HASH_MARKS_BOTH); 488 fInkDensity->SetHashMarkCount(10); 489 fInkDensity->SetModificationMessage(new BMessage(kMsgQuality)); 490 fInkDensity->SetTarget(this); 491 } 492 493 494 void 495 JobSetupView::AddDriverSpecificSettings(BGridLayout* gridLayout, int row) 496 { 497 if (!fPrinterCap->isSupport(PrinterCap::kDriverSpecificCapabilities)) 498 return; 499 500 int count = fPrinterCap->countCap(PrinterCap::kDriverSpecificCapabilities); 501 const BaseCap** capabilities = fPrinterCap->enumCap( 502 PrinterCap::kDriverSpecificCapabilities); 503 504 for (int i = 0; i < count; i ++) { 505 const DriverSpecificCap* capability = static_cast<const DriverSpecificCap*>( 506 capabilities[i]); 507 508 const char* label = capability->fLabel.c_str(); 509 BPopUpMenu* popUpMenu = new BPopUpMenu(label); 510 popUpMenu->SetRadioMode(true); 511 512 PrinterCap::CapID category = static_cast<PrinterCap::CapID>( 513 capability->ID()); 514 515 const BaseCap** categoryCapabilities = fPrinterCap->enumCap(category); 516 517 int categoryCount = fPrinterCap->countCap(category); 518 519 string value = GetDriverSpecificValue(category, capability->Key()); 520 PrinterCap::KeyPredicate predicate(value.c_str()); 521 522 FillCapabilityMenu(popUpMenu, kMsgNone, categoryCapabilities, 523 categoryCount, predicate); 524 525 BString menuLabel = label; 526 menuLabel << ":"; 527 BMenuField* menuField = new BMenuField(label, menuLabel.String(), 528 popUpMenu); 529 popUpMenu->SetTargetForItems(this); 530 531 gridLayout->AddItem(menuField->CreateLabelLayoutItem(), 532 0, row); 533 gridLayout->AddItem(menuField->CreateMenuBarLayoutItem(), 534 1, row); 535 row ++; 536 537 fDriverSpecificLists[category] = popUpMenu; 538 } 539 } 540 541 542 string 543 JobSetupView::GetDriverSpecificValue(PrinterCap::CapID category, 544 const char* key) 545 { 546 if (fJobData->HasDriverSpecificSetting(key)) 547 return fJobData->DriverSpecificSetting(key); 548 549 const BaseCap* defaultCapability = fPrinterCap->getDefaultCap(category); 550 return defaultCapability->fKey; 551 } 552 553 554 template<typename Predicate> 555 void 556 JobSetupView::FillCapabilityMenu(BPopUpMenu* menu, uint32 message, 557 const BaseCap** capabilities, int count, Predicate& predicate) 558 { 559 bool marked = false; 560 561 BMenuItem* firstItem = NULL; 562 BMenuItem* defaultItem = NULL; 563 BMenuItem* item = NULL; 564 while (count--) { 565 const BaseCap* capability = *capabilities; 566 if (message != kMsgNone) 567 item = new BMenuItem(capability->fLabel.c_str(), 568 new BMessage(message)); 569 else 570 item = new BMenuItem(capability->fLabel.c_str(), NULL); 571 572 menu->AddItem(item); 573 574 if (firstItem == NULL) 575 firstItem = item; 576 577 if (capability->fIsDefault) 578 defaultItem = item; 579 580 581 if (predicate(capability)) { 582 item->SetMarked(true); 583 marked = true; 584 } 585 586 capabilities++; 587 } 588 589 if (marked) 590 return; 591 592 if (defaultItem != NULL) 593 defaultItem->SetMarked(true); 594 else if (firstItem != NULL) 595 firstItem->SetMarked(true); 596 } 597 598 599 void 600 JobSetupView::FillCapabilityMenu(BPopUpMenu* menu, uint32 message, 601 PrinterCap::CapID category, int id) 602 { 603 PrinterCap::IDPredicate predicate(id); 604 int count = fPrinterCap->countCap(category); 605 const BaseCap **capabilities = fPrinterCap->enumCap(category); 606 FillCapabilityMenu(menu, message, capabilities, count, predicate); 607 } 608 609 610 void 611 JobSetupView::FillCapabilityMenu(BPopUpMenu* menu, uint32 message, 612 const BaseCap** capabilities, int count, int id) 613 { 614 PrinterCap::IDPredicate predicate(id); 615 FillCapabilityMenu(menu, message, capabilities, count, predicate); 616 } 617 618 619 int 620 JobSetupView::GetID(const BaseCap** capabilities, int count, const char* label, 621 int defaultValue) 622 { 623 while (count--) { 624 const BaseCap* capability = *capabilities; 625 if (capability->fLabel == label) 626 return capability->ID(); 627 } 628 return defaultValue; 629 } 630 631 632 void 633 JobSetupView::UpdateButtonEnabledState() 634 { 635 bool pageRangeEnabled = fAll->Value() != B_CONTROL_ON; 636 fFromPage->SetEnabled(pageRangeEnabled); 637 fToPage->SetEnabled(pageRangeEnabled); 638 639 bool pageSelectionEnabled = fDuplex == NULL || 640 fDuplex->Value() != B_CONTROL_ON; 641 fAllPages->SetEnabled(pageSelectionEnabled); 642 fOddNumberedPages->SetEnabled(pageSelectionEnabled); 643 fEvenNumberedPages->SetEnabled(pageSelectionEnabled); 644 } 645 646 647 void 648 JobSetupView::MessageReceived(BMessage* message) 649 { 650 switch (message->what) { 651 case kMsgRangeAll: 652 case kMsgRangeSelection: 653 case kMsgDuplexChanged: 654 UpdateButtonEnabledState(); 655 break; 656 657 case kMsgQuality: 658 UpdateHalftonePreview(); 659 break; 660 661 case kMsgCollateChanged: 662 fPages->setCollate(fCollate->Value() == B_CONTROL_ON); 663 break; 664 665 case kMsgReverseChanged: 666 fPages->setReverse(fReverse->Value() == B_CONTROL_ON); 667 break; 668 } 669 } 670 671 672 void 673 JobSetupView::UpdateHalftonePreview() 674 { 675 if (!IsHalftoneConfigurationNeeded()) 676 return; 677 678 fHalftone->preview(Gamma(), InkDensity(), DitherType(), 679 Color() != JobData::kMonochrome); 680 } 681 682 683 JobData::Color 684 JobSetupView::Color() 685 { 686 const char *label = fColorType->FindMarked()->Label(); 687 const BaseCap* capability = fPrinterCap->findCap(PrinterCap::kColor, label); 688 if (capability == NULL) 689 return JobData::kMonochrome; 690 691 const ColorCap* colorCap = static_cast<const ColorCap*>(capability); 692 return colorCap->fColor; 693 } 694 695 696 Halftone::DitherType 697 JobSetupView::DitherType() 698 { 699 const char *label = fDitherType->FindMarked()->Label(); 700 int id = GetID(gDitherTypes, sizeof(gDitherTypes) / sizeof(gDitherTypes[0]), 701 label, Halftone::kTypeFloydSteinberg); 702 return static_cast<Halftone::DitherType>(id); 703 } 704 705 float 706 JobSetupView::Gamma() 707 { 708 const float value = (float)fGamma->Value(); 709 return pow(2.0, value / 100.0); 710 } 711 712 713 float 714 JobSetupView::InkDensity() 715 { 716 const float value = (float)(127 - fInkDensity->Value()); 717 return value; 718 } 719 720 721 JobData::PaperSource 722 JobSetupView::PaperSource() 723 { 724 const char *label = fPaperFeed->FindMarked()->Label(); 725 const BaseCap* capability = fPrinterCap->findCap(PrinterCap::kPaperSource, 726 label); 727 728 if (capability == NULL) 729 capability = fPrinterCap->getDefaultCap(PrinterCap::kPaperSource); 730 return static_cast<const PaperSourceCap*>(capability)->fPaperSource; 731 732 } 733 734 bool 735 JobSetupView::UpdateJobData(bool showPreview) 736 { 737 fJobData->setShowPreview(showPreview); 738 fJobData->setColor(Color()); 739 if (IsHalftoneConfigurationNeeded()) { 740 fJobData->setGamma(Gamma()); 741 fJobData->setInkDensity(InkDensity()); 742 fJobData->setDitherType(DitherType()); 743 } 744 745 int first_page; 746 int last_page; 747 748 if (B_CONTROL_ON == fAll->Value()) { 749 first_page = 1; 750 last_page = -1; 751 } else { 752 first_page = atoi(fFromPage->Text()); 753 last_page = atoi(fToPage->Text()); 754 } 755 756 fJobData->setFirstPage(first_page); 757 fJobData->setLastPage(last_page); 758 759 fJobData->setPaperSource(PaperSource()); 760 761 fJobData->setNup(GetID(gNups, sizeof(gNups) / sizeof(gNups[0]), 762 fNup->FindMarked()->Label(), 1)); 763 764 if (fPrinterCap->isSupport(PrinterCap::kPrintStyle)) { 765 fJobData->setPrintStyle((B_CONTROL_ON == fDuplex->Value()) 766 ? JobData::kDuplex : JobData::kSimplex); 767 } 768 769 fJobData->setCopies(atoi(fCopies->Text())); 770 771 fJobData->setCollate(B_CONTROL_ON == fCollate->Value()); 772 fJobData->setReverse(B_CONTROL_ON == fReverse->Value()); 773 774 JobData::PageSelection pageSelection = JobData::kAllPages; 775 if (fOddNumberedPages->Value() == B_CONTROL_ON) 776 pageSelection = JobData::kOddNumberedPages; 777 if (fEvenNumberedPages->Value() == B_CONTROL_ON) 778 pageSelection = JobData::kEvenNumberedPages; 779 fJobData->setPageSelection(pageSelection); 780 781 std::map<PrinterCap::CapID, BPopUpMenu*>::iterator it = 782 fDriverSpecificLists.begin(); 783 for(; it != fDriverSpecificLists.end(); it++) { 784 PrinterCap::CapID category = it->first; 785 BPopUpMenu* popUpMenu = it->second; 786 const char* key = fPrinterCap->findCap( 787 PrinterCap::kDriverSpecificCapabilities, (int)category)->Key(); 788 const char* label = popUpMenu->FindMarked()->Label(); 789 const char* value = fPrinterCap->findCap(category, label)->Key(); 790 fJobData->SetDriverSpecificSetting(key, value); 791 } 792 793 fJobData->save(); 794 return true; 795 } 796 797 798 JobSetupDlg::JobSetupDlg(JobData* jobData, PrinterData* printerData, 799 const PrinterCap* printerCap) 800 : 801 DialogWindow(BRect(100, 100, 200, 200), "PrintJob Setup", 802 B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, 803 B_NOT_RESIZABLE | B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE 804 | B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS) 805 { 806 SetResult(B_ERROR); 807 AddShortcut('W', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED)); 808 809 fJobSetup = new JobSetupView(jobData, printerData, printerCap); 810 SetLayout(new BGroupLayout(B_VERTICAL)); 811 AddChild(BGroupLayoutBuilder(B_VERTICAL, 0) 812 .Add(fJobSetup) 813 .SetInsets(10, 10, 10, 10) 814 ); 815 } 816 817 818 void 819 JobSetupDlg::MessageReceived(BMessage* message) 820 { 821 switch (message->what) { 822 case kMsgOK: 823 case kMsgPreview: 824 fJobSetup->UpdateJobData(message->what == kMsgPreview); 825 SetResult(B_NO_ERROR); 826 PostMessage(B_QUIT_REQUESTED); 827 break; 828 829 case kMsgCancel: 830 PostMessage(B_QUIT_REQUESTED); 831 break; 832 833 default: 834 DialogWindow::MessageReceived(message); 835 break; 836 } 837 } 838