1 /* 2 * Copyright 2003-2009, Axel Dörfler, axeld@pinc-software.de. 3 * Copyright 2019, Haiku, Inc. All rights reserved. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "DefaultMediaTheme.h" 9 10 #include <Box.h> 11 #include <Button.h> 12 #include <ChannelSlider.h> 13 #include <CheckBox.h> 14 #include <GroupView.h> 15 #include <MediaRoster.h> 16 #include <MenuField.h> 17 #include <MessageFilter.h> 18 #include <OptionPopUp.h> 19 #include <ParameterWeb.h> 20 #include <ScrollBar.h> 21 #include <ScrollView.h> 22 #include <Slider.h> 23 #include <SpaceLayoutItem.h> 24 #include <StringView.h> 25 #include <TabView.h> 26 #include <TextControl.h> 27 #include <Window.h> 28 29 #include "MediaDebug.h" 30 31 32 using namespace BPrivate; 33 34 35 namespace BPrivate { 36 37 class SeparatorView : public BView { 38 public: 39 SeparatorView(orientation orientation); 40 virtual ~SeparatorView(); 41 42 virtual void Draw(BRect updateRect); 43 44 private: 45 bool fVertical; 46 }; 47 48 class TitleView : public BView { 49 public: 50 TitleView(const char *title); 51 virtual ~TitleView(); 52 53 virtual void Draw(BRect updateRect); 54 virtual void GetPreferredSize(float *width, float *height); 55 56 private: 57 BString fTitle; 58 }; 59 60 class CheckBox : public BCheckBox { 61 public: 62 CheckBox(const char* name, const char* label, 63 BDiscreteParameter ¶meter); 64 virtual ~CheckBox(); 65 66 virtual void AttachedToWindow(); 67 virtual void DetachedFromWindow(); 68 private: 69 BDiscreteParameter &fParameter; 70 }; 71 72 class OptionPopUp : public BOptionPopUp { 73 public: 74 OptionPopUp(const char* name, const char* label, 75 BDiscreteParameter ¶meter); 76 virtual ~OptionPopUp(); 77 78 virtual void AttachedToWindow(); 79 virtual void DetachedFromWindow(); 80 private: 81 BDiscreteParameter &fParameter; 82 }; 83 84 class Slider : public BSlider { 85 public: 86 Slider(const char* name, const char*label, int32 minValue, 87 int32 maxValue, BContinuousParameter ¶meter); 88 virtual ~Slider(); 89 90 virtual void AttachedToWindow(); 91 virtual void DetachedFromWindow(); 92 private: 93 BContinuousParameter &fParameter; 94 }; 95 96 class ChannelSlider : public BChannelSlider { 97 public: 98 ChannelSlider(const char* name, const char* label, 99 orientation orientation, int32 channels, 100 BContinuousParameter ¶meter); 101 virtual ~ChannelSlider(); 102 103 virtual void AttachedToWindow(); 104 virtual void DetachedFromWindow(); 105 private: 106 BContinuousParameter &fParameter; 107 }; 108 109 class MessageFilter : public BMessageFilter { 110 public: 111 static MessageFilter *FilterFor(BView *view, BParameter ¶meter); 112 113 protected: 114 MessageFilter(); 115 }; 116 117 class ContinuousMessageFilter : public MessageFilter { 118 public: 119 ContinuousMessageFilter(BControl *control, 120 BContinuousParameter ¶meter); 121 virtual ~ContinuousMessageFilter(); 122 123 virtual filter_result Filter(BMessage *message, BHandler **target); 124 125 private: 126 void _UpdateControl(); 127 128 BControl *fControl; 129 BContinuousParameter &fParameter; 130 }; 131 132 class DiscreteMessageFilter : public MessageFilter { 133 public: 134 DiscreteMessageFilter(BControl *control, BDiscreteParameter ¶meter); 135 virtual ~DiscreteMessageFilter(); 136 137 virtual filter_result Filter(BMessage *message, BHandler **target); 138 139 private: 140 BDiscreteParameter &fParameter; 141 }; 142 143 } // namespace BPrivate 144 145 146 const uint32 kMsgParameterChanged = '_mPC'; 147 148 149 static bool 150 parameter_should_be_hidden(BParameter ¶meter) 151 { 152 // ToDo: note, this is probably completely stupid, but it's the only 153 // way I could safely remove the null parameters that are not shown 154 // by the R5 media theme 155 if (parameter.Type() != BParameter::B_NULL_PARAMETER 156 || strcmp(parameter.Kind(), B_WEB_PHYSICAL_INPUT)) 157 return false; 158 159 for (int32 i = 0; i < parameter.CountOutputs(); i++) { 160 if (!strcmp(parameter.OutputAt(0)->Kind(), B_INPUT_MUX)) 161 return true; 162 } 163 164 return false; 165 } 166 167 168 static void 169 start_watching_for_parameter_changes(BControl* control, BParameter ¶meter) 170 { 171 BMediaRoster* roster = BMediaRoster::CurrentRoster(); 172 if (roster == NULL) 173 return; 174 175 if (roster->StartWatching(control, parameter.Web()->Node(), 176 B_MEDIA_NEW_PARAMETER_VALUE) != B_OK) { 177 fprintf(stderr, "DefaultMediaTheme: Failed to start watching parameter" 178 "\"%s\"\n", parameter.Name()); 179 return; 180 } 181 } 182 183 184 static void 185 stop_watching_for_parameter_changes(BControl* control, BParameter ¶meter) 186 { 187 BMediaRoster* roster = BMediaRoster::CurrentRoster(); 188 if (roster == NULL) 189 return; 190 191 roster->StopWatching(control, parameter.Web()->Node(), 192 B_MEDIA_NEW_PARAMETER_VALUE); 193 } 194 195 196 // #pragma mark - 197 198 199 SeparatorView::SeparatorView(orientation orientation) 200 : BView("-", B_WILL_DRAW), 201 fVertical(orientation == B_VERTICAL) 202 { 203 if (fVertical) { 204 SetExplicitMinSize(BSize(5, 0)); 205 SetExplicitMaxSize(BSize(5, MaxSize().height)); 206 } else { 207 SetExplicitMinSize(BSize(0, 5)); 208 SetExplicitMaxSize(BSize(MaxSize().width, 5)); 209 } 210 } 211 212 213 SeparatorView::~SeparatorView() 214 { 215 } 216 217 218 void 219 SeparatorView::Draw(BRect updateRect) 220 { 221 rgb_color color = ui_color(B_PANEL_BACKGROUND_COLOR); 222 BRect rect = updateRect & Bounds(); 223 224 SetHighColor(tint_color(color, B_DARKEN_1_TINT)); 225 if (fVertical) 226 StrokeLine(BPoint(0, rect.top), BPoint(0, rect.bottom)); 227 else 228 StrokeLine(BPoint(rect.left, 0), BPoint(rect.right, 0)); 229 230 SetHighColor(tint_color(color, B_LIGHTEN_1_TINT)); 231 if (fVertical) 232 StrokeLine(BPoint(1, rect.top), BPoint(1, rect.bottom)); 233 else 234 StrokeLine(BPoint(rect.left, 1), BPoint(rect.right, 1)); 235 } 236 237 238 // #pragma mark - 239 240 241 TitleView::TitleView(const char *title) 242 : BView(title, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE), 243 fTitle(title) 244 { 245 AdoptSystemColors(); 246 } 247 248 249 TitleView::~TitleView() 250 { 251 } 252 253 254 void 255 TitleView::Draw(BRect updateRect) 256 { 257 BRect rect(Bounds()); 258 rect.left = (rect.Width() - StringWidth(fTitle)) / 2; 259 260 SetDrawingMode(B_OP_COPY); 261 SetHighColor(tint_color(ViewColor(), B_LIGHTEN_2_TINT)); 262 DrawString(fTitle, BPoint(rect.left + 1, rect.bottom - 8)); 263 264 SetDrawingMode(B_OP_OVER); 265 SetHighColor(80, 20, 20); 266 DrawString(fTitle, BPoint(rect.left, rect.bottom - 9)); 267 } 268 269 270 void 271 TitleView::GetPreferredSize(float *_width, float *_height) 272 { 273 if (_width) 274 *_width = StringWidth(fTitle) + 2; 275 276 if (_height) { 277 font_height fontHeight; 278 GetFontHeight(&fontHeight); 279 280 *_height = fontHeight.ascent + fontHeight.descent + fontHeight.leading 281 + 8; 282 } 283 } 284 285 286 // #pragma mark - 287 288 289 CheckBox::CheckBox(const char* name, const char* label, 290 BDiscreteParameter ¶meter) 291 : BCheckBox(name, label, NULL), 292 fParameter(parameter) 293 { 294 } 295 296 297 CheckBox::~CheckBox() 298 { 299 } 300 301 302 void 303 CheckBox::AttachedToWindow() 304 { 305 BCheckBox::AttachedToWindow(); 306 307 SetTarget(this); 308 start_watching_for_parameter_changes(this, fParameter); 309 } 310 311 312 void 313 CheckBox::DetachedFromWindow() 314 { 315 stop_watching_for_parameter_changes(this, fParameter); 316 } 317 318 319 OptionPopUp::OptionPopUp(const char* name, const char* label, 320 BDiscreteParameter ¶meter) 321 : BOptionPopUp(name, label, NULL), 322 fParameter(parameter) 323 { 324 } 325 326 327 OptionPopUp::~OptionPopUp() 328 { 329 } 330 331 332 void 333 OptionPopUp::AttachedToWindow() 334 { 335 BOptionPopUp::AttachedToWindow(); 336 337 SetTarget(this); 338 start_watching_for_parameter_changes(this, fParameter); 339 } 340 341 342 void 343 OptionPopUp::DetachedFromWindow() 344 { 345 stop_watching_for_parameter_changes(this, fParameter); 346 } 347 348 349 Slider::Slider(const char* name, const char* label, int32 minValue, 350 int32 maxValue, BContinuousParameter ¶meter) 351 : BSlider(name, label, NULL, minValue, maxValue, B_HORIZONTAL), 352 fParameter(parameter) 353 { 354 } 355 356 357 Slider::~Slider() 358 { 359 } 360 361 362 void 363 Slider::AttachedToWindow() 364 { 365 BSlider::AttachedToWindow(); 366 367 SetTarget(this); 368 start_watching_for_parameter_changes(this, fParameter); 369 } 370 371 372 void 373 Slider::DetachedFromWindow() 374 { 375 stop_watching_for_parameter_changes(this, fParameter); 376 } 377 378 379 ChannelSlider::ChannelSlider(const char* name, const char* label, 380 orientation orientation, int32 channels, BContinuousParameter ¶meter) 381 : BChannelSlider(name, label, NULL, orientation, channels), 382 fParameter(parameter) 383 { 384 } 385 386 387 ChannelSlider::~ChannelSlider() 388 { 389 } 390 391 392 void 393 ChannelSlider::AttachedToWindow() 394 { 395 BChannelSlider::AttachedToWindow(); 396 397 SetTarget(this); 398 start_watching_for_parameter_changes(this, fParameter); 399 } 400 401 402 void 403 ChannelSlider::DetachedFromWindow() 404 { 405 stop_watching_for_parameter_changes(this, fParameter); 406 407 BChannelSlider::DetachedFromWindow(); 408 } 409 410 411 // #pragma mark - 412 413 414 MessageFilter::MessageFilter() 415 : BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE) 416 { 417 } 418 419 420 MessageFilter * 421 MessageFilter::FilterFor(BView *view, BParameter ¶meter) 422 { 423 BControl *control = dynamic_cast<BControl *>(view); 424 if (control == NULL) 425 return NULL; 426 427 switch (parameter.Type()) { 428 case BParameter::B_CONTINUOUS_PARAMETER: 429 return new ContinuousMessageFilter(control, 430 static_cast<BContinuousParameter &>(parameter)); 431 432 case BParameter::B_DISCRETE_PARAMETER: 433 return new DiscreteMessageFilter(control, 434 static_cast<BDiscreteParameter &>(parameter)); 435 436 case BParameter::B_NULL_PARAMETER: /* fall through */ 437 default: 438 return NULL; 439 } 440 } 441 442 443 // #pragma mark - 444 445 446 ContinuousMessageFilter::ContinuousMessageFilter(BControl *control, 447 BContinuousParameter ¶meter) 448 : MessageFilter(), 449 fControl(control), 450 fParameter(parameter) 451 { 452 // initialize view for us 453 control->SetMessage(new BMessage(kMsgParameterChanged)); 454 455 if (BSlider *slider = dynamic_cast<BSlider *>(fControl)) 456 slider->SetModificationMessage(new BMessage(kMsgParameterChanged)); 457 else if (BChannelSlider *slider = dynamic_cast<BChannelSlider *>(fControl)) 458 slider->SetModificationMessage(new BMessage(kMsgParameterChanged)); 459 else 460 ERROR("ContinuousMessageFilter: unknown continuous parameter view\n"); 461 462 // set initial value 463 _UpdateControl(); 464 } 465 466 467 ContinuousMessageFilter::~ContinuousMessageFilter() 468 { 469 } 470 471 472 filter_result 473 ContinuousMessageFilter::Filter(BMessage *message, BHandler **target) 474 { 475 if (*target != fControl) 476 return B_DISPATCH_MESSAGE; 477 478 if (message->what == kMsgParameterChanged) { 479 // update parameter from control 480 // TODO: support for response! 481 482 float value[fParameter.CountChannels()]; 483 484 if (BSlider *slider = dynamic_cast<BSlider *>(fControl)) { 485 value[0] = (float)(slider->Value() / 1000.0); 486 } else if (BChannelSlider *slider 487 = dynamic_cast<BChannelSlider *>(fControl)) { 488 for (int32 i = 0; i < fParameter.CountChannels(); i++) 489 value[i] = (float)(slider->ValueFor(i) / 1000.0); 490 } 491 492 TRACE("ContinuousMessageFilter::Filter: update view %s, %" B_PRId32 493 " channels\n", fControl->Name(), fParameter.CountChannels()); 494 495 if (fParameter.SetValue((void *)value, sizeof(value), 496 -1) < B_OK) { 497 ERROR("ContinuousMessageFilter::Filter: Could not set parameter " 498 "value for %p\n", &fParameter); 499 return B_DISPATCH_MESSAGE; 500 } 501 return B_SKIP_MESSAGE; 502 } 503 if (message->what == B_MEDIA_NEW_PARAMETER_VALUE) { 504 // update view from parameter -- if the message concerns us 505 const media_node* node; 506 int32 parameterID; 507 ssize_t size; 508 if (message->FindInt32("parameter", ¶meterID) != B_OK 509 || fParameter.ID() != parameterID 510 || message->FindData("node", B_RAW_TYPE, (const void**)&node, 511 &size) != B_OK 512 || fParameter.Web()->Node() != *node) 513 return B_DISPATCH_MESSAGE; 514 515 _UpdateControl(); 516 return B_SKIP_MESSAGE; 517 } 518 519 return B_DISPATCH_MESSAGE; 520 } 521 522 523 void 524 ContinuousMessageFilter::_UpdateControl() 525 { 526 // TODO: response support! 527 528 float value[fParameter.CountChannels()]; 529 size_t size = sizeof(value); 530 if (fParameter.GetValue((void *)&value, &size, NULL) < B_OK) { 531 ERROR("ContinuousMessageFilter: Could not get value for continuous " 532 "parameter %p (name '%s', node %d)\n", &fParameter, 533 fParameter.Name(), (int)fParameter.Web()->Node().node); 534 return; 535 } 536 537 if (BSlider *slider = dynamic_cast<BSlider *>(fControl)) { 538 slider->SetValue((int32) (1000 * value[0])); 539 slider->SetModificationMessage(new BMessage(kMsgParameterChanged)); 540 } else if (BChannelSlider *slider 541 = dynamic_cast<BChannelSlider *>(fControl)) { 542 for (int32 i = 0; i < fParameter.CountChannels(); i++) { 543 slider->SetValueFor(i, (int32) (1000 * value[i])); 544 } 545 } 546 } 547 548 549 // #pragma mark - 550 551 552 DiscreteMessageFilter::DiscreteMessageFilter(BControl *control, 553 BDiscreteParameter ¶meter) 554 : MessageFilter(), 555 fParameter(parameter) 556 { 557 // initialize view for us 558 control->SetMessage(new BMessage(kMsgParameterChanged)); 559 560 // set initial value 561 size_t size = sizeof(int32); 562 int32 value; 563 if (parameter.GetValue((void *)&value, &size, NULL) < B_OK) { 564 ERROR("DiscreteMessageFilter: Could not get value for discrete " 565 "parameter %p (name '%s', node %d)\n", ¶meter, 566 parameter.Name(), (int)(parameter.Web()->Node().node)); 567 return; 568 } 569 570 if (BCheckBox *checkBox = dynamic_cast<BCheckBox *>(control)) { 571 checkBox->SetValue(value); 572 } else if (BOptionPopUp *popUp = dynamic_cast<BOptionPopUp *>(control)) { 573 popUp->SelectOptionFor(value); 574 } else 575 ERROR("DiscreteMessageFilter: unknown discrete parameter view\n"); 576 } 577 578 579 DiscreteMessageFilter::~DiscreteMessageFilter() 580 { 581 } 582 583 584 filter_result 585 DiscreteMessageFilter::Filter(BMessage *message, BHandler **target) 586 { 587 BControl *control; 588 589 if ((control = dynamic_cast<BControl *>(*target)) == NULL) 590 return B_DISPATCH_MESSAGE; 591 592 if (message->what == B_MEDIA_NEW_PARAMETER_VALUE) { 593 TRACE("DiscreteMessageFilter::Filter: Got a new parameter value\n"); 594 const media_node* node; 595 int32 parameterID; 596 ssize_t size; 597 if (message->FindInt32("parameter", ¶meterID) != B_OK 598 || fParameter.ID() != parameterID 599 || message->FindData("node", B_RAW_TYPE, (const void**)&node, 600 &size) != B_OK 601 || fParameter.Web()->Node() != *node) 602 return B_DISPATCH_MESSAGE; 603 604 int32 value = 0; 605 size_t valueSize = sizeof(int32); 606 if (fParameter.GetValue((void*)&value, &valueSize, NULL) < B_OK) { 607 ERROR("DiscreteMessageFilter: Could not get value for continuous " 608 "parameter %p (name '%s', node %d)\n", &fParameter, 609 fParameter.Name(), (int)fParameter.Web()->Node().node); 610 return B_SKIP_MESSAGE; 611 } 612 if (BCheckBox* checkBox = dynamic_cast<BCheckBox*>(control)) { 613 checkBox->SetValue(value); 614 } else if (BOptionPopUp* popUp = dynamic_cast<BOptionPopUp*>(control)) { 615 popUp->SetValue(value); 616 } 617 618 return B_SKIP_MESSAGE; 619 } 620 621 if (message->what != kMsgParameterChanged) 622 return B_DISPATCH_MESSAGE; 623 624 // update view 625 626 int32 value = 0; 627 628 if (BCheckBox *checkBox = dynamic_cast<BCheckBox *>(control)) { 629 value = checkBox->Value(); 630 } else if (BOptionPopUp *popUp = dynamic_cast<BOptionPopUp *>(control)) { 631 popUp->SelectedOption(NULL, &value); 632 } 633 634 TRACE("DiscreteMessageFilter::Filter: update view %s, value = %" 635 B_PRId32 "\n", control->Name(), value); 636 637 if (fParameter.SetValue((void *)&value, sizeof(value), -1) < B_OK) { 638 ERROR("DiscreteMessageFilter::Filter: Could not set parameter value for %p\n", &fParameter); 639 return B_DISPATCH_MESSAGE; 640 } 641 642 return B_SKIP_MESSAGE; 643 } 644 645 646 // #pragma mark - 647 648 649 DefaultMediaTheme::DefaultMediaTheme() 650 : BMediaTheme("Haiku theme", "Haiku built-in theme version 0.1") 651 { 652 CALLED(); 653 } 654 655 656 BControl * 657 DefaultMediaTheme::MakeControlFor(BParameter *parameter) 658 { 659 CALLED(); 660 661 return MakeViewFor(parameter); 662 } 663 664 665 BView * 666 DefaultMediaTheme::MakeViewFor(BParameterWeb *web, const BRect *hintRect) 667 { 668 CALLED(); 669 670 if (web == NULL) 671 return NULL; 672 673 // do we have more than one attached parameter group? 674 // if so, use a tabbed view with a tab for each group 675 676 BTabView *tabView = NULL; 677 if (web->CountGroups() > 1) 678 tabView = new BTabView("web"); 679 680 for (int32 i = 0; i < web->CountGroups(); i++) { 681 BParameterGroup *group = web->GroupAt(i); 682 if (group == NULL) 683 continue; 684 685 BView *groupView = MakeViewFor(*group); 686 if (groupView == NULL) 687 continue; 688 689 BScrollView *scrollView = new BScrollView(groupView->Name(), groupView, 0, 690 true, true, B_NO_BORDER); 691 scrollView->SetExplicitMinSize(BSize(B_V_SCROLL_BAR_WIDTH, 692 B_H_SCROLL_BAR_HEIGHT)); 693 if (tabView == NULL) { 694 if (hintRect != NULL) { 695 scrollView->MoveTo(hintRect->LeftTop()); 696 scrollView->ResizeTo(hintRect->Size()); 697 } else { 698 scrollView->ResizeTo(600, 400); 699 // See comment below. 700 } 701 return scrollView; 702 } 703 tabView->AddTab(scrollView); 704 } 705 706 if (hintRect != NULL) { 707 tabView->MoveTo(hintRect->LeftTop()); 708 tabView->ResizeTo(hintRect->Size()); 709 } else { 710 // Apps not using layouted views may expect PreferredSize() to return 711 // a sane value right away, and use this to set the maximum size of 712 // things. Layouted views return their current size until the view has 713 // been attached to the window, so in order to prevent breakage, we set 714 // a default view size here. 715 tabView->ResizeTo(600, 400); 716 } 717 return tabView; 718 } 719 720 721 BView * 722 DefaultMediaTheme::MakeViewFor(BParameterGroup& group) 723 { 724 CALLED(); 725 726 if (group.Flags() & B_HIDDEN_PARAMETER) 727 return NULL; 728 729 BGroupView *view = new BGroupView(group.Name(), B_HORIZONTAL, 730 B_USE_HALF_ITEM_SPACING); 731 BGroupLayout *layout = view->GroupLayout(); 732 layout->SetInsets(B_USE_HALF_ITEM_INSETS); 733 734 // Create and add the parameter views 735 if (group.CountParameters() > 0) { 736 BGroupView *paramView = new BGroupView(group.Name(), B_VERTICAL, 737 B_USE_HALF_ITEM_SPACING); 738 BGroupLayout *paramLayout = paramView->GroupLayout(); 739 paramLayout->SetInsets(0); 740 741 for (int32 i = 0; i < group.CountParameters(); i++) { 742 BParameter *parameter = group.ParameterAt(i); 743 if (parameter == NULL) 744 continue; 745 746 BView *parameterView = MakeSelfHostingViewFor(*parameter); 747 if (parameterView == NULL) 748 continue; 749 750 paramLayout->AddView(parameterView); 751 } 752 paramLayout->AddItem(BSpaceLayoutItem::CreateHorizontalStrut(10)); 753 layout->AddView(paramView); 754 } 755 756 // Add the sub-group views 757 for (int32 i = 0; i < group.CountGroups(); i++) { 758 BParameterGroup *subGroup = group.GroupAt(i); 759 if (subGroup == NULL) 760 continue; 761 762 BView *groupView = MakeViewFor(*subGroup); 763 if (groupView == NULL) 764 continue; 765 766 if (i > 0) 767 layout->AddView(new SeparatorView(B_VERTICAL)); 768 769 layout->AddView(groupView); 770 } 771 772 layout->AddItem(BSpaceLayoutItem::CreateGlue()); 773 return view; 774 } 775 776 777 /*! This creates a view that handles all incoming messages itself - that's 778 what is meant with self-hosting. 779 */ 780 BView * 781 DefaultMediaTheme::MakeSelfHostingViewFor(BParameter& parameter) 782 { 783 if (parameter.Flags() & B_HIDDEN_PARAMETER 784 || parameter_should_be_hidden(parameter)) 785 return NULL; 786 787 BView *view = MakeViewFor(¶meter); 788 if (view == NULL) { 789 // The MakeViewFor() method above returns a BControl - which we 790 // don't need for a null parameter; that's why it returns NULL. 791 // But we want to see something anyway, so we add a string view 792 // here. 793 if (parameter.Type() == BParameter::B_NULL_PARAMETER) { 794 if (parameter.Group()->ParameterAt(0) == ¶meter) { 795 // this is the first parameter in this group, so 796 // let's use a nice title view 797 return new TitleView(parameter.Name()); 798 } 799 BStringView *stringView = new BStringView(parameter.Name(), 800 parameter.Name()); 801 stringView->SetAlignment(B_ALIGN_CENTER); 802 803 return stringView; 804 } 805 806 return NULL; 807 } 808 809 MessageFilter *filter = MessageFilter::FilterFor(view, parameter); 810 if (filter != NULL) 811 view->AddFilter(filter); 812 813 return view; 814 } 815 816 817 BControl * 818 DefaultMediaTheme::MakeViewFor(BParameter *parameter) 819 { 820 switch (parameter->Type()) { 821 case BParameter::B_NULL_PARAMETER: 822 // there is no default view for a null parameter 823 return NULL; 824 825 case BParameter::B_DISCRETE_PARAMETER: 826 { 827 BDiscreteParameter &discrete 828 = static_cast<BDiscreteParameter &>(*parameter); 829 830 if (!strcmp(discrete.Kind(), B_ENABLE) 831 || !strcmp(discrete.Kind(), B_MUTE) 832 || discrete.CountItems() == 0) { 833 return new CheckBox(discrete.Name(), discrete.Name(), discrete); 834 } else { 835 BOptionPopUp *popUp = new OptionPopUp(discrete.Name(), 836 discrete.Name(), discrete); 837 838 for (int32 i = 0; i < discrete.CountItems(); i++) { 839 popUp->AddOption(discrete.ItemNameAt(i), 840 discrete.ItemValueAt(i)); 841 } 842 843 return popUp; 844 } 845 } 846 847 case BParameter::B_CONTINUOUS_PARAMETER: 848 { 849 BContinuousParameter &continuous 850 = static_cast<BContinuousParameter &>(*parameter); 851 852 if (!strcmp(continuous.Kind(), B_MASTER_GAIN) 853 || !strcmp(continuous.Kind(), B_GAIN)) { 854 BChannelSlider *slider = new ChannelSlider( 855 continuous.Name(), continuous.Name(), B_VERTICAL, 856 continuous.CountChannels(), continuous); 857 858 BString minLabel, maxLabel; 859 const char *unit = continuous.Unit(); 860 if (unit[0]) { 861 // if we have a unit, print it next to the limit values 862 minLabel.SetToFormat("%g %s", continuous.MinValue(), continuous.Unit()); 863 maxLabel.SetToFormat("%g %s", continuous.MaxValue(), continuous.Unit()); 864 } else { 865 minLabel.SetToFormat("%g", continuous.MinValue()); 866 maxLabel.SetToFormat("%g", continuous.MaxValue()); 867 } 868 slider->SetLimitLabels(minLabel, maxLabel); 869 870 // ToDo: take BContinuousParameter::GetResponse() & ValueStep() into account! 871 872 for (int32 i = 0; i < continuous.CountChannels(); i++) { 873 slider->SetLimitsFor(i, int32(continuous.MinValue() * 1000), 874 int32(continuous.MaxValue() * 1000)); 875 } 876 877 return slider; 878 } 879 880 BSlider *slider = new Slider(parameter->Name(), 881 parameter->Name(), 0, 100, continuous); 882 883 return slider; 884 } 885 886 default: 887 ERROR("BMediaTheme: Don't know parameter type: 0x%x\n", 888 parameter->Type()); 889 } 890 return NULL; 891 } 892 893