* Copyright 2007, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "AbstractButton.h"
#include <View.h>
AbstractButton::AbstractButton(button_policy policy, BMessage* message,
BMessenger target)
: View(BRect(0, 0, 0, 0)),
BInvoker(message, target),
fPolicy(policy),
fSelected(false),
fPressed(false),
fPressedInBounds(false)
{
}
void
AbstractButton::SetPolicy(button_policy policy)
{
fPolicy = policy;
}
button_policy
AbstractButton::Policy() const
{
return fPolicy;
}
void
AbstractButton::SetSelected(bool selected)
{
if (selected != fSelected) {
fSelected = selected;
Invalidate();
bool notify = false;
switch (fPolicy) {
case BUTTON_POLICY_TOGGLE_ON_RELEASE:
case BUTTON_POLICY_SELECT_ON_RELEASE:
notify = true;
break;
case BUTTON_POLICY_INVOKE_ON_RELEASE:
notify = !fPressed;
break;
}
if (notify) {
_NotifyListeners();
if (Message()) {
BMessage message(*Message());
message.AddBool("selected", IsSelected());
InvokeNotify(&message);
}
}
}
}
bool
AbstractButton::IsSelected() const
{
return fSelected;
}
void
AbstractButton::MouseDown(BPoint where, uint32 buttons, int32 modifiers)
{
if (fPressed)
return;
fPressed = true;
_PressedUpdate(where);
}
void
AbstractButton::MouseUp(BPoint where, uint32 buttons, int32 modifiers)
{
if (!fPressed || (buttons & B_PRIMARY_MOUSE_BUTTON))
return;
_PressedUpdate(where);
fPressed = false;
if (fPressedInBounds) {
fPressedInBounds = false;
bool selected = fSelected;
switch (fPolicy) {
case BUTTON_POLICY_TOGGLE_ON_RELEASE:
selected = !fSelected;
break;
case BUTTON_POLICY_SELECT_ON_RELEASE:
selected = true;
break;
case BUTTON_POLICY_INVOKE_ON_RELEASE:
selected = false;
break;
}
SetSelected(selected);
}
Invalidate();
}
void
AbstractButton::MouseMoved(BPoint where, uint32 buttons, int32 modifiers)
{
if (!fPressed)
return;
_PressedUpdate(where);
}
void
AbstractButton::AddListener(Listener* listener)
{
if (listener && !fListeners.HasItem(listener))
fListeners.AddItem(listener);
}
void
AbstractButton::RemoveListener(Listener* listener)
{
if (listener)
fListeners.RemoveItem(listener);
}
bool
AbstractButton::IsPressed() const
{
return (fPressed && fPressedInBounds);
}
void
AbstractButton::_PressedUpdate(BPoint where)
{
bool pressedInBounds = Bounds().Contains(where);
if (pressedInBounds == fPressedInBounds)
return;
fPressedInBounds = pressedInBounds;
switch (fPolicy) {
case BUTTON_POLICY_TOGGLE_ON_RELEASE:
case BUTTON_POLICY_SELECT_ON_RELEASE:
break;
case BUTTON_POLICY_INVOKE_ON_RELEASE:
SetSelected(fPressedInBounds);
break;
}
Invalidate();
}
void
AbstractButton::_NotifyListeners()
{
if (!fListeners.IsEmpty()) {
BList listeners(fListeners);
for (int32 i = 0; Listener* listener = (Listener*)listeners.ItemAt(i);
i++) {
listener->SelectionChanged(this);
}
}
}
AbstractButton::Listener::~Listener()
{
}