/* * JobSetupDlg.cpp * Copyright 1999-2000 Y.Takagi. All Rights Reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "HalftoneView.h" #include "JobSetupDlg.h" #include "JobData.h" #include "JSDSlider.h" #include "PagesView.h" #include "PrinterData.h" #include "PrinterCap.h" #include "DbgMsg.h" using namespace std; struct NupCap : public EnumCap { NupCap(const string &label, bool isDefault, int nup) : EnumCap(label, isDefault), fNup(nup) {} int32 ID() const { return fNup; } int fNup; }; struct DitherCap : public EnumCap { DitherCap(const string &label, bool isDefault, Halftone::DitherType ditherType) : EnumCap(label, isDefault), fDitherType(ditherType) {} int32 ID() const { return fDitherType; } Halftone::DitherType fDitherType; }; static const NupCap gNup1("1", true, 1); static const NupCap gNup2("2", false, 2); static const NupCap gNup4("4", false, 4); static const NupCap gNup8("8", false, 8); static const NupCap gNup9("9", false, 9); static const NupCap gNup16("16", false, 16); static const NupCap gNup25("25", false, 25); static const NupCap gNup32("32", false, 32); static const NupCap gNup36("36", false, 36); static const DitherCap gDitherType1("Crosshatch", false, Halftone::kType1); static const DitherCap gDitherType2("Grid", false, Halftone::kType2); static const DitherCap gDitherType3("Stipple", false, Halftone::kType3); static const DitherCap gDitherFloydSteinberg("Floyd-Steinberg", false, Halftone::kTypeFloydSteinberg); const BaseCap *gNups[] = { &gNup1, &gNup2, &gNup4, &gNup8, &gNup9, &gNup16, &gNup25, &gNup32, &gNup36 }; const BaseCap *gDitherTypes[] = { &gDitherType1, &gDitherType2, &gDitherType3, &gDitherFloydSteinberg }; static const char* kCategoryID = "id"; enum { kMsgRangeAll = 'JSdl', kMsgRangeSelection, kMsgCancel, kMsgOK, kMsgQuality, kMsgCollateChanged, kMsgReverseChanged, kMsgDuplexChanged, kMsgIntSliderChanged, kMsgDoubleSliderChanged, kMsgNone = 0 }; JobSetupView::JobSetupView(JobData* jobData, PrinterData* printerData, const PrinterCap *printerCap) : BView("jobSetup", B_WILL_DRAW), fCopies(NULL), fFromPage(NULL), fToPage(NULL), fJobData(jobData), fPrinterData(printerData), fPrinterCap(printerCap), fColorType(NULL), fDitherType(NULL), fGamma(NULL), fInkDensity(NULL), fHalftone(NULL), fAll(NULL), fCollate(NULL), fReverse(NULL), fPages(NULL), fPaperFeed(NULL), fDuplex(NULL), fNup(NULL), fAllPages(NULL), fOddNumberedPages(NULL), fEvenNumberedPages(NULL) { SetViewUIColor(B_PANEL_BACKGROUND_COLOR); } BRadioButton* JobSetupView::CreatePageSelectionItem(const char* name, const char* label, JobData::PageSelection pageSelection) { BRadioButton* button = new BRadioButton(name, label, NULL); if (fJobData->GetPageSelection() == pageSelection) { button->SetValue(B_CONTROL_ON); } return button; } void JobSetupView::AllowOnlyDigits(BTextView* textView, int maxDigits) { int num; for (num = 0; num <= 255; num++) { textView->DisallowChar(num); } for (num = 0; num <= 9; num++) { textView->AllowChar('0' + num); } textView->SetMaxBytes(maxDigits); } void JobSetupView::AttachedToWindow() { // quality BBox* qualityBox = new BBox("quality"); qualityBox->SetLabel("Quality"); // color fColorType = new BPopUpMenu("color"); fColorType->SetRadioMode(true); FillCapabilityMenu(fColorType, kMsgQuality, PrinterCap::kColor, fJobData->GetColor()); BMenuField* colorMenuField = new BMenuField("color", "Color:", fColorType); fColorType->SetTargetForItems(this); if (IsHalftoneConfigurationNeeded()) CreateHalftoneConfigurationUI(); // page range BBox* pageRangeBox = new BBox("pageRange"); pageRangeBox->SetLabel("Page range"); fAll = new BRadioButton("all", "Print all Pages", new BMessage(kMsgRangeAll)); BRadioButton *range = new BRadioButton("selection", "Print selected Pages:", new BMessage(kMsgRangeSelection)); fFromPage = new BTextControl("from", "From:", "", NULL); fFromPage->SetAlignment(B_ALIGN_LEFT, B_ALIGN_RIGHT); AllowOnlyDigits(fFromPage->TextView(), 6); fToPage = new BTextControl("to", "To:", "", NULL); fToPage->SetAlignment(B_ALIGN_LEFT, B_ALIGN_RIGHT); AllowOnlyDigits(fToPage->TextView(), 6); int first_page = fJobData->GetFirstPage(); int last_page = fJobData->GetLastPage(); if (first_page <= 1 && last_page <= 0) { fAll->SetValue(B_CONTROL_ON); } else { range->SetValue(B_CONTROL_ON); if (first_page < 1) first_page = 1; if (first_page > last_page) last_page = -1; BString oss1; oss1 << first_page; fFromPage->SetText(oss1.String()); BString oss2; oss2 << last_page; fToPage->SetText(oss2.String()); } fAll->SetTarget(this); range->SetTarget(this); // paper source fPaperFeed = new BPopUpMenu(""); fPaperFeed->SetRadioMode(true); FillCapabilityMenu(fPaperFeed, kMsgNone, PrinterCap::kPaperSource, fJobData->GetPaperSource()); BMenuField* paperSourceMenufield = new BMenuField("paperSource", "Paper source:", fPaperFeed); // Pages per sheet fNup = new BPopUpMenu(""); fNup->SetRadioMode(true); FillCapabilityMenu(fNup, kMsgNone, gNups, sizeof(gNups) / sizeof(gNups[0]), (int)fJobData->GetNup()); BMenuField* pagesPerSheet = new BMenuField("pagesPerSheet", "Pages per sheet:", fNup); // duplex if (fPrinterCap->Supports(PrinterCap::kPrintStyle)) { fDuplex = new BCheckBox("duplex", "Duplex", new BMessage(kMsgDuplexChanged)); if (fJobData->GetPrintStyle() != JobData::kSimplex) { fDuplex->SetValue(B_CONTROL_ON); } fDuplex->SetTarget(this); } else { fDuplex = NULL; } // copies fCopies = new BTextControl("copies", "Number of copies:", "", NULL); AllowOnlyDigits(fCopies->TextView(), 3); BString copies; copies << fJobData->GetCopies(); fCopies->SetText(copies.String()); // collate fCollate = new BCheckBox("collate", "Collate", new BMessage(kMsgCollateChanged)); if (fJobData->GetCollate()) { fCollate->SetValue(B_CONTROL_ON); } fCollate->SetTarget(this); // reverse fReverse = new BCheckBox("reverse", "Reverse order", new BMessage(kMsgReverseChanged)); if (fJobData->GetReverse()) { fReverse->SetValue(B_CONTROL_ON); } fReverse->SetTarget(this); // pages view // TODO make layout API compatible fPages = new PagesView(BRect(0, 0, 150, 40), "pages", B_FOLLOW_ALL, B_WILL_DRAW); fPages->SetCollate(fJobData->GetCollate()); fPages->SetReverse(fJobData->GetReverse()); fPages->SetExplicitMinSize(BSize(150, 40)); fPages->SetExplicitMaxSize(BSize(150, 40)); // page selection BBox* pageSelectionBox = new BBox("pageSelection"); pageSelectionBox->SetLabel("Page selection"); fAllPages = CreatePageSelectionItem("allPages", "All pages", JobData::kAllPages); fOddNumberedPages = CreatePageSelectionItem("oddPages", "Odd-numbered pages", JobData::kOddNumberedPages); fEvenNumberedPages = CreatePageSelectionItem("evenPages", "Even-numbered pages", JobData::kEvenNumberedPages); fPreview = new BCheckBox("preview", "Show preview before printing", NULL); if (fJobData->GetShowPreview()) fPreview->SetValue(B_CONTROL_ON); // separator line BBox *separator = new BBox("separator"); separator->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 1)); // buttons BButton* cancel = new BButton("cancel", "Cancel", new BMessage(kMsgCancel)); BButton* ok = new BButton("ok", "OK", new BMessage(kMsgOK)); ok->MakeDefault(true); if (IsHalftoneConfigurationNeeded()) { BGroupView* halftoneGroup = new BGroupView(B_VERTICAL, 0); BGroupLayout* halftoneLayout = halftoneGroup->GroupLayout(); halftoneLayout->AddView(fHalftone); fHalftoneBox->AddChild(halftoneGroup); } BGridView* qualityGrid = new BGridView(); BGridLayout* qualityGridLayout = qualityGrid->GridLayout(); qualityGridLayout->AddItem(colorMenuField->CreateLabelLayoutItem(), 0, 0); qualityGridLayout->AddItem(colorMenuField->CreateMenuBarLayoutItem(), 1, 0); if (IsHalftoneConfigurationNeeded()) { qualityGridLayout->AddItem(fDitherMenuField->CreateLabelLayoutItem(), 0, 1); qualityGridLayout->AddItem(fDitherMenuField->CreateMenuBarLayoutItem(), 1, 1); qualityGridLayout->AddView(fGamma, 0, 2, 2); qualityGridLayout->AddView(fInkDensity, 0, 3, 2); qualityGridLayout->AddView(fHalftoneBox, 0, 4, 2); } else { AddDriverSpecificSettings(qualityGridLayout, 1); } qualityGridLayout->SetSpacing(0, 0); qualityGridLayout->SetInsets(5, 5, 5, 5); qualityBox->AddChild(qualityGrid); // TODO put qualityGrid in a scroll view // the layout of the box surrounding the scroll view using the following // code is not correct; the box still has the size of the qualityGird; // and the scroll view is vertically centered inside the box! //BScrollView* qualityScroller = new BScrollView("qualityScroller", // qualityGrid, 0, false, true); //qualityScroller->SetExplicitMaxSize(BSize(500, 500)); //qualityBox->AddChild(qualityScroller); BGridView* pageRangeGrid = new BGridView(); BGridLayout* pageRangeLayout = pageRangeGrid->GridLayout(); pageRangeLayout->AddItem(fFromPage->CreateLabelLayoutItem(), 0, 0); pageRangeLayout->AddItem(fFromPage->CreateTextViewLayoutItem(), 1, 0); pageRangeLayout->AddItem(fToPage->CreateLabelLayoutItem(), 0, 1); pageRangeLayout->AddItem(fToPage->CreateTextViewLayoutItem(), 1, 1); pageRangeLayout->SetInsets(0, 0, 0, 0); pageRangeLayout->SetSpacing(0, 0); BGroupView* pageRangeGroup = new BGroupView(B_VERTICAL, 0); BGroupLayout* pageRangeGroupLayout = pageRangeGroup->GroupLayout(); pageRangeGroupLayout->AddView(fAll); pageRangeGroupLayout->AddView(range); pageRangeGroupLayout->AddView(pageRangeGrid); pageRangeGroupLayout->SetInsets(5, 5, 5, 5); pageRangeBox->AddChild(pageRangeGroup); BGridView* settings = new BGridView(); BGridLayout* settingsLayout = settings->GridLayout(); settingsLayout->AddItem(paperSourceMenufield->CreateLabelLayoutItem(), 0, 0); settingsLayout->AddItem(paperSourceMenufield->CreateMenuBarLayoutItem(), 1, 0); settingsLayout->AddItem(pagesPerSheet->CreateLabelLayoutItem(), 0, 1); settingsLayout->AddItem(pagesPerSheet->CreateMenuBarLayoutItem(), 1, 1); int row = 2; if (fDuplex != NULL) { settingsLayout->AddView(fDuplex, 0, row, 2); row ++; } settingsLayout->AddItem(fCopies->CreateLabelLayoutItem(), 0, row); settingsLayout->AddItem(fCopies->CreateTextViewLayoutItem(), 1, row); settingsLayout->SetSpacing(0, 0); BGroupView* pageSelectionGroup = new BGroupView(B_VERTICAL, 0); BGroupLayout* groupLayout = pageSelectionGroup->GroupLayout(); groupLayout->AddView(fAllPages); groupLayout->AddView(fOddNumberedPages); groupLayout->AddView(fEvenNumberedPages); groupLayout->SetInsets(5, 5, 5, 5); pageSelectionBox->AddChild(pageSelectionGroup); SetLayout(new BGroupLayout(B_VERTICAL)); AddChild(BGroupLayoutBuilder(B_VERTICAL, 0) .AddGroup(B_HORIZONTAL, 10, 1.0f) .AddGroup(B_VERTICAL, 10, 1.0f) .Add(qualityBox) .Add(pageRangeBox) .AddGlue() .End() .AddGroup(B_VERTICAL, 0, 1.0f) .Add(settings) .AddStrut(5) .Add(fCollate) .Add(fReverse) .Add(fPages) .AddStrut(5) .Add(pageSelectionBox) .AddGlue() .End() .End() .Add(fPreview) .AddGlue() .Add(separator) .AddGroup(B_HORIZONTAL, 10, 1.0f) .AddGlue() .Add(cancel) .Add(ok) .End() .SetInsets(0, 0, 0, 0) ); UpdateHalftonePreview(); UpdateButtonEnabledState(); } bool JobSetupView::IsHalftoneConfigurationNeeded() { return fPrinterCap->Supports(PrinterCap::kHalftone); } void JobSetupView::CreateHalftoneConfigurationUI() { // dither type fDitherType = new BPopUpMenu(""); fDitherType->SetRadioMode(true); FillCapabilityMenu(fDitherType, kMsgQuality, gDitherTypes, sizeof(gDitherTypes) / sizeof(gDitherTypes[0]), (int)fJobData->GetDitherType()); fDitherMenuField = new BMenuField("dithering", "Dot Pattern:", fDitherType); fDitherType->SetTargetForItems(this); // halftone preview view fHalftoneBox = new BBox("halftoneBox"); fHalftoneBox->SetBorder(B_PLAIN_BORDER); // TODO make layout compatible BSize size(240, 14 * 4); BRect rect(0, 0, size.width, size.height); fHalftone = new HalftoneView(rect, "halftone", B_FOLLOW_ALL, B_WILL_DRAW); fHalftone->SetExplicitMinSize(size); fHalftone->SetExplicitMaxSize(size); // gamma fGamma = new JSDSlider("gamma", "Gamma", new BMessage(kMsgQuality), -300, 300); fGamma->SetLimitLabels("Lighter", "Darker"); fGamma->SetValue((int32)(100 * log(fJobData->GetGamma()) / log(2.0))); fGamma->SetHashMarks(B_HASH_MARKS_BOTH); fGamma->SetHashMarkCount(7); fGamma->SetModificationMessage(new BMessage(kMsgQuality)); fGamma->SetTarget(this); // ink density fInkDensity = new JSDSlider("inkDensity", "Ink usage", new BMessage(kMsgQuality), 0, 127); fInkDensity->SetLimitLabels("Min", "Max"); fInkDensity->SetValue((int32)fJobData->GetInkDensity()); fInkDensity->SetHashMarks(B_HASH_MARKS_BOTH); fInkDensity->SetHashMarkCount(10); fInkDensity->SetModificationMessage(new BMessage(kMsgQuality)); fInkDensity->SetTarget(this); } void JobSetupView::AddDriverSpecificSettings(BGridLayout* gridLayout, int row) { if (!fPrinterCap->Supports(PrinterCap::kDriverSpecificCapabilities)) return; int count = fPrinterCap->CountCap(PrinterCap::kDriverSpecificCapabilities); const BaseCap** capabilities = fPrinterCap->GetCaps( PrinterCap::kDriverSpecificCapabilities); for (int i = 0; i < count; i ++) { const DriverSpecificCap* capability = static_cast(capabilities[i]); switch (capability->fType) { case DriverSpecificCap::kList: AddPopUpMenu(capability, gridLayout, row); break; case DriverSpecificCap::kBoolean: AddCheckBox(capability, gridLayout, row); break; case DriverSpecificCap::kIntRange: case DriverSpecificCap::kIntDimension: AddIntSlider(capability, gridLayout, row); break; case DriverSpecificCap::kDoubleRange: AddDoubleSlider(capability, gridLayout, row); break; } } } void JobSetupView::AddPopUpMenu(const DriverSpecificCap* capability, BGridLayout* gridLayout, int& row) { const char* label = capability->fLabel.c_str(); BPopUpMenu* popUpMenu = new BPopUpMenu(label); popUpMenu->SetRadioMode(true); PrinterCap::CapID category = static_cast( capability->ID()); const BaseCap** categoryCapabilities = fPrinterCap->GetCaps(category); int categoryCount = fPrinterCap->CountCap(category); string value = GetDriverSpecificValue(category, capability->Key()); PrinterCap::KeyPredicate predicate(value.c_str()); FillCapabilityMenu(popUpMenu, kMsgNone, categoryCapabilities, categoryCount, predicate); BString menuLabel = label; menuLabel << ":"; BMenuField* menuField = new BMenuField(label, menuLabel.String(), popUpMenu); popUpMenu->SetTargetForItems(this); gridLayout->AddItem(menuField->CreateLabelLayoutItem(), 0, row); gridLayout->AddItem(menuField->CreateMenuBarLayoutItem(), 1, row); row ++; fDriverSpecificPopUpMenus[category] = popUpMenu; } void JobSetupView::AddCheckBox(const DriverSpecificCap* capability, BGridLayout* gridLayout, int& row) { PrinterCap::CapID category = static_cast( capability->ID()); const BooleanCap* booleanCap = fPrinterCap->FindBooleanCap(category); if (booleanCap == NULL) { fprintf(stderr, "Internal error: BooleanCap for '%s' not found!\n", capability->Label()); return; } const char* key = capability->Key(); BString name; name << "pds_" << key; BCheckBox* checkBox = new BCheckBox(name.String(), capability->Label(), NULL); bool value = booleanCap->DefaultValue(); if (fJobData->Settings().HasBoolean(key)) value = fJobData->Settings().GetBoolean(key); if (value) checkBox->SetValue(B_CONTROL_ON); gridLayout->AddView(checkBox, 0, row, 2); row ++; fDriverSpecificCheckBoxes[capability->Key()] = checkBox; } void JobSetupView::AddIntSlider(const DriverSpecificCap* capability, BGridLayout* gridLayout, int& row) { PrinterCap::CapID category = static_cast( capability->ID()); const IntRangeCap* range = fPrinterCap->FindIntRangeCap(category); if (range == NULL) { fprintf(stderr, "Internal error: IntRangeCap for '%s' not found!\n", capability->Label()); return; } const char* label = capability->Label(); const char* key = capability->Key(); BString name; name << "pds_" << key; BMessage* message = new BMessage(kMsgIntSliderChanged); message->AddInt32(kCategoryID, category); BSlider* slider = new BSlider(name.String(), label, message, 0, 1000, B_HORIZONTAL); slider->SetModificationMessage(new BMessage(*message)); slider->SetTarget(this); int32 value = range->DefaultValue(); if (fJobData->Settings().HasInt(key)) value = fJobData->Settings().GetInt(key); float position = (value - range->Lower()) / (range->Upper() - range->Lower()); slider->SetPosition(position); gridLayout->AddView(slider, 0, row, 2); row ++; IntRange intRange(label, key, range, slider); fDriverSpecificIntSliders[category] = intRange; intRange.UpdateLabel(); } void JobSetupView::AddDoubleSlider(const DriverSpecificCap* capability, BGridLayout* gridLayout, int& row) { PrinterCap::CapID category = static_cast( capability->ID()); const DoubleRangeCap* range = fPrinterCap->FindDoubleRangeCap(category); if (range == NULL) { fprintf(stderr, "Internal error: DoubleRangeCap for '%s' not found!\n", capability->Label()); return; } const char* label = capability->Label(); const char* key = capability->Key(); BString name; name << "pds_" << key; BMessage* message = new BMessage(kMsgDoubleSliderChanged); message->AddInt32(kCategoryID, category); BSlider* slider = new BSlider(name.String(), label, message, 0, 1000, B_HORIZONTAL); slider->SetModificationMessage(new BMessage(*message)); slider->SetTarget(this); double value = range->DefaultValue(); if (fJobData->Settings().HasDouble(key)) value = fJobData->Settings().GetDouble(key); float position = static_cast((value - range->Lower()) / (range->Upper() - range->Lower())); slider->SetPosition(position); gridLayout->AddView(slider, 0, row, 2); row ++; DoubleRange doubleRange(label, key, range, slider); fDriverSpecificDoubleSliders[category] = doubleRange; doubleRange.UpdateLabel(); } string JobSetupView::GetDriverSpecificValue(PrinterCap::CapID category, const char* key) { if (fJobData->Settings().HasString(key)) return fJobData->Settings().GetString(key); const EnumCap* defaultCapability = fPrinterCap->GetDefaultCap(category); return defaultCapability->fKey; } template void JobSetupView::FillCapabilityMenu(BPopUpMenu* menu, uint32 message, const BaseCap** capabilities, int count, Predicate& predicate) { bool marked = false; BMenuItem* firstItem = NULL; BMenuItem* defaultItem = NULL; BMenuItem* item = NULL; while (count--) { const EnumCap* capability = dynamic_cast(*capabilities); if (message != kMsgNone) item = new BMenuItem(capability->fLabel.c_str(), new BMessage(message)); else item = new BMenuItem(capability->fLabel.c_str(), NULL); menu->AddItem(item); if (firstItem == NULL) firstItem = item; if (capability->fIsDefault) defaultItem = item; if (predicate(capability)) { item->SetMarked(true); marked = true; } capabilities++; } if (marked) return; if (defaultItem != NULL) defaultItem->SetMarked(true); else if (firstItem != NULL) firstItem->SetMarked(true); } void JobSetupView::FillCapabilityMenu(BPopUpMenu* menu, uint32 message, PrinterCap::CapID category, int id) { PrinterCap::IDPredicate predicate(id); int count = fPrinterCap->CountCap(category); const BaseCap **capabilities = fPrinterCap->GetCaps(category); FillCapabilityMenu(menu, message, capabilities, count, predicate); } void JobSetupView::FillCapabilityMenu(BPopUpMenu* menu, uint32 message, const BaseCap** capabilities, int count, int id) { PrinterCap::IDPredicate predicate(id); FillCapabilityMenu(menu, message, capabilities, count, predicate); } int JobSetupView::GetID(const BaseCap** capabilities, int count, const char* label, int defaultValue) { while (count--) { const EnumCap* capability = dynamic_cast(*capabilities); if (capability == NULL) break; if (capability->fLabel == label) return capability->ID(); } return defaultValue; } void JobSetupView::UpdateButtonEnabledState() { bool pageRangeEnabled = fAll->Value() != B_CONTROL_ON; fFromPage->SetEnabled(pageRangeEnabled); fToPage->SetEnabled(pageRangeEnabled); bool pageSelectionEnabled = fDuplex == NULL || fDuplex->Value() != B_CONTROL_ON; fAllPages->SetEnabled(pageSelectionEnabled); fOddNumberedPages->SetEnabled(pageSelectionEnabled); fEvenNumberedPages->SetEnabled(pageSelectionEnabled); } void JobSetupView::MessageReceived(BMessage* message) { switch (message->what) { case kMsgRangeAll: case kMsgRangeSelection: case kMsgDuplexChanged: UpdateButtonEnabledState(); break; case kMsgQuality: UpdateHalftonePreview(); break; case kMsgCollateChanged: fPages->SetCollate(fCollate->Value() == B_CONTROL_ON); break; case kMsgReverseChanged: fPages->SetReverse(fReverse->Value() == B_CONTROL_ON); break; case kMsgIntSliderChanged: UpdateIntSlider(message); break; case kMsgDoubleSliderChanged: UpdateDoubleSlider(message); break; } } void JobSetupView::UpdateHalftonePreview() { if (!IsHalftoneConfigurationNeeded()) return; fHalftone->Preview(Gamma(), InkDensity(), DitherType(), Color() != JobData::kMonochrome); } void JobSetupView::UpdateIntSlider(BMessage* message) { int32 id; if (message->FindInt32(kCategoryID, &id) != B_OK) return; PrinterCap::CapID capID = static_cast(id); fDriverSpecificIntSliders[capID].UpdateLabel(); } void JobSetupView::UpdateDoubleSlider(BMessage* message) { int32 id; if (message->FindInt32(kCategoryID, &id) != B_OK) return; PrinterCap::CapID capID = static_cast(id); fDriverSpecificDoubleSliders[capID].UpdateLabel(); } JobData::Color JobSetupView::Color() { const char *label = fColorType->FindMarked()->Label(); const BaseCap* capability = fPrinterCap->FindCap(PrinterCap::kColor, label); if (capability == NULL) return JobData::kMonochrome; const ColorCap* colorCap = static_cast(capability); return colorCap->fColor; } Halftone::DitherType JobSetupView::DitherType() { const char *label = fDitherType->FindMarked()->Label(); int id = GetID(gDitherTypes, sizeof(gDitherTypes) / sizeof(gDitherTypes[0]), label, Halftone::kTypeFloydSteinberg); return static_cast(id); } float JobSetupView::Gamma() { const float value = (float)fGamma->Value(); return pow(2.0, value / 100.0); } float JobSetupView::InkDensity() { const float value = (float)(127 - fInkDensity->Value()); return value; } JobData::PaperSource JobSetupView::PaperSource() { const char *label = fPaperFeed->FindMarked()->Label(); const BaseCap* capability = fPrinterCap->FindCap(PrinterCap::kPaperSource, label); if (capability == NULL) capability = fPrinterCap->GetDefaultCap(PrinterCap::kPaperSource); return static_cast(capability)->fPaperSource; } bool JobSetupView::UpdateJobData() { fJobData->SetShowPreview(fPreview->Value() == B_CONTROL_ON); fJobData->SetColor(Color()); if (IsHalftoneConfigurationNeeded()) { fJobData->SetGamma(Gamma()); fJobData->SetInkDensity(InkDensity()); fJobData->SetDitherType(DitherType()); } int first_page; int last_page; if (B_CONTROL_ON == fAll->Value()) { first_page = 1; last_page = -1; } else { first_page = atoi(fFromPage->Text()); last_page = atoi(fToPage->Text()); } fJobData->SetFirstPage(first_page); fJobData->SetLastPage(last_page); fJobData->SetPaperSource(PaperSource()); fJobData->SetNup(GetID(gNups, sizeof(gNups) / sizeof(gNups[0]), fNup->FindMarked()->Label(), 1)); if (fPrinterCap->Supports(PrinterCap::kPrintStyle)) { fJobData->SetPrintStyle((B_CONTROL_ON == fDuplex->Value()) ? JobData::kDuplex : JobData::kSimplex); } fJobData->SetCopies(atoi(fCopies->Text())); fJobData->SetCollate(B_CONTROL_ON == fCollate->Value()); fJobData->SetReverse(B_CONTROL_ON == fReverse->Value()); JobData::PageSelection pageSelection = JobData::kAllPages; if (fOddNumberedPages->Value() == B_CONTROL_ON) pageSelection = JobData::kOddNumberedPages; if (fEvenNumberedPages->Value() == B_CONTROL_ON) pageSelection = JobData::kEvenNumberedPages; fJobData->SetPageSelection(pageSelection); { std::map::iterator it = fDriverSpecificPopUpMenus.begin(); for(; it != fDriverSpecificPopUpMenus.end(); it++) { PrinterCap::CapID category = it->first; BPopUpMenu* popUpMenu = it->second; const char* key = fPrinterCap->FindCap( PrinterCap::kDriverSpecificCapabilities, (int)category)->Key(); const char* label = popUpMenu->FindMarked()->Label(); const char* value = static_cast(fPrinterCap-> FindCap(category, label))->Key(); fJobData->Settings().SetString(key, value); } } { std::map::iterator it = fDriverSpecificCheckBoxes.begin(); for(; it != fDriverSpecificCheckBoxes.end(); it++) { const char* key = it->first.c_str(); BCheckBox* checkBox = it->second; bool value = checkBox->Value() == B_CONTROL_ON; fJobData->Settings().SetBoolean(key, value); } } { std::map::iterator it = fDriverSpecificIntSliders.begin(); for(; it != fDriverSpecificIntSliders.end(); it++) { IntRange& range = it->second; fJobData->Settings().SetInt(range.Key(), range.Value()); } } { std::map::iterator it = fDriverSpecificDoubleSliders.begin(); for(; it != fDriverSpecificDoubleSliders.end(); it++) { DoubleRange& range = it->second; fJobData->Settings().SetDouble(range.Key(), range.Value()); } } fJobData->Save(); return true; } JobSetupDlg::JobSetupDlg(JobData* jobData, PrinterData* printerData, const PrinterCap* printerCap) : DialogWindow(BRect(100, 100, 200, 200), "Print job setup", B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, B_NOT_RESIZABLE | B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE) { SetResult(B_ERROR); AddShortcut('W', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED)); fJobSetup = new JobSetupView(jobData, printerData, printerCap); SetLayout(new BGroupLayout(B_VERTICAL)); AddChild(BGroupLayoutBuilder(B_VERTICAL, 0) .Add(fJobSetup) .SetInsets(10, 10, 10, 10) ); } void JobSetupDlg::MessageReceived(BMessage* message) { switch (message->what) { case kMsgOK: fJobSetup->UpdateJobData(); SetResult(B_NO_ERROR); PostMessage(B_QUIT_REQUESTED); break; case kMsgCancel: PostMessage(B_QUIT_REQUESTED); break; default: DialogWindow::MessageReceived(message); break; } }