3 * Copyright 1999-2000 Y.Takagi. All Rights Reserved.
22 #include <GroupLayout.h>
23 #include <GroupLayoutBuilder.h>
25 #include <MessageFilter.h>
26 #include <MenuField.h>
30 #include <PopUpMenu.h>
32 #include <RadioButton.h>
36 #include <TextControl.h>
40 #include "HalftoneView.h"
41 #include "JobSetupDlg.h"
43 #include "JSDSlider.h"
44 #include "PagesView.h"
45 #include "PrinterData.h"
46 #include "PrinterCap.h"
53 struct NupCap
: public EnumCap
{
54 NupCap(const string
&label
, bool isDefault
, int nup
)
56 EnumCap(label
, isDefault
),
60 int32
ID() const { return fNup
; }
66 struct DitherCap
: public EnumCap
{
67 DitherCap(const string
&label
, bool isDefault
,
68 Halftone::DitherType ditherType
)
70 EnumCap(label
, isDefault
),
71 fDitherType(ditherType
)
74 int32
ID() const { return fDitherType
; }
76 Halftone::DitherType fDitherType
;
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);
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
);
98 const BaseCap
*gNups
[] = {
111 const BaseCap
*gDitherTypes
[] = {
115 &gDitherFloydSteinberg
119 static const char* kCategoryID
= "id";
123 kMsgRangeAll
= 'JSdl',
131 kMsgIntSliderChanged
,
132 kMsgDoubleSliderChanged
,
137 JobSetupView::JobSetupView(JobData
* jobData
, PrinterData
* printerData
,
138 const PrinterCap
*printerCap
)
140 BView("jobSetup", B_WILL_DRAW
),
145 fPrinterData(printerData
),
146 fPrinterCap(printerCap
),
160 fOddNumberedPages(NULL
),
161 fEvenNumberedPages(NULL
)
163 SetViewUIColor(B_PANEL_BACKGROUND_COLOR
);
168 JobSetupView::CreatePageSelectionItem(const char* name
, const char* label
,
169 JobData::PageSelection pageSelection
)
171 BRadioButton
* button
= new BRadioButton(name
, label
, NULL
);
172 if (fJobData
->GetPageSelection() == pageSelection
) {
173 button
->SetValue(B_CONTROL_ON
);
180 JobSetupView::AllowOnlyDigits(BTextView
* textView
, int maxDigits
)
183 for (num
= 0; num
<= 255; num
++) {
184 textView
->DisallowChar(num
);
186 for (num
= 0; num
<= 9; num
++) {
187 textView
->AllowChar('0' + num
);
189 textView
->SetMaxBytes(maxDigits
);
194 JobSetupView::AttachedToWindow()
197 BBox
* qualityBox
= new BBox("quality");
198 qualityBox
->SetLabel("Quality");
201 fColorType
= new BPopUpMenu("color");
202 fColorType
->SetRadioMode(true);
203 FillCapabilityMenu(fColorType
, kMsgQuality
, PrinterCap::kColor
,
204 fJobData
->GetColor());
205 BMenuField
* colorMenuField
= new BMenuField("color", "Color:", fColorType
);
206 fColorType
->SetTargetForItems(this);
208 if (IsHalftoneConfigurationNeeded())
209 CreateHalftoneConfigurationUI();
213 BBox
* pageRangeBox
= new BBox("pageRange");
214 pageRangeBox
->SetLabel("Page range");
216 fAll
= new BRadioButton("all", "Print all Pages", new BMessage(kMsgRangeAll
));
218 BRadioButton
*range
= new BRadioButton("selection", "Print selected Pages:",
219 new BMessage(kMsgRangeSelection
));
221 fFromPage
= new BTextControl("from", "From:", "", NULL
);
222 fFromPage
->SetAlignment(B_ALIGN_LEFT
, B_ALIGN_RIGHT
);
223 AllowOnlyDigits(fFromPage
->TextView(), 6);
225 fToPage
= new BTextControl("to", "To:", "", NULL
);
226 fToPage
->SetAlignment(B_ALIGN_LEFT
, B_ALIGN_RIGHT
);
227 AllowOnlyDigits(fToPage
->TextView(), 6);
229 int first_page
= fJobData
->GetFirstPage();
230 int last_page
= fJobData
->GetLastPage();
232 if (first_page
<= 1 && last_page
<= 0) {
233 fAll
->SetValue(B_CONTROL_ON
);
235 range
->SetValue(B_CONTROL_ON
);
238 if (first_page
> last_page
)
243 fFromPage
->SetText(oss1
.String());
247 fToPage
->SetText(oss2
.String());
250 fAll
->SetTarget(this);
251 range
->SetTarget(this);
254 fPaperFeed
= new BPopUpMenu("");
255 fPaperFeed
->SetRadioMode(true);
256 FillCapabilityMenu(fPaperFeed
, kMsgNone
, PrinterCap::kPaperSource
,
257 fJobData
->GetPaperSource());
258 BMenuField
* paperSourceMenufield
= new BMenuField("paperSource",
259 "Paper source:", fPaperFeed
);
262 fNup
= new BPopUpMenu("");
263 fNup
->SetRadioMode(true);
264 FillCapabilityMenu(fNup
, kMsgNone
, gNups
,
265 sizeof(gNups
) / sizeof(gNups
[0]), (int)fJobData
->GetNup());
266 BMenuField
* pagesPerSheet
= new BMenuField("pagesPerSheet",
267 "Pages per sheet:", fNup
);
270 if (fPrinterCap
->Supports(PrinterCap::kPrintStyle
)) {
271 fDuplex
= new BCheckBox("duplex", "Duplex",
272 new BMessage(kMsgDuplexChanged
));
273 if (fJobData
->GetPrintStyle() != JobData::kSimplex
) {
274 fDuplex
->SetValue(B_CONTROL_ON
);
276 fDuplex
->SetTarget(this);
282 fCopies
= new BTextControl("copies", "Number of copies:", "", NULL
);
283 AllowOnlyDigits(fCopies
->TextView(), 3);
286 copies
<< fJobData
->GetCopies();
287 fCopies
->SetText(copies
.String());
290 fCollate
= new BCheckBox("collate", "Collate",
291 new BMessage(kMsgCollateChanged
));
292 if (fJobData
->GetCollate()) {
293 fCollate
->SetValue(B_CONTROL_ON
);
295 fCollate
->SetTarget(this);
298 fReverse
= new BCheckBox("reverse", "Reverse order",
299 new BMessage(kMsgReverseChanged
));
300 if (fJobData
->GetReverse()) {
301 fReverse
->SetValue(B_CONTROL_ON
);
303 fReverse
->SetTarget(this);
306 // TODO make layout API compatible
307 fPages
= new PagesView(BRect(0, 0, 150, 40), "pages", B_FOLLOW_ALL
,
309 fPages
->SetCollate(fJobData
->GetCollate());
310 fPages
->SetReverse(fJobData
->GetReverse());
311 fPages
->SetExplicitMinSize(BSize(150, 40));
312 fPages
->SetExplicitMaxSize(BSize(150, 40));
315 BBox
* pageSelectionBox
= new BBox("pageSelection");
316 pageSelectionBox
->SetLabel("Page selection");
318 fAllPages
= CreatePageSelectionItem("allPages", "All pages",
320 fOddNumberedPages
= CreatePageSelectionItem("oddPages",
321 "Odd-numbered pages", JobData::kOddNumberedPages
);
322 fEvenNumberedPages
= CreatePageSelectionItem("evenPages",
323 "Even-numbered pages", JobData::kEvenNumberedPages
);
325 fPreview
= new BCheckBox("preview", "Show preview before printing", NULL
);
326 if (fJobData
->GetShowPreview())
327 fPreview
->SetValue(B_CONTROL_ON
);
330 BBox
*separator
= new BBox("separator");
331 separator
->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED
, 1));
334 BButton
* cancel
= new BButton("cancel", "Cancel",
335 new BMessage(kMsgCancel
));
336 BButton
* ok
= new BButton("ok", "OK", new BMessage(kMsgOK
));
337 ok
->MakeDefault(true);
339 if (IsHalftoneConfigurationNeeded()) {
340 BGroupView
* halftoneGroup
= new BGroupView(B_VERTICAL
, 0);
341 BGroupLayout
* halftoneLayout
= halftoneGroup
->GroupLayout();
342 halftoneLayout
->AddView(fHalftone
);
343 fHalftoneBox
->AddChild(halftoneGroup
);
346 BGridView
* qualityGrid
= new BGridView();
347 BGridLayout
* qualityGridLayout
= qualityGrid
->GridLayout();
348 qualityGridLayout
->AddItem(colorMenuField
->CreateLabelLayoutItem(), 0, 0);
349 qualityGridLayout
->AddItem(colorMenuField
->CreateMenuBarLayoutItem(), 1, 0);
350 if (IsHalftoneConfigurationNeeded()) {
351 qualityGridLayout
->AddItem(fDitherMenuField
->CreateLabelLayoutItem(),
353 qualityGridLayout
->AddItem(fDitherMenuField
->CreateMenuBarLayoutItem(),
355 qualityGridLayout
->AddView(fGamma
, 0, 2, 2);
356 qualityGridLayout
->AddView(fInkDensity
, 0, 3, 2);
357 qualityGridLayout
->AddView(fHalftoneBox
, 0, 4, 2);
359 AddDriverSpecificSettings(qualityGridLayout
, 1);
361 qualityGridLayout
->SetSpacing(0, 0);
362 qualityGridLayout
->SetInsets(5, 5, 5, 5);
363 qualityBox
->AddChild(qualityGrid
);
364 // TODO put qualityGrid in a scroll view
365 // the layout of the box surrounding the scroll view using the following
366 // code is not correct; the box still has the size of the qualityGird;
367 // and the scroll view is vertically centered inside the box!
368 //BScrollView* qualityScroller = new BScrollView("qualityScroller",
369 // qualityGrid, 0, false, true);
370 //qualityScroller->SetExplicitMaxSize(BSize(500, 500));
371 //qualityBox->AddChild(qualityScroller);
373 BGridView
* pageRangeGrid
= new BGridView();
374 BGridLayout
* pageRangeLayout
= pageRangeGrid
->GridLayout();
375 pageRangeLayout
->AddItem(fFromPage
->CreateLabelLayoutItem(), 0, 0);
376 pageRangeLayout
->AddItem(fFromPage
->CreateTextViewLayoutItem(), 1, 0);
377 pageRangeLayout
->AddItem(fToPage
->CreateLabelLayoutItem(), 0, 1);
378 pageRangeLayout
->AddItem(fToPage
->CreateTextViewLayoutItem(), 1, 1);
379 pageRangeLayout
->SetInsets(0, 0, 0, 0);
380 pageRangeLayout
->SetSpacing(0, 0);
382 BGroupView
* pageRangeGroup
= new BGroupView(B_VERTICAL
, 0);
383 BGroupLayout
* pageRangeGroupLayout
= pageRangeGroup
->GroupLayout();
384 pageRangeGroupLayout
->AddView(fAll
);
385 pageRangeGroupLayout
->AddView(range
);
386 pageRangeGroupLayout
->AddView(pageRangeGrid
);
387 pageRangeGroupLayout
->SetInsets(5, 5, 5, 5);
388 pageRangeBox
->AddChild(pageRangeGroup
);
390 BGridView
* settings
= new BGridView();
391 BGridLayout
* settingsLayout
= settings
->GridLayout();
392 settingsLayout
->AddItem(paperSourceMenufield
->CreateLabelLayoutItem(), 0,
394 settingsLayout
->AddItem(paperSourceMenufield
->CreateMenuBarLayoutItem(), 1,
396 settingsLayout
->AddItem(pagesPerSheet
->CreateLabelLayoutItem(), 0, 1);
397 settingsLayout
->AddItem(pagesPerSheet
->CreateMenuBarLayoutItem(), 1, 1);
399 if (fDuplex
!= NULL
) {
400 settingsLayout
->AddView(fDuplex
, 0, row
, 2);
403 settingsLayout
->AddItem(fCopies
->CreateLabelLayoutItem(), 0, row
);
404 settingsLayout
->AddItem(fCopies
->CreateTextViewLayoutItem(), 1, row
);
405 settingsLayout
->SetSpacing(0, 0);
408 BGroupView
* pageSelectionGroup
= new BGroupView(B_VERTICAL
, 0);
409 BGroupLayout
* groupLayout
= pageSelectionGroup
->GroupLayout();
410 groupLayout
->AddView(fAllPages
);
411 groupLayout
->AddView(fOddNumberedPages
);
412 groupLayout
->AddView(fEvenNumberedPages
);
413 groupLayout
->SetInsets(5, 5, 5, 5);
414 pageSelectionBox
->AddChild(pageSelectionGroup
);
416 SetLayout(new BGroupLayout(B_VERTICAL
));
417 AddChild(BGroupLayoutBuilder(B_VERTICAL
, 0)
418 .AddGroup(B_HORIZONTAL
, 10, 1.0f
)
419 .AddGroup(B_VERTICAL
, 10, 1.0f
)
424 .AddGroup(B_VERTICAL
, 0, 1.0f
)
431 .Add(pageSelectionBox
)
438 .AddGroup(B_HORIZONTAL
, 10, 1.0f
)
443 .SetInsets(0, 0, 0, 0)
446 UpdateHalftonePreview();
448 UpdateButtonEnabledState();
453 JobSetupView::IsHalftoneConfigurationNeeded()
455 return fPrinterCap
->Supports(PrinterCap::kHalftone
);
460 JobSetupView::CreateHalftoneConfigurationUI()
463 fDitherType
= new BPopUpMenu("");
464 fDitherType
->SetRadioMode(true);
465 FillCapabilityMenu(fDitherType
, kMsgQuality
, gDitherTypes
,
466 sizeof(gDitherTypes
) / sizeof(gDitherTypes
[0]),
467 (int)fJobData
->GetDitherType());
468 fDitherMenuField
= new BMenuField("dithering", "Dot Pattern:",
470 fDitherType
->SetTargetForItems(this);
472 // halftone preview view
473 fHalftoneBox
= new BBox("halftoneBox");
474 fHalftoneBox
->SetBorder(B_PLAIN_BORDER
);
476 // TODO make layout compatible
477 BSize
size(240, 14 * 4);
478 BRect
rect(0, 0, size
.width
, size
.height
);
479 fHalftone
= new HalftoneView(rect
, "halftone",
480 B_FOLLOW_ALL
, B_WILL_DRAW
);
481 fHalftone
->SetExplicitMinSize(size
);
482 fHalftone
->SetExplicitMaxSize(size
);
485 fGamma
= new JSDSlider("gamma", "Gamma", new BMessage(kMsgQuality
),
488 fGamma
->SetLimitLabels("Lighter", "Darker");
489 fGamma
->SetValue((int32
)(100 * log(fJobData
->GetGamma()) / log(2.0)));
490 fGamma
->SetHashMarks(B_HASH_MARKS_BOTH
);
491 fGamma
->SetHashMarkCount(7);
492 fGamma
->SetModificationMessage(new BMessage(kMsgQuality
));
493 fGamma
->SetTarget(this);
496 fInkDensity
= new JSDSlider("inkDensity", "Ink usage",
497 new BMessage(kMsgQuality
), 0, 127);
499 fInkDensity
->SetLimitLabels("Min", "Max");
500 fInkDensity
->SetValue((int32
)fJobData
->GetInkDensity());
501 fInkDensity
->SetHashMarks(B_HASH_MARKS_BOTH
);
502 fInkDensity
->SetHashMarkCount(10);
503 fInkDensity
->SetModificationMessage(new BMessage(kMsgQuality
));
504 fInkDensity
->SetTarget(this);
509 JobSetupView::AddDriverSpecificSettings(BGridLayout
* gridLayout
, int row
)
511 if (!fPrinterCap
->Supports(PrinterCap::kDriverSpecificCapabilities
))
514 int count
= fPrinterCap
->CountCap(PrinterCap::kDriverSpecificCapabilities
);
515 const BaseCap
** capabilities
= fPrinterCap
->GetCaps(
516 PrinterCap::kDriverSpecificCapabilities
);
518 for (int i
= 0; i
< count
; i
++) {
519 const DriverSpecificCap
* capability
=
520 static_cast<const DriverSpecificCap
*>(capabilities
[i
]);
522 switch (capability
->fType
) {
523 case DriverSpecificCap::kList
:
524 AddPopUpMenu(capability
, gridLayout
, row
);
526 case DriverSpecificCap::kBoolean
:
527 AddCheckBox(capability
, gridLayout
, row
);
529 case DriverSpecificCap::kIntRange
:
530 case DriverSpecificCap::kIntDimension
:
531 AddIntSlider(capability
, gridLayout
, row
);
533 case DriverSpecificCap::kDoubleRange
:
534 AddDoubleSlider(capability
, gridLayout
, row
);
543 JobSetupView::AddPopUpMenu(const DriverSpecificCap
* capability
,
544 BGridLayout
* gridLayout
, int& row
)
546 const char* label
= capability
->fLabel
.c_str();
547 BPopUpMenu
* popUpMenu
= new BPopUpMenu(label
);
548 popUpMenu
->SetRadioMode(true);
550 PrinterCap::CapID category
= static_cast<PrinterCap::CapID
>(
553 const BaseCap
** categoryCapabilities
= fPrinterCap
->GetCaps(category
);
555 int categoryCount
= fPrinterCap
->CountCap(category
);
557 string value
= GetDriverSpecificValue(category
, capability
->Key());
558 PrinterCap::KeyPredicate
predicate(value
.c_str());
560 FillCapabilityMenu(popUpMenu
, kMsgNone
, categoryCapabilities
,
561 categoryCount
, predicate
);
563 BString menuLabel
= label
;
565 BMenuField
* menuField
= new BMenuField(label
, menuLabel
.String(),
567 popUpMenu
->SetTargetForItems(this);
569 gridLayout
->AddItem(menuField
->CreateLabelLayoutItem(),
571 gridLayout
->AddItem(menuField
->CreateMenuBarLayoutItem(),
575 fDriverSpecificPopUpMenus
[category
] = popUpMenu
;
580 JobSetupView::AddCheckBox(const DriverSpecificCap
* capability
,
581 BGridLayout
* gridLayout
, int& row
)
583 PrinterCap::CapID category
= static_cast<PrinterCap::CapID
>(
585 const BooleanCap
* booleanCap
= fPrinterCap
->FindBooleanCap(category
);
586 if (booleanCap
== NULL
) {
587 fprintf(stderr
, "Internal error: BooleanCap for '%s' not found!\n",
588 capability
->Label());
592 const char* key
= capability
->Key();
594 name
<< "pds_" << key
;
595 BCheckBox
* checkBox
= new BCheckBox(name
.String(), capability
->Label(),
598 bool value
= booleanCap
->DefaultValue();
599 if (fJobData
->Settings().HasBoolean(key
))
600 value
= fJobData
->Settings().GetBoolean(key
);
602 checkBox
->SetValue(B_CONTROL_ON
);
604 gridLayout
->AddView(checkBox
, 0, row
, 2);
607 fDriverSpecificCheckBoxes
[capability
->Key()] = checkBox
;
612 JobSetupView::AddIntSlider(const DriverSpecificCap
* capability
,
613 BGridLayout
* gridLayout
, int& row
)
615 PrinterCap::CapID category
= static_cast<PrinterCap::CapID
>(
617 const IntRangeCap
* range
= fPrinterCap
->FindIntRangeCap(category
);
619 fprintf(stderr
, "Internal error: IntRangeCap for '%s' not found!\n",
620 capability
->Label());
624 const char* label
= capability
->Label();
625 const char* key
= capability
->Key();
627 name
<< "pds_" << key
;
628 BMessage
* message
= new BMessage(kMsgIntSliderChanged
);
629 message
->AddInt32(kCategoryID
, category
);
630 BSlider
* slider
= new BSlider(name
.String(), label
,
631 message
, 0, 1000, B_HORIZONTAL
);
632 slider
->SetModificationMessage(new BMessage(*message
));
633 slider
->SetTarget(this);
635 int32 value
= range
->DefaultValue();
636 if (fJobData
->Settings().HasInt(key
))
637 value
= fJobData
->Settings().GetInt(key
);
638 float position
= (value
- range
->Lower()) /
639 (range
->Upper() - range
->Lower());
640 slider
->SetPosition(position
);
642 gridLayout
->AddView(slider
, 0, row
, 2);
645 IntRange
intRange(label
, key
, range
, slider
);
646 fDriverSpecificIntSliders
[category
] = intRange
;
647 intRange
.UpdateLabel();
652 JobSetupView::AddDoubleSlider(const DriverSpecificCap
* capability
,
653 BGridLayout
* gridLayout
, int& row
)
655 PrinterCap::CapID category
= static_cast<PrinterCap::CapID
>(
657 const DoubleRangeCap
* range
= fPrinterCap
->FindDoubleRangeCap(category
);
659 fprintf(stderr
, "Internal error: DoubleRangeCap for '%s' not found!\n",
660 capability
->Label());
664 const char* label
= capability
->Label();
665 const char* key
= capability
->Key();
667 name
<< "pds_" << key
;
668 BMessage
* message
= new BMessage(kMsgDoubleSliderChanged
);
669 message
->AddInt32(kCategoryID
, category
);
670 BSlider
* slider
= new BSlider(name
.String(), label
,
671 message
, 0, 1000, B_HORIZONTAL
);
672 slider
->SetModificationMessage(new BMessage(*message
));
673 slider
->SetTarget(this);
675 double value
= range
->DefaultValue();
676 if (fJobData
->Settings().HasDouble(key
))
677 value
= fJobData
->Settings().GetDouble(key
);
678 float position
= static_cast<float>((value
- range
->Lower()) /
679 (range
->Upper() - range
->Lower()));
680 slider
->SetPosition(position
);
682 gridLayout
->AddView(slider
, 0, row
, 2);
685 DoubleRange
doubleRange(label
, key
, range
, slider
);
686 fDriverSpecificDoubleSliders
[category
] = doubleRange
;
687 doubleRange
.UpdateLabel();
692 JobSetupView::GetDriverSpecificValue(PrinterCap::CapID category
,
695 if (fJobData
->Settings().HasString(key
))
696 return fJobData
->Settings().GetString(key
);
698 const EnumCap
* defaultCapability
= fPrinterCap
->GetDefaultCap(category
);
699 return defaultCapability
->fKey
;
703 template<typename Predicate
>
705 JobSetupView::FillCapabilityMenu(BPopUpMenu
* menu
, uint32 message
,
706 const BaseCap
** capabilities
, int count
, Predicate
& predicate
)
710 BMenuItem
* firstItem
= NULL
;
711 BMenuItem
* defaultItem
= NULL
;
712 BMenuItem
* item
= NULL
;
714 const EnumCap
* capability
= dynamic_cast<const EnumCap
*>(*capabilities
);
715 if (message
!= kMsgNone
)
716 item
= new BMenuItem(capability
->fLabel
.c_str(),
717 new BMessage(message
));
719 item
= new BMenuItem(capability
->fLabel
.c_str(), NULL
);
723 if (firstItem
== NULL
)
726 if (capability
->fIsDefault
)
730 if (predicate(capability
)) {
731 item
->SetMarked(true);
741 if (defaultItem
!= NULL
)
742 defaultItem
->SetMarked(true);
743 else if (firstItem
!= NULL
)
744 firstItem
->SetMarked(true);
749 JobSetupView::FillCapabilityMenu(BPopUpMenu
* menu
, uint32 message
,
750 PrinterCap::CapID category
, int id
)
752 PrinterCap::IDPredicate
predicate(id
);
753 int count
= fPrinterCap
->CountCap(category
);
754 const BaseCap
**capabilities
= fPrinterCap
->GetCaps(category
);
755 FillCapabilityMenu(menu
, message
, capabilities
, count
, predicate
);
760 JobSetupView::FillCapabilityMenu(BPopUpMenu
* menu
, uint32 message
,
761 const BaseCap
** capabilities
, int count
, int id
)
763 PrinterCap::IDPredicate
predicate(id
);
764 FillCapabilityMenu(menu
, message
, capabilities
, count
, predicate
);
769 JobSetupView::GetID(const BaseCap
** capabilities
, int count
, const char* label
,
773 const EnumCap
* capability
=
774 dynamic_cast<const EnumCap
*>(*capabilities
);
775 if (capability
== NULL
)
778 if (capability
->fLabel
== label
)
779 return capability
->ID();
786 JobSetupView::UpdateButtonEnabledState()
788 bool pageRangeEnabled
= fAll
->Value() != B_CONTROL_ON
;
789 fFromPage
->SetEnabled(pageRangeEnabled
);
790 fToPage
->SetEnabled(pageRangeEnabled
);
792 bool pageSelectionEnabled
= fDuplex
== NULL
||
793 fDuplex
->Value() != B_CONTROL_ON
;
794 fAllPages
->SetEnabled(pageSelectionEnabled
);
795 fOddNumberedPages
->SetEnabled(pageSelectionEnabled
);
796 fEvenNumberedPages
->SetEnabled(pageSelectionEnabled
);
801 JobSetupView::MessageReceived(BMessage
* message
)
803 switch (message
->what
) {
805 case kMsgRangeSelection
:
806 case kMsgDuplexChanged
:
807 UpdateButtonEnabledState();
811 UpdateHalftonePreview();
814 case kMsgCollateChanged
:
815 fPages
->SetCollate(fCollate
->Value() == B_CONTROL_ON
);
818 case kMsgReverseChanged
:
819 fPages
->SetReverse(fReverse
->Value() == B_CONTROL_ON
);
822 case kMsgIntSliderChanged
:
823 UpdateIntSlider(message
);
826 case kMsgDoubleSliderChanged
:
827 UpdateDoubleSlider(message
);
834 JobSetupView::UpdateHalftonePreview()
836 if (!IsHalftoneConfigurationNeeded())
839 fHalftone
->Preview(Gamma(), InkDensity(), DitherType(),
840 Color() != JobData::kMonochrome
);
845 JobSetupView::UpdateIntSlider(BMessage
* message
)
848 if (message
->FindInt32(kCategoryID
, &id
) != B_OK
)
850 PrinterCap::CapID capID
= static_cast<PrinterCap::CapID
>(id
);
851 fDriverSpecificIntSliders
[capID
].UpdateLabel();
856 JobSetupView::UpdateDoubleSlider(BMessage
* message
)
859 if (message
->FindInt32(kCategoryID
, &id
) != B_OK
)
861 PrinterCap::CapID capID
= static_cast<PrinterCap::CapID
>(id
);
862 fDriverSpecificDoubleSliders
[capID
].UpdateLabel();
867 JobSetupView::Color()
869 const char *label
= fColorType
->FindMarked()->Label();
870 const BaseCap
* capability
= fPrinterCap
->FindCap(PrinterCap::kColor
, label
);
871 if (capability
== NULL
)
872 return JobData::kMonochrome
;
874 const ColorCap
* colorCap
= static_cast<const ColorCap
*>(capability
);
875 return colorCap
->fColor
;
880 JobSetupView::DitherType()
882 const char *label
= fDitherType
->FindMarked()->Label();
883 int id
= GetID(gDitherTypes
, sizeof(gDitherTypes
) / sizeof(gDitherTypes
[0]),
884 label
, Halftone::kTypeFloydSteinberg
);
885 return static_cast<Halftone::DitherType
>(id
);
889 JobSetupView::Gamma()
891 const float value
= (float)fGamma
->Value();
892 return pow(2.0, value
/ 100.0);
897 JobSetupView::InkDensity()
899 const float value
= (float)(127 - fInkDensity
->Value());
905 JobSetupView::PaperSource()
907 const char *label
= fPaperFeed
->FindMarked()->Label();
908 const BaseCap
* capability
= fPrinterCap
->FindCap(PrinterCap::kPaperSource
,
911 if (capability
== NULL
)
912 capability
= fPrinterCap
->GetDefaultCap(PrinterCap::kPaperSource
);
913 return static_cast<const PaperSourceCap
*>(capability
)->fPaperSource
;
918 JobSetupView::UpdateJobData()
920 fJobData
->SetShowPreview(fPreview
->Value() == B_CONTROL_ON
);
921 fJobData
->SetColor(Color());
922 if (IsHalftoneConfigurationNeeded()) {
923 fJobData
->SetGamma(Gamma());
924 fJobData
->SetInkDensity(InkDensity());
925 fJobData
->SetDitherType(DitherType());
931 if (B_CONTROL_ON
== fAll
->Value()) {
935 first_page
= atoi(fFromPage
->Text());
936 last_page
= atoi(fToPage
->Text());
939 fJobData
->SetFirstPage(first_page
);
940 fJobData
->SetLastPage(last_page
);
942 fJobData
->SetPaperSource(PaperSource());
944 fJobData
->SetNup(GetID(gNups
, sizeof(gNups
) / sizeof(gNups
[0]),
945 fNup
->FindMarked()->Label(), 1));
947 if (fPrinterCap
->Supports(PrinterCap::kPrintStyle
)) {
948 fJobData
->SetPrintStyle((B_CONTROL_ON
== fDuplex
->Value())
949 ? JobData::kDuplex
: JobData::kSimplex
);
952 fJobData
->SetCopies(atoi(fCopies
->Text()));
954 fJobData
->SetCollate(B_CONTROL_ON
== fCollate
->Value());
955 fJobData
->SetReverse(B_CONTROL_ON
== fReverse
->Value());
957 JobData::PageSelection pageSelection
= JobData::kAllPages
;
958 if (fOddNumberedPages
->Value() == B_CONTROL_ON
)
959 pageSelection
= JobData::kOddNumberedPages
;
960 if (fEvenNumberedPages
->Value() == B_CONTROL_ON
)
961 pageSelection
= JobData::kEvenNumberedPages
;
962 fJobData
->SetPageSelection(pageSelection
);
965 std::map
<PrinterCap::CapID
, BPopUpMenu
*>::iterator it
=
966 fDriverSpecificPopUpMenus
.begin();
967 for(; it
!= fDriverSpecificPopUpMenus
.end(); it
++) {
968 PrinterCap::CapID category
= it
->first
;
969 BPopUpMenu
* popUpMenu
= it
->second
;
970 const char* key
= fPrinterCap
->FindCap(
971 PrinterCap::kDriverSpecificCapabilities
, (int)category
)->Key();
972 const char* label
= popUpMenu
->FindMarked()->Label();
973 const char* value
= static_cast<const EnumCap
*>(fPrinterCap
->
974 FindCap(category
, label
))->Key();
975 fJobData
->Settings().SetString(key
, value
);
980 std::map
<string
, BCheckBox
*>::iterator it
=
981 fDriverSpecificCheckBoxes
.begin();
982 for(; it
!= fDriverSpecificCheckBoxes
.end(); it
++) {
983 const char* key
= it
->first
.c_str();
984 BCheckBox
* checkBox
= it
->second
;
985 bool value
= checkBox
->Value() == B_CONTROL_ON
;
986 fJobData
->Settings().SetBoolean(key
, value
);
991 std::map
<PrinterCap::CapID
, IntRange
>::iterator it
=
992 fDriverSpecificIntSliders
.begin();
993 for(; it
!= fDriverSpecificIntSliders
.end(); it
++) {
994 IntRange
& range
= it
->second
;
995 fJobData
->Settings().SetInt(range
.Key(), range
.Value());
1000 std::map
<PrinterCap::CapID
, DoubleRange
>::iterator it
=
1001 fDriverSpecificDoubleSliders
.begin();
1002 for(; it
!= fDriverSpecificDoubleSliders
.end(); it
++) {
1003 DoubleRange
& range
= it
->second
;
1004 fJobData
->Settings().SetDouble(range
.Key(), range
.Value());
1013 JobSetupDlg::JobSetupDlg(JobData
* jobData
, PrinterData
* printerData
,
1014 const PrinterCap
* printerCap
)
1016 DialogWindow(BRect(100, 100, 200, 200), "Print job setup",
1017 B_TITLED_WINDOW_LOOK
, B_MODAL_APP_WINDOW_FEEL
,
1018 B_NOT_RESIZABLE
| B_NOT_MINIMIZABLE
| B_NOT_ZOOMABLE
1019 | B_ASYNCHRONOUS_CONTROLS
| B_AUTO_UPDATE_SIZE_LIMITS
1020 | B_CLOSE_ON_ESCAPE
)
1023 AddShortcut('W', B_COMMAND_KEY
, new BMessage(B_QUIT_REQUESTED
));
1025 fJobSetup
= new JobSetupView(jobData
, printerData
, printerCap
);
1026 SetLayout(new BGroupLayout(B_VERTICAL
));
1027 AddChild(BGroupLayoutBuilder(B_VERTICAL
, 0)
1029 .SetInsets(10, 10, 10, 10)
1035 JobSetupDlg::MessageReceived(BMessage
* message
)
1037 switch (message
->what
) {
1039 fJobSetup
->UpdateJobData();
1040 SetResult(B_NO_ERROR
);
1041 PostMessage(B_QUIT_REQUESTED
);
1045 PostMessage(B_QUIT_REQUESTED
);
1049 DialogWindow::MessageReceived(message
);