From b8da958ed6dbd7c37538d595bb12941cbcbdb43c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 2 Jul 2003 02:06:21 +0000 Subject: [PATCH] Big visual update: it's now almost the same as the original MediaTheme. Some special parameter types are still missing, actually changing anything is missing, some needed work-arounds for broken Be code, etc. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3798 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kits/media/DefaultMediaTheme.cpp | 334 +++++++++++++++++++++++---- 1 file changed, 292 insertions(+), 42 deletions(-) diff --git a/src/kits/media/DefaultMediaTheme.cpp b/src/kits/media/DefaultMediaTheme.cpp index d11c16b047..bb8e3605fe 100644 --- a/src/kits/media/DefaultMediaTheme.cpp +++ b/src/kits/media/DefaultMediaTheme.cpp @@ -14,13 +14,130 @@ #include #include #include +#include #include #include +#include +#include using namespace BPrivate; +namespace BPrivate { + +class SeparatorView : public BView { + public: + SeparatorView(BRect frame); + virtual ~SeparatorView(); + + virtual void Draw(BRect updateRect); + + private: + bool fVertical; +}; + +class TitleView : public BView { + public: + TitleView(BRect frame, const char *title); + virtual ~TitleView(); + + virtual void Draw(BRect updateRect); + virtual void GetPreferredSize(float *width, float *height); + + private: + const char *fTitle; +}; + +} // namespace BPrivate + + +SeparatorView::SeparatorView(BRect frame) + : BView(frame, "-", B_FOLLOW_NONE, B_WILL_DRAW) +{ + fVertical = frame.Width() < frame.Height(); +} + + +SeparatorView::~SeparatorView() +{ +} + + +void +SeparatorView::Draw(BRect updateRect) +{ + rgb_color color = ui_color(B_PANEL_BACKGROUND_COLOR); + BRect rect = updateRect & Bounds(); + + SetHighColor(tint_color(color, B_DARKEN_1_TINT)); + if (fVertical) + StrokeLine(BPoint(0, rect.top), BPoint(0, rect.bottom)); + else + StrokeLine(BPoint(rect.left, 0), BPoint(rect.right, 0)); + + SetHighColor(tint_color(color, B_LIGHTEN_1_TINT)); + if (fVertical) + StrokeLine(BPoint(1, rect.top), BPoint(1, rect.bottom)); + else + StrokeLine(BPoint(rect.left, 1), BPoint(rect.right, 1)); +} + + +// #pragma mark - + + +TitleView::TitleView(BRect frame, const char *title) + : BView(frame, title, B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW) +{ + fTitle = strdup(title); + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + SetLowColor(ViewColor()); +} + + +TitleView::~TitleView() +{ + free((char *)fTitle); +} + + +void +TitleView::Draw(BRect updateRect) +{ + BRect rect(Bounds()); + + SetDrawingMode(B_OP_COPY); + SetHighColor(240, 240, 240); + DrawString(fTitle, BPoint(rect.left + 1, rect.bottom - 9)); + + SetDrawingMode(B_OP_OVER); + SetHighColor(80, 20, 20); + DrawString(fTitle, BPoint(rect.left, rect.bottom - 8)); + + //SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT)); + //StrokeLine(BPoint(rect.left, rect.bottom), BPoint(rect.right, rect.bottom)); +} + + +void +TitleView::GetPreferredSize(float *_width, float *_height) +{ + if (_width) + *_width = StringWidth(fTitle) + 2; + + if (_height) { + font_height fontHeight; + GetFontHeight(&fontHeight); + + *_height = fontHeight.ascent + fontHeight.descent + fontHeight.leading + 8; + } +} + + +// #pragma mark - + + DefaultMediaTheme::DefaultMediaTheme() : BMediaTheme("BeOS Theme", "BeOS built-in theme version 0.1") { @@ -50,10 +167,15 @@ DefaultMediaTheme::MakeViewFor(BParameterWeb *web, const BRect *hintRect) if (hintRect) rect = *hintRect; else - rect.Set(0, 0, 150, 100); + rect.Set(0, 0, 80, 100); - BView *view = new BView(rect, "web", B_FOLLOW_ALL, B_WILL_DRAW); - view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + // do we have more than one attached parameter group? + // if so, use a tabbed view with a tab for each group + + BTabView *tabView = NULL; + + if (web->CountGroups() > 1) + tabView = new BTabView(rect, "web"); rect.OffsetTo(B_ORIGIN); @@ -62,51 +184,67 @@ DefaultMediaTheme::MakeViewFor(BParameterWeb *web, const BRect *hintRect) if (group == NULL) continue; - BView *groupView = MakeViewFor(group, &rect); + BView *groupView = MakeViewFor(*group, rect); if (groupView == NULL) continue; - view->AddChild(groupView); + if (tabView == NULL) { + // if we don't need a container to put that view into, + // we're done here + return groupView; + } - rect.OffsetBy(0, groupView->Bounds().Height() + 5); + tabView->AddTab(groupView); if (groupView->Bounds().Width() + 5 > rect.Width()) rect.right = groupView->Bounds().Width() - 1; } - view->ResizeTo(rect.right + 10, rect.top + 5); + if (tabView != NULL) { + tabView->ResizeTo(rect.right + 10, rect.bottom + tabView->TabHeight()); - return view; + rect = tabView->Bounds(); + rect.InsetBySelf(1, 1); + tabView->ContainerView()->ResizeTo(rect.Width(), rect.Height()); + } + + return tabView; } BView * -DefaultMediaTheme::MakeViewFor(BParameterGroup *group, const BRect *hintRect) +DefaultMediaTheme::MakeViewFor(BParameterGroup &group, const BRect &hintRect) { CALLED(); - BRect rect(*hintRect); - rect.InsetBySelf(5, 5); - - BBox *view = new BBox(rect, group->Name()); - view->SetLabel(group->Name()); + BRect rect(hintRect); + BBox *view = new BBox(rect, group.Name()); + view->SetBorder(B_NO_BORDER); // Add the sub-group views rect.OffsetTo(B_ORIGIN); rect.InsetBySelf(5, 5); - rect.top += 10; // ToDo: font height - rect.right = rect.left + 100; + rect.right = rect.left + 50; - for (int32 i = 0; i < group->CountGroups(); i++) { - BParameterGroup *subGroup = group->GroupAt(i); + for (int32 i = 0; i < group.CountGroups(); i++) { + BParameterGroup *subGroup = group.GroupAt(i); if (subGroup == NULL) continue; - BView *groupView = MakeViewFor(subGroup, &rect); + BView *groupView = MakeViewFor(*subGroup, rect); if (groupView == NULL) continue; + if (i > 0) { + // add separator view + BRect separatorRect(rect); + separatorRect.left -= 3; + separatorRect.right = separatorRect.left + 1; + + view->AddChild(new SeparatorView(separatorRect)); + } + view->AddChild(groupView); rect.OffsetBy(groupView->Bounds().Width() + 5, 0); @@ -115,33 +253,107 @@ DefaultMediaTheme::MakeViewFor(BParameterGroup *group, const BRect *hintRect) rect.bottom = groupView->Bounds().Height() - 1; } - view->ResizeTo(rect.left + 10, rect.bottom + 25); + view->ResizeTo(rect.left + 10, rect.bottom + 10); rect.left = 5; // add the parameter views part of the group - if (view->CountChildren() > 0) - rect.OffsetBy(0, rect.Height() + 5); + if (group.CountParameters() == 0) + return view; - for (int32 i = 0; i < group->CountParameters(); i++) { - BParameter *parameter = group->ParameterAt(i); + if (view->CountChildren() > 0) + rect.OffsetBy(0, rect.Height() + 10); + + BList views; + bool center = false; + + for (int32 i = 0; i < group.CountParameters(); i++) { + BParameter *parameter = group.ParameterAt(i); if (parameter == NULL) continue; - BControl *control = MakeViewFor(parameter, &rect); - if (control == NULL) + BView *parameterView = MakeSelfHostingViewFor(*parameter, rect); + if (parameterView == NULL) continue; - view->AddChild(control); + // if there is a BChannelSlider (ToDo: or any vertical slider?) + // the views will be centered + if (dynamic_cast(parameterView) != NULL) + center = true; - rect.OffsetBy(0, control->Bounds().Height() + 5); + parameterView->SetViewColor(view->ViewColor()); + // ToDo: dunno why this is needed, but the controls + // sometimes (!) have a white background without it - if (control->Bounds().Width() + 5 > rect.Width()) - rect.right = control->Bounds().Width() - 1; + view->AddChild(parameterView); + views.AddItem(parameterView); + + rect.OffsetBy(0, parameterView->Bounds().Height() + 5); + + if (parameterView->Bounds().Width() + 5 > rect.Width()) + rect.right = parameterView->Bounds().Width() + rect.left + 5; } - if (group->CountParameters() > 0) - view->ResizeTo(rect.right + 10, rect.top + 5); + if (group.CountParameters() > 0) + view->ResizeTo(rect.right + 5, rect.top + 5); + + // center the parameter views if needed, and tweak some views + + float width = view->Bounds().Width(); + + for (int32 i = 0; i < views.CountItems(); i++) { + BView *subView = static_cast(views.ItemAt(i)); + BRect frame = subView->Frame(); + + if (center) + subView->MoveTo((width - frame.Width()) / 2, frame.top); + else { + // tweak the PopUp views to look better + if (dynamic_cast(subView) != NULL) { + subView->ResizeTo(width, frame.Height()); + //subView->SetDivider(10); + } + } + } + + return view; +} + + +/** This creates a view that handles all incoming messages itself - that's + * what is meant with self-hosting. + */ + +BView * +DefaultMediaTheme::MakeSelfHostingViewFor(BParameter ¶meter, const BRect &hintRect) +{ + BView *view = MakeViewFor(¶meter, &hintRect); + if (view == NULL) { + // The MakeViewFor() method above returns a BControl - which we + // don't need for a null parameter; that's why it returns NULL. + // But we want to see something anyway, so we add a string view + // here. + if (parameter.Type() == BParameter::B_NULL_PARAMETER) { + if (parameter.Group()->ParameterAt(0) == ¶meter) { + // this is the first parameter in this group, so + // let's use a nice title view + + TitleView *titleView = new TitleView(hintRect, parameter.Name()); + titleView->ResizeToPreferred(); + + return titleView; + } + BStringView *stringView = new BStringView(hintRect, parameter.Name(), parameter.Name()); + stringView->SetAlignment(B_ALIGN_CENTER); + stringView->ResizeToPreferred(); + + return stringView; + } + + return NULL; + } + + // ToDo: create message filters for this view! return view; } @@ -154,7 +366,7 @@ DefaultMediaTheme::MakeViewFor(BParameter *parameter, const BRect *hintRect) if (hintRect) rect = *hintRect; else - rect.Set(0, 0, 150, 100); + rect.Set(0, 0, 50, 100); switch (parameter->Type()) { case BParameter::B_NULL_PARAMETER: @@ -165,7 +377,16 @@ DefaultMediaTheme::MakeViewFor(BParameter *parameter, const BRect *hintRect) { BDiscreteParameter &discrete = static_cast(*parameter); - if (discrete.CountItems() > 0) { + if (!strcmp(discrete.Kind(), B_ENABLE) + || !strcmp(discrete.Kind(), B_MUTE) + || discrete.CountItems() == 0) { + // create a checkbox item + + BCheckBox *checkBox = new BCheckBox(rect, discrete.Name(), discrete.Name(), NULL); + checkBox->ResizeToPreferred(); + + return checkBox; + } else { // create a pop up menu field BOptionPopUp *popUp = new BOptionPopUp(rect, discrete.Name(), discrete.Name(), NULL); @@ -177,21 +398,50 @@ DefaultMediaTheme::MakeViewFor(BParameter *parameter, const BRect *hintRect) popUp->ResizeToPreferred(); return popUp; - } else { - // create a checkbox item - - BCheckBox *checkBox = new BCheckBox(rect, discrete.Name(), discrete.Name(), NULL); - checkBox->ResizeToPreferred(); - - return checkBox; } } case BParameter::B_CONTINUOUS_PARAMETER: { + BContinuousParameter &continuous = static_cast(*parameter); + + if (!strcmp(continuous.Kind(), B_MASTER_GAIN) + || !strcmp(continuous.Kind(), B_GAIN)) + { + BChannelSlider *slider = new BChannelSlider(rect, continuous.Name(), + continuous.Name(), NULL, B_VERTICAL, continuous.CountChannels()); + + char minLabel[64], maxLabel[64]; + + const char *unit = continuous.Unit(); + if (unit[0]) { + // if we have a unit, print it next to the limit values + sprintf(minLabel, "%g %s", continuous.MinValue(), continuous.Unit()); + sprintf(maxLabel, "%g %s", continuous.MaxValue(), continuous.Unit()); + } else { + sprintf(minLabel, "%g", continuous.MinValue()); + sprintf(maxLabel, "%g", continuous.MaxValue()); + } + slider->SetLimitLabels(minLabel, maxLabel); + + float width, height; + slider->GetPreferredSize(&width, &height); + slider->ResizeTo(width, 190); + + // ToDo: take BContinuousParameter::GetResponse() & ValueStep() into account! + + for (int32 i = 0; i < continuous.CountChannels(); i++) + slider->SetLimitsFor(i, continuous.MinValue(), continuous.MaxValue()); + + return slider; + } + BSlider *slider = new BSlider(rect, parameter->Name(), parameter->Name(), NULL, 0, 100); - slider->ResizeToPreferred(); + + float width, height; + slider->GetPreferredSize(&width, &height); + slider->ResizeTo(100, height); return slider; }