DefaultMediaTheme: improve watching for parameter value changes.

* Addresses TODO of sub-classing controls, registering with the
  media roster for parameter changes.
* Also adds support for discrete parameter controls, which didn't
  have this functionality.
* With this change, the controls no longer need to be focused or
  modified for the parameter changes to register.
This commit is contained in:
Jessica Hamilton 2017-01-15 20:09:05 +13:00
parent 939b40d65c
commit 9c7d2b4668

View File

@ -105,6 +105,51 @@ class TitleView : public BView {
const char *fTitle; const char *fTitle;
}; };
class CheckBox : public BCheckBox {
public:
CheckBox(BRect area, const char* name, const char* label,
BDiscreteParameter &parameter);
virtual ~CheckBox();
virtual void AttachedToWindow();
private:
BDiscreteParameter &fParameter;
};
class OptionPopUp : public BOptionPopUp {
public:
OptionPopUp(BRect area, const char* name, const char* label,
BDiscreteParameter &parameter);
virtual ~OptionPopUp();
virtual void AttachedToWindow();
private:
BDiscreteParameter &fParameter;
};
class Slider : public BSlider {
public:
Slider(BRect area, const char* name, const char*label, int32 minValue,
int32 maxValue, BContinuousParameter &parameter);
virtual ~Slider();
virtual void AttachedToWindow();
private:
BContinuousParameter &fParameter;
};
class ChannelSlider : public BChannelSlider {
public:
ChannelSlider(BRect area, const char* name, const char* label,
orientation orientation, int32 channels,
BContinuousParameter &parameter);
virtual ~ChannelSlider();
virtual void AttachedToWindow();
private:
BContinuousParameter &fParameter;
};
class MessageFilter : public BMessageFilter { class MessageFilter : public BMessageFilter {
public: public:
static MessageFilter *FilterFor(BView *view, BParameter &parameter); static MessageFilter *FilterFor(BView *view, BParameter &parameter);
@ -126,7 +171,6 @@ class ContinuousMessageFilter : public MessageFilter {
BControl *fControl; BControl *fControl;
BContinuousParameter &fParameter; BContinuousParameter &fParameter;
bool fRegistered;
}; };
class DiscreteMessageFilter : public MessageFilter { class DiscreteMessageFilter : public MessageFilter {
@ -165,6 +209,25 @@ parameter_should_be_hidden(BParameter &parameter)
} }
static void
start_watching_for_parameter_changes(BControl* control, BParameter &parameter)
{
if (BMediaRoster* roster = BMediaRoster::CurrentRoster()) {
roster->StartWatching(control, parameter.Web()->Node(),
B_MEDIA_NEW_PARAMETER_VALUE);
}
}
static void
stop_watching_for_parameter_changes(BControl* control, BParameter &parameter)
{
if (BMediaRoster* roster = BMediaRoster::CurrentRoster()) {
roster->StopWatching(control, parameter.Web()->Node(),
B_MEDIA_NEW_PARAMETER_VALUE);
}
}
// #pragma mark - // #pragma mark -
@ -557,6 +620,93 @@ TitleView::GetPreferredSize(float *_width, float *_height)
// #pragma mark - // #pragma mark -
CheckBox::CheckBox(BRect area, const char* name, const char* label,
BDiscreteParameter &parameter)
: BCheckBox(area, name, label, NULL),
fParameter(parameter)
{
}
CheckBox::~CheckBox()
{
stop_watching_for_parameter_changes(this, fParameter);
}
void
CheckBox::AttachedToWindow()
{
start_watching_for_parameter_changes(this, fParameter);
}
OptionPopUp::OptionPopUp(BRect area, const char* name, const char* label,
BDiscreteParameter &parameter)
: BOptionPopUp(area, name, label, NULL),
fParameter(parameter)
{
}
OptionPopUp::~OptionPopUp()
{
stop_watching_for_parameter_changes(this, fParameter);
}
void
OptionPopUp::AttachedToWindow()
{
start_watching_for_parameter_changes(this, fParameter);
}
Slider::Slider(BRect area, const char* name, const char* label, int32 minValue,
int32 maxValue, BContinuousParameter &parameter)
: BSlider(area, name, label, NULL, minValue, maxValue),
fParameter(parameter)
{
}
Slider::~Slider()
{
stop_watching_for_parameter_changes(this, fParameter);
}
void
Slider::AttachedToWindow()
{
start_watching_for_parameter_changes(this, fParameter);
}
ChannelSlider::ChannelSlider(BRect area, const char* name, const char* label,
orientation orientation, int32 channels, BContinuousParameter &parameter)
: BChannelSlider(area, name, label, NULL, orientation, channels),
fParameter(parameter)
{
}
ChannelSlider::~ChannelSlider()
{
stop_watching_for_parameter_changes(this, fParameter);
}
void
ChannelSlider::AttachedToWindow()
{
start_watching_for_parameter_changes(this, fParameter);
}
// #pragma mark -
MessageFilter::MessageFilter() MessageFilter::MessageFilter()
: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE) : BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE)
{ {
@ -593,8 +743,7 @@ ContinuousMessageFilter::ContinuousMessageFilter(BControl *control,
BContinuousParameter &parameter) BContinuousParameter &parameter)
: MessageFilter(), : MessageFilter(),
fControl(control), fControl(control),
fParameter(parameter), fParameter(parameter)
fRegistered(false)
{ {
// initialize view for us // initialize view for us
control->SetMessage(new BMessage(kMsgParameterChanged)); control->SetMessage(new BMessage(kMsgParameterChanged));
@ -622,16 +771,6 @@ ContinuousMessageFilter::Filter(BMessage *message, BHandler **target)
if (*target != fControl) if (*target != fControl)
return B_DISPATCH_MESSAGE; return B_DISPATCH_MESSAGE;
// TODO: remove this work-around! We can solve this by subclassing the
// slider classes, and start watching in their AttachedToWindow() method
if (!fRegistered) {
if (BMediaRoster* roster = BMediaRoster::CurrentRoster()) {
roster->StartWatching(fControl, fParameter.Web()->Node(),
B_MEDIA_NEW_PARAMETER_VALUE);
}
fRegistered = true;
}
if (message->what == kMsgParameterChanged) { if (message->what == kMsgParameterChanged) {
// update parameter from control // update parameter from control
// TODO: support for response! // TODO: support for response!
@ -715,7 +854,6 @@ DiscreteMessageFilter::DiscreteMessageFilter(BControl *control,
control->SetMessage(new BMessage(kMsgParameterChanged)); control->SetMessage(new BMessage(kMsgParameterChanged));
// set initial value // set initial value
size_t size = sizeof(int32); size_t size = sizeof(int32);
int32 value; int32 value;
if (parameter.GetValue((void *)&value, &size, NULL) < B_OK) { if (parameter.GetValue((void *)&value, &size, NULL) < B_OK) {
@ -744,8 +882,39 @@ DiscreteMessageFilter::Filter(BMessage *message, BHandler **target)
{ {
BControl *control; BControl *control;
if (message->what != kMsgParameterChanged if ((control = dynamic_cast<BControl *>(*target)) == NULL)
|| (control = dynamic_cast<BControl *>(*target)) == NULL) return B_DISPATCH_MESSAGE;
if (message->what == B_MEDIA_NEW_PARAMETER_VALUE) {
TRACE("DiscreteMessageFilter::Filter: Got a new parameter value\n");
const media_node* node;
int32 parameterID;
ssize_t size;
if (message->FindInt32("parameter", &parameterID) != B_OK
|| fParameter.ID() != parameterID
|| message->FindData("node", B_RAW_TYPE, (const void**)&node,
&size) != B_OK
|| fParameter.Web()->Node() != *node)
return B_DISPATCH_MESSAGE;
int32 value = 0;
size_t valueSize = sizeof(int32);
if (fParameter.GetValue((void*)&value, &valueSize, NULL) < B_OK) {
ERROR("DiscreteMessageFilter: Could not get value for continuous "
"parameter %p (name '%s', node %d)\n", &fParameter,
fParameter.Name(), (int)fParameter.Web()->Node().node);
return B_SKIP_MESSAGE;
}
if (BCheckBox* checkBox = dynamic_cast<BCheckBox*>(control)) {
checkBox->SetValue(value);
} else if (BOptionPopUp* popUp = dynamic_cast<BOptionPopUp*>(control)) {
popUp->SetValue(value);
}
return B_SKIP_MESSAGE;
}
if (message->what != kMsgParameterChanged)
return B_DISPATCH_MESSAGE; return B_DISPATCH_MESSAGE;
// update view // update view
@ -1077,8 +1246,8 @@ DefaultMediaTheme::MakeViewFor(BParameter *parameter, const BRect *hintRect)
|| discrete.CountItems() == 0) { || discrete.CountItems() == 0) {
// create a checkbox item // create a checkbox item
BCheckBox *checkBox = new BCheckBox(rect, discrete.Name(), BCheckBox *checkBox = new CheckBox(rect, discrete.Name(),
discrete.Name(), NULL); discrete.Name(), discrete);
checkBox->ResizeToPreferred(); checkBox->ResizeToPreferred();
return checkBox; return checkBox;
@ -1099,8 +1268,8 @@ DefaultMediaTheme::MakeViewFor(BParameter *parameter, const BRect *hintRect)
width += font.StringWidth(discrete.Name()) + 55; width += font.StringWidth(discrete.Name()) + 55;
rect.right = rect.left + width; rect.right = rect.left + width;
BOptionPopUp *popUp = new BOptionPopUp(rect, discrete.Name(), BOptionPopUp *popUp = new OptionPopUp(rect, discrete.Name(),
discrete.Name(), NULL); discrete.Name(), discrete);
for (int32 i = 0; i < discrete.CountItems(); i++) { for (int32 i = 0; i < discrete.CountItems(); i++) {
popUp->AddOption(discrete.ItemNameAt(i), discrete.ItemValueAt(i)); popUp->AddOption(discrete.ItemNameAt(i), discrete.ItemValueAt(i));
@ -1118,8 +1287,9 @@ DefaultMediaTheme::MakeViewFor(BParameter *parameter, const BRect *hintRect)
if (!strcmp(continuous.Kind(), B_MASTER_GAIN) if (!strcmp(continuous.Kind(), B_MASTER_GAIN)
|| !strcmp(continuous.Kind(), B_GAIN)) { || !strcmp(continuous.Kind(), B_GAIN)) {
BChannelSlider *slider = new BChannelSlider(rect, continuous.Name(), BChannelSlider *slider = new ChannelSlider(rect,
continuous.Name(), NULL, B_VERTICAL, continuous.CountChannels()); continuous.Name(), continuous.Name(), B_VERTICAL,
continuous.CountChannels(), continuous);
char minLabel[64], maxLabel[64]; char minLabel[64], maxLabel[64];
@ -1148,8 +1318,8 @@ DefaultMediaTheme::MakeViewFor(BParameter *parameter, const BRect *hintRect)
return slider; return slider;
} }
BSlider *slider = new BSlider(rect, parameter->Name(), parameter->Name(), BSlider *slider = new Slider(rect, parameter->Name(),
NULL, 0, 100); parameter->Name(), 0, 100, continuous);
float width, height; float width, height;
slider->GetPreferredSize(&width, &height); slider->GetPreferredSize(&width, &height);