xref: /haiku/src/tests/kits/interface/layout/widget_layout_test/AbstractButton.cpp (revision 0ce9bc68953f5c743aba5d2e125419133e15c641)
1 /*
2  * Copyright 2007, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
3  * All rights reserved. Distributed under the terms of the MIT License.
4  */
5 
6 #include "AbstractButton.h"
7 
8 #include <View.h>
9 
10 
11 // #pragma mark - AbstractButton
12 
13 
AbstractButton(button_policy policy,BMessage * message,BMessenger target)14 AbstractButton::AbstractButton(button_policy policy, BMessage* message,
15 	BMessenger target)
16 	: View(BRect(0, 0, 0, 0)),
17 	  BInvoker(message, target),
18 	  fPolicy(policy),
19 	  fSelected(false),
20 	  fPressed(false),
21 	  fPressedInBounds(false)
22 {
23 }
24 
25 
26 void
SetPolicy(button_policy policy)27 AbstractButton::SetPolicy(button_policy policy)
28 {
29 	fPolicy = policy;
30 }
31 
32 
33 button_policy
Policy() const34 AbstractButton::Policy() const
35 {
36 	return fPolicy;
37 }
38 
39 
40 void
SetSelected(bool selected)41 AbstractButton::SetSelected(bool selected)
42 {
43 	if (selected != fSelected) {
44 		fSelected = selected;
45 		Invalidate();
46 
47 		// check whether to notify the listeners depending on the button policy
48 		bool notify = false;
49 		switch (fPolicy) {
50 			case BUTTON_POLICY_TOGGLE_ON_RELEASE:
51 			case BUTTON_POLICY_SELECT_ON_RELEASE:
52 				// always notify on selection changes
53 				notify = true;
54 				break;
55 			case BUTTON_POLICY_INVOKE_ON_RELEASE:
56 				// only notify when the user interaction has been finished
57 				notify = !fPressed;
58 				break;
59 		}
60 
61 		if (notify) {
62 			// notify synchronous listeners
63 			_NotifyListeners();
64 
65 			// send the message
66 			if (Message()) {
67 				BMessage message(*Message());
68 				message.AddBool("selected", IsSelected());
69 				InvokeNotify(&message);
70 			}
71 		}
72 	}
73 }
74 
75 
76 bool
IsSelected() const77 AbstractButton::IsSelected() const
78 {
79 	return fSelected;
80 }
81 
82 
83 void
MouseDown(BPoint where,uint32 buttons,int32 modifiers)84 AbstractButton::MouseDown(BPoint where, uint32 buttons, int32 modifiers)
85 {
86 	if (fPressed)
87 		return;
88 
89 	fPressed = true;
90 	_PressedUpdate(where);
91 }
92 
93 
94 void
MouseUp(BPoint where,uint32 buttons,int32 modifiers)95 AbstractButton::MouseUp(BPoint where, uint32 buttons, int32 modifiers)
96 {
97 	if (!fPressed || (buttons & B_PRIMARY_MOUSE_BUTTON))
98 		return;
99 
100 	_PressedUpdate(where);
101 	fPressed = false;
102 	if (fPressedInBounds) {
103 		fPressedInBounds = false;
104 
105 		// update selected state according to policy
106 		bool selected = fSelected;
107 		switch (fPolicy) {
108 			case BUTTON_POLICY_TOGGLE_ON_RELEASE:
109 				selected = !fSelected;
110 				break;
111 			case BUTTON_POLICY_SELECT_ON_RELEASE:
112 				selected = true;
113 				break;
114 			case BUTTON_POLICY_INVOKE_ON_RELEASE:
115 				selected = false;
116 				break;
117 		}
118 
119 		SetSelected(selected);
120 	}
121 	Invalidate();
122 }
123 
124 
125 void
MouseMoved(BPoint where,uint32 buttons,int32 modifiers)126 AbstractButton::MouseMoved(BPoint where, uint32 buttons, int32 modifiers)
127 {
128 	if (!fPressed)
129 		return;
130 
131 	_PressedUpdate(where);
132 }
133 
134 
135 void
AddListener(Listener * listener)136 AbstractButton::AddListener(Listener* listener)
137 {
138 	if (listener && !fListeners.HasItem(listener))
139 		fListeners.AddItem(listener);
140 }
141 
142 
143 void
RemoveListener(Listener * listener)144 AbstractButton::RemoveListener(Listener* listener)
145 {
146 	if (listener)
147 		fListeners.RemoveItem(listener);
148 }
149 
150 
151 bool
IsPressed() const152 AbstractButton::IsPressed() const
153 {
154 	return (fPressed && fPressedInBounds);
155 }
156 
157 
158 void
_PressedUpdate(BPoint where)159 AbstractButton::_PressedUpdate(BPoint where)
160 {
161 	bool pressedInBounds = Bounds().Contains(where);
162 	if (pressedInBounds == fPressedInBounds)
163 		return;
164 
165 	fPressedInBounds = pressedInBounds;
166 
167 	// update the selected state according to the button policy
168 	switch (fPolicy) {
169 		case BUTTON_POLICY_TOGGLE_ON_RELEASE:
170 		case BUTTON_POLICY_SELECT_ON_RELEASE:
171 			// nothing to do
172 			break;
173 		case BUTTON_POLICY_INVOKE_ON_RELEASE:
174 			SetSelected(fPressedInBounds);
175 			break;
176 	}
177 
178 	Invalidate();
179 }
180 
181 
182 void
_NotifyListeners()183 AbstractButton::_NotifyListeners()
184 {
185 	if (!fListeners.IsEmpty()) {
186 		BList listeners(fListeners);
187 		for (int32 i = 0; Listener* listener = (Listener*)listeners.ItemAt(i);
188 			 i++) {
189 			listener->SelectionChanged(this);
190 		}
191 	}
192 }
193 
194 
195 // #pragma mark - AbstractButton::Listener
196 
197 
~Listener()198 AbstractButton::Listener::~Listener()
199 {
200 }
201 
202