2 * Copyright 2008, Haiku.
3 * Distributed under the terms of the MIT license.
6 * Michael Pfeiffer <laplace@users.sourceforge.net>
9 #include "PPDConfigView.h"
10 #include "PPDParser.h"
11 #include "StatementListVisitor.h"
17 #include <MenuField.h>
19 #include <RadioButton.h>
20 #include <ScrollView.h>
21 #include <StringView.h>
25 const float kLeftMargin
= 3.0;
26 const float kRightMargin
= 3.0;
27 const float kTopMargin
= 3.0;
28 const float kBottomMargin
= 3.0;
30 // space between views
31 const float kHorizontalSpace
= 8.0;
32 const float kVerticalSpace
= 8.0;
34 // Message what values
35 const uint32 kMsgBooleanChanged
= 'bool';
36 const uint32 kMsgStringChanged
= 'strc';
40 class DefaultValueExtractor
: public StatementListVisitor
42 BMessage fDefaultValues
;
45 void DoDefault(Statement
* statement
)
47 const char* keyword
= statement
->GetKeywordString();
48 const char* value
= statement
->GetValueString();
49 if (keyword
!= NULL
&& value
!= NULL
) {
50 fDefaultValues
.AddString(keyword
, value
);
54 const BMessage
& GetDefaultValues()
56 return fDefaultValues
;
60 class CategoryBuilder
: public StatementListVisitor
62 BOutlineListView
* fCategories
;
65 CategoryBuilder(BOutlineListView
* categories
)
66 : fCategories(categories
)
69 void AddStatement(const char* text
, Statement
* statement
)
72 BStringItem
* item
= new CategoryItem(text
, statement
, GetLevel());
73 fCategories
->AddItem(item
);
77 void BeginGroup(GroupStatement
* group
)
79 const char* translation
= group
->GetGroupTranslation();
80 const char* name
= group
->GetGroupName();
82 const char* text
= NULL
;
83 if (translation
!= NULL
) {
89 AddStatement(text
, group
->GetStatement());
95 DetailsBuilder adds views to the details view and sets the
96 value to the one specified in the settings.
98 The group type determines the view to be used for user input:
100 ---------------------
106 class DetailsBuilder
: public StatementListVisitor
111 const char* fKeyword
;
113 GroupStatement fGroup
;
115 BMenuField
* fMenuField
;
116 const BMessage
& fSettings
;
118 void AddView(BView
* view
);
120 BMessage
* GetMessage(uint32 what
, const char* option
);
123 DetailsBuilder(BView
* parent
, BView
* details
, BRect bounds
, Statement
* group
, const BMessage
& settings
);
125 BRect
GetBounds() { return fBounds
; }
127 void Visit(StatementList
* list
);
129 void DoValue(Statement
* statement
);
132 void DetailsBuilder::AddView(BView
* view
)
135 fDetails
->AddChild(view
);
136 view
->ResizeToPreferred();
138 fBounds
.OffsetBy(0, view
->Bounds().Height()+1);
140 BControl
* control
= dynamic_cast<BControl
*>(view
);
141 if (control
!= NULL
) {
142 control
->SetTarget(fParent
);
147 DetailsBuilder::DetailsBuilder(BView
* parent
, BView
* details
, BRect bounds
, Statement
* group
, const BMessage
& settings
)
154 , fSettings(settings
)
156 fKeyword
= fGroup
.GetGroupName();
158 if (fKeyword
== NULL
) return;
160 fValue
= settings
.FindString(fKeyword
);
162 const char* label
= fGroup
.GetGroupTranslation();
168 if (fGroup
.GetType() == GroupStatement::kPickOne
) {
169 fMenu
= new BMenu("<pick one>");
170 fMenu
->SetRadioMode(true);
171 fMenu
->SetLabelFromMarked(true);
172 fMenuField
= new BMenuField(fBounds
, "menuField", label
, fMenu
);
174 } else if (fGroup
.GetType() == GroupStatement::kBoolean
) {
175 BMessage
* message
= GetMessage(kMsgBooleanChanged
, "");
176 BCheckBox
* cb
= new BCheckBox(fBounds
, "", label
, message
);
178 cb
->SetValue((fValue
!= NULL
&& strcmp(fValue
, "True") == 0)
186 void DetailsBuilder::Visit(StatementList
* list
)
188 if (fKeyword
== NULL
) return;
190 StatementListVisitor::Visit(list
);
193 BMessage
* DetailsBuilder::GetMessage(uint32 what
, const char* option
)
195 BMessage
* message
= new BMessage(what
);
196 message
->AddString("keyword", fKeyword
);
198 if (option
!= NULL
) {
199 message
->AddString("option", option
);
204 void DetailsBuilder::DoValue(Statement
* statement
)
206 if (GetLevel() != 0) return;
207 if (strcmp(fKeyword
, statement
->GetKeywordString()) != 0) return;
209 const char* text
= NULL
;
210 const char* option
= statement
->GetOptionString();
211 if (statement
->GetTranslationString() != NULL
) {
212 text
= statement
->GetTranslationString();
213 } else if (option
!= NULL
) {
217 if (text
== NULL
) return;
220 BMessage
* message
= NULL
;
222 if (fGroup
.GetType() == GroupStatement::kPickMany
||
223 fGroup
.GetType() == GroupStatement::kUnknown
) {
224 message
= GetMessage(kMsgStringChanged
, option
);
225 view
= new BCheckBox(fBounds
, "", text
, message
);
226 } else if (fGroup
.GetType() == GroupStatement::kPickOne
) {
227 message
= GetMessage(kMsgStringChanged
, option
);
228 BMenuItem
* item
= new BMenuItem(text
, message
);
229 item
->SetTarget(fParent
);
230 fMenu
->AddItem(item
);
231 if (fValue
!= NULL
&& option
!= NULL
&& strcmp(fValue
, option
) == 0) {
232 item
->SetMarked(true);
239 #define kBoxHeight 20
240 #define kBoxBottomMargin 4
241 #define kBoxLeftMargin 8
242 #define kBoxRightMargin 8
244 #define kItemLeftMargin 5
245 #define kItemRightMargin 5
247 class PPDBuilder
: public StatementListVisitor
257 return fNestedBoxes
.CountItems() == 0;
260 void Push(BView
* view
)
262 fNestedBoxes
.AddItem(view
);
267 fNestedBoxes
.RemoveItem((int32
)fNestedBoxes
.CountItems()-1);
275 return (BView
*)fNestedBoxes
.ItemAt(fNestedBoxes
.CountItems()-1);
281 BRect
GetControlBounds()
284 BRect
bounds(fBounds
);
285 bounds
.left
+= kItemLeftMargin
/** GetLevel()*/;
286 bounds
.right
-= kItemRightMargin
/** GetLevel()*/;
290 BView
* box
= GetView();
291 BRect
bounds(box
->Bounds());
292 bounds
.top
= bounds
.bottom
- kBoxBottomMargin
;
293 bounds
.bottom
= bounds
.top
+ kBoxHeight
;
294 bounds
.left
+= kBoxLeftMargin
;
295 bounds
.right
-= kBoxRightMargin
;
299 bool IsUIGroup(GroupStatement
* group
)
301 return group
->IsUIGroup() || group
->IsJCL();
304 void UpdateParentHeight(float height
)
307 fBounds
.OffsetBy(0, height
);
309 BView
* parent
= GetView();
310 parent
->ResizeBy(0, height
);
315 PPDBuilder(BView
* parent
, BView
* view
, BMessage
& settings
)
318 , fBounds(view
->Bounds())
319 , fSettings(settings
)
321 RemoveChildren(view
);
322 fBounds
.OffsetTo(0, 0);
323 fBounds
.left
+= kLeftMargin
;
324 fBounds
.top
+= kTopMargin
;
325 fBounds
.right
-= kRightMargin
;
330 return BRect(0, 0, fView
->Bounds().Width(), fBounds
.top
);
333 void AddUIGroup(const char* text
, Statement
* statement
)
335 if (statement
->GetChildren() == NULL
) return;
336 DetailsBuilder
builder(fParent
, GetView(), GetControlBounds(), statement
, fSettings
);
337 builder
.Visit(statement
->GetChildren());
340 fBounds
.OffsetTo(fBounds
.left
, builder
.GetBounds().top
);
342 BView
* box
= GetView();
343 box
->ResizeTo(box
->Bounds().Width(), builder
.GetBounds().top
+ kBoxBottomMargin
);
347 void OpenGroup(const char* text
)
350 BBox
* box
= new BBox(GetControlBounds(), text
);
352 GetView()->AddChild(box
);
354 box
->ResizeTo(box
->Bounds().Width(), kBoxHeight
);
361 BView
* box
= GetView();
363 UpdateParentHeight(box
->Bounds().Height());
367 void BeginGroup(GroupStatement
* group
)
369 const char* translation
= group
->GetGroupTranslation();
370 const char* name
= group
->GetGroupName();
372 const char* text
= NULL
;
373 if (translation
!= NULL
) {
379 if (IsUIGroup(group
)) {
380 AddUIGroup(text
, group
->GetStatement());
386 void EndGroup(GroupStatement
* group
)
388 if (!IsUIGroup(group
)) {
394 PPDConfigView::PPDConfigView(BRect bounds
, const char *name
, uint32 resizeMask
, uint32 flags
)
395 : BView(bounds
, name
, resizeMask
, flags
)
398 // add category outline list view
399 bounds
.OffsetTo(0, 0);
400 BRect
listBounds(bounds
.left
+ kLeftMargin
, bounds
.top
+ kTopMargin
,
401 bounds
.right
- kHorizontalSpace
, bounds
.bottom
- kBottomMargin
);
402 listBounds
.right
-= B_V_SCROLL_BAR_WIDTH
;
403 listBounds
.bottom
-= B_H_SCROLL_BAR_HEIGHT
;
405 BStringView
* label
= new BStringView(listBounds
, "printer-settings", "Printer Settings:");
407 label
->ResizeToPreferred();
409 listBounds
.top
+= label
->Bounds().bottom
+ 5;
412 fDetails
= new BView(listBounds
, "details", B_FOLLOW_ALL_SIDES
, B_WILL_DRAW
);
413 fDetails
->SetViewUIColor(B_PANEL_BACKGROUND_COLOR
);
415 BScrollView
* scrollView
= new BScrollView("details-scroll-view",
416 fDetails
, B_FOLLOW_ALL_SIDES
, 0, true, true);
418 AddChild(scrollView
);
421 void SetScrollBar(BScrollBar
* scroller
, float contents
, float client
)
423 if (scroller
!= NULL
) {
424 float extent
= contents
- client
;
426 scroller
->SetRange(0, extent
);
427 scroller
->SetProportion(1-extent
/ contents
);
428 scroller
->SetSteps(20, client
);
430 scroller
->SetRange(0, 0);
435 void PPDConfigView::FillCategories()
437 if (fPPD
== NULL
) return;
439 PPDBuilder
builder(this, fDetails
, fSettings
);
441 BScrollBar
* scroller
= fDetails
->ScrollBar(B_VERTICAL
);
442 SetScrollBar(scroller
, builder
.GetBounds().Height(), fDetails
->Bounds().Height());
443 scroller
= fDetails
->ScrollBar(B_HORIZONTAL
);
444 SetScrollBar(scroller
, builder
.GetBounds().Width(), fDetails
->Bounds().Width());
447 void PPDConfigView::FillDetails(Statement
* statement
)
449 RemoveChildren(fDetails
);
451 if (statement
== NULL
) {
455 StatementList
* children
= statement
->GetChildren();
456 if (children
== NULL
) {
460 BRect
bounds(fDetails
->Bounds());
461 bounds
.OffsetTo(kLeftMargin
, kTopMargin
);
462 DetailsBuilder
builder(this, fDetails
, bounds
, statement
, fSettings
);
463 builder
.Visit(children
);
466 void PPDConfigView::BooleanChanged(BMessage
* msg
)
468 const char* keyword
= msg
->FindString("keyword");
471 if (msg
->FindInt32("be:value", &value
) == B_OK
) {
478 fSettings
.ReplaceString(keyword
, option
);
482 void PPDConfigView::StringChanged(BMessage
* msg
)
484 const char* keyword
= msg
->FindString("keyword");
485 const char* option
= msg
->FindString("option");
487 if (keyword
!= NULL
&& keyword
!= NULL
) {
488 fSettings
.ReplaceString(keyword
, option
);
492 void PPDConfigView::MessageReceived(BMessage
* msg
)
495 case kMsgBooleanChanged
: BooleanChanged(msg
);
497 case kMsgStringChanged
: StringChanged(msg
);
501 BView::MessageReceived(msg
);
504 void PPDConfigView::SetupSettings(const BMessage
& currentSettings
)
506 DefaultValueExtractor extractor
;
507 extractor
.Visit(fPPD
);
509 const BMessage
&defaultValues(extractor
.GetDefaultValues());
510 fSettings
.MakeEmpty();
514 for (int32 index
= 0; defaultValues
.GetInfo(B_STRING_TYPE
, index
, &name
, &code
) == B_OK
; index
++) {
515 const char* value
= currentSettings
.FindString(name
);
517 value
= defaultValues
.FindString(name
);
520 fSettings
.AddString(name
, value
);
525 void PPDConfigView::Set(const char* file
, const BMessage
& currentSettings
)
529 PPDParser
parser(file
);
530 fPPD
= parser
.ParseAll();
532 fprintf(stderr
, "Parsing error (%s): %s\n", file
, parser
.GetErrorMessage());
535 SetupSettings(currentSettings
);