1 /*
2 * Copyright 2006-2007, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Stephan Aßmus <superstippi@gmx.de>
7 */
8
9 #include "MultipleManipulatorState.h"
10
11 #include <stdio.h>
12
13 #include <AppDefs.h>
14
15 #include "Manipulator.h"
16 #include "StateView.h"
17
18 // constructor
MultipleManipulatorState(StateView * view)19 MultipleManipulatorState::MultipleManipulatorState(StateView* view)
20 : ViewState(view),
21 fManipulators(24),
22 fCurrentManipulator(NULL),
23 fPreviousManipulator(NULL)
24 {
25 }
26
27 // destructor
~MultipleManipulatorState()28 MultipleManipulatorState::~MultipleManipulatorState()
29 {
30 DeleteManipulators();
31 }
32
33 // #pragma mark -
34
35 // Init
36 void
Init()37 MultipleManipulatorState::Init()
38 {
39 }
40
41 // Cleanup
42 void
Cleanup()43 MultipleManipulatorState::Cleanup()
44 {
45 }
46
47 // #pragma mark -
48
49 // Draw
50 void
Draw(BView * into,BRect updateRect)51 MultipleManipulatorState::Draw(BView* into, BRect updateRect)
52 {
53 int32 count = fManipulators.CountItems();
54 for (int32 i = 0; i < count; i++) {
55 Manipulator* manipulator =
56 (Manipulator*)fManipulators.ItemAtFast(i);
57 if (manipulator->Bounds().Intersects(updateRect))
58 manipulator->Draw(into, updateRect);
59 }
60 }
61
62 // MessageReceived
63 bool
MessageReceived(BMessage * message,Command ** _command)64 MultipleManipulatorState::MessageReceived(BMessage* message,
65 Command** _command)
66 {
67 int32 count = fManipulators.CountItems();
68 for (int32 i = 0; i < count; i++) {
69 Manipulator* manipulator =
70 (Manipulator*)fManipulators.ItemAtFast(i);
71 if (manipulator->MessageReceived(message, _command))
72 return true;
73 }
74 return false;
75 }
76
77 // #pragma mark -
78
79 // MouseDown
80 void
MouseDown(BPoint where,uint32 buttons,uint32 clicks)81 MultipleManipulatorState::MouseDown(BPoint where, uint32 buttons, uint32 clicks)
82 {
83 if (buttons & B_SECONDARY_MOUSE_BUTTON) {
84 _ShowContextMenu(where);
85 return;
86 }
87
88 if (clicks == 2
89 && fPreviousManipulator
90 && fManipulators.HasItem(fPreviousManipulator)) {
91 // valid double click (onto the same, still existing manipulator)
92 if (fPreviousManipulator->TrackingBounds(fView).Contains(where)
93 && fPreviousManipulator->DoubleClicked(where)) {
94 // TODO: eat the click here or wait for MouseUp?
95 fPreviousManipulator = NULL;
96 return;
97 }
98 }
99
100 int32 count = fManipulators.CountItems();
101 for (int32 i = count - 1; i >= 0; i--) {
102 Manipulator* manipulator =
103 (Manipulator*)fManipulators.ItemAtFast(i);
104 if (manipulator->MouseDown(where)) {
105 fCurrentManipulator = manipulator;
106 break;
107 }
108 }
109
110 fView->SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
111 }
112
113 // MouseMoved
114 void
MouseMoved(BPoint where,uint32 transit,const BMessage * dragMessage)115 MultipleManipulatorState::MouseMoved(BPoint where, uint32 transit,
116 const BMessage* dragMessage)
117 {
118 if (fCurrentManipulator) {
119 // the mouse is currently pressed
120 fCurrentManipulator->MouseMoved(where);
121
122 } else {
123 // the mouse is currently NOT pressed
124
125 // call MouseOver on all manipulators
126 // until one feels responsible
127 int32 count = fManipulators.CountItems();
128 bool updateCursor = true;
129 for (int32 i = 0; i < count; i++) {
130 Manipulator* manipulator =
131 (Manipulator*)fManipulators.ItemAtFast(i);
132 if (manipulator->TrackingBounds(fView).Contains(where)
133 && manipulator->MouseOver(where)) {
134 updateCursor = false;
135 break;
136 }
137 }
138 if (updateCursor)
139 _UpdateCursor();
140 }
141 }
142
143 // MouseUp
144 Command*
MouseUp()145 MultipleManipulatorState::MouseUp()
146 {
147 Command* command = NULL;
148 if (fCurrentManipulator) {
149 command = fCurrentManipulator->MouseUp();
150 fPreviousManipulator = fCurrentManipulator;
151 fCurrentManipulator = NULL;
152 }
153 return command;
154 }
155
156 // #pragma mark -
157
158 // ModifiersChanged
159 void
ModifiersChanged(uint32 modifiers)160 MultipleManipulatorState::ModifiersChanged(uint32 modifiers)
161 {
162 int32 count = fManipulators.CountItems();
163 for (int32 i = 0; i < count; i++) {
164 Manipulator* manipulator =
165 (Manipulator*)fManipulators.ItemAtFast(i);
166 manipulator->ModifiersChanged(modifiers);
167 }
168 }
169
170 // HandleKeyDown
171 bool
HandleKeyDown(uint32 key,uint32 modifiers,Command ** _command)172 MultipleManipulatorState::HandleKeyDown(uint32 key, uint32 modifiers,
173 Command** _command)
174 {
175 // TODO: somehow this looks suspicious, because it doesn't
176 // seem guaranteed that the manipulator having indicated to
177 // handle the key down handles the matching key up event...
178 // maybe there should be the concept of the "focused manipulator"
179 int32 count = fManipulators.CountItems();
180 for (int32 i = 0; i < count; i++) {
181 Manipulator* manipulator =
182 (Manipulator*)fManipulators.ItemAtFast(i);
183 if (manipulator->HandleKeyDown(key, modifiers, _command))
184 return true;
185 }
186 return false;
187 }
188
189 // HandleKeyUp
190 bool
HandleKeyUp(uint32 key,uint32 modifiers,Command ** _command)191 MultipleManipulatorState::HandleKeyUp(uint32 key, uint32 modifiers,
192 Command** _command)
193 {
194 int32 count = fManipulators.CountItems();
195 for (int32 i = 0; i < count; i++) {
196 Manipulator* manipulator =
197 (Manipulator*)fManipulators.ItemAtFast(i);
198 if (manipulator->HandleKeyUp(key, modifiers, _command))
199 return true;
200 }
201 return false;
202 }
203
204 // UpdateCursor
205 bool
UpdateCursor()206 MultipleManipulatorState::UpdateCursor()
207 {
208 if (fPreviousManipulator && fManipulators.HasItem(fPreviousManipulator))
209 return fPreviousManipulator->UpdateCursor();
210 return false;
211 }
212
213 // #pragma mark -
214
215 // AddManipulator
216 bool
AddManipulator(Manipulator * manipulator)217 MultipleManipulatorState::AddManipulator(Manipulator* manipulator)
218 {
219 if (!manipulator)
220 return false;
221
222 if (fManipulators.AddItem((void*)manipulator)) {
223 manipulator->AttachedToView(fView);
224 fView->Invalidate(manipulator->Bounds());
225 return true;
226 }
227 return false;
228 }
229
230 // RemoveManipulator
231 Manipulator*
RemoveManipulator(int32 index)232 MultipleManipulatorState::RemoveManipulator(int32 index)
233 {
234 Manipulator* manipulator = (Manipulator*)fManipulators.RemoveItem(index);
235
236 if (manipulator == fCurrentManipulator)
237 fCurrentManipulator = NULL;
238
239 if (manipulator) {
240 fView->Invalidate(manipulator->Bounds());
241 manipulator->DetachedFromView(fView);
242 }
243
244 return manipulator;
245 }
246
247 // DeleteManipulators
248 void
DeleteManipulators()249 MultipleManipulatorState::DeleteManipulators()
250 {
251 BRect dirty(LONG_MAX, LONG_MAX, LONG_MIN, LONG_MIN);
252
253 int32 count = fManipulators.CountItems();
254 for (int32 i = 0; i < count; i++) {
255 Manipulator* m = (Manipulator*)fManipulators.ItemAtFast(i);
256 dirty = dirty | m->Bounds();
257 m->DetachedFromView(fView);
258 delete m;
259 }
260 fManipulators.MakeEmpty();
261 fCurrentManipulator = NULL;
262 fPreviousManipulator = NULL;
263
264 fView->Invalidate(dirty);
265 _UpdateCursor();
266 }
267
268 // CountManipulators
269 int32
CountManipulators() const270 MultipleManipulatorState::CountManipulators() const
271 {
272 return fManipulators.CountItems();
273 }
274
275 // ManipulatorAt
276 Manipulator*
ManipulatorAt(int32 index) const277 MultipleManipulatorState::ManipulatorAt(int32 index) const
278 {
279 return (Manipulator*)fManipulators.ItemAt(index);
280 }
281
282 // ManipulatorAtFast
283 Manipulator*
ManipulatorAtFast(int32 index) const284 MultipleManipulatorState::ManipulatorAtFast(int32 index) const
285 {
286 return (Manipulator*)fManipulators.ItemAtFast(index);
287 }
288
289 // #pragma mark -
290
291 // _UpdateViewCursor
292 void
_UpdateCursor()293 MultipleManipulatorState::_UpdateCursor()
294 {
295 if (fCurrentManipulator)
296 fCurrentManipulator->UpdateCursor();
297 else
298 fView->SetViewCursor(B_CURSOR_SYSTEM_DEFAULT);
299 }
300
301 // _ShowContextMenu
302 void
_ShowContextMenu(BPoint where)303 MultipleManipulatorState::_ShowContextMenu(BPoint where)
304 {
305 int32 count = fManipulators.CountItems();
306 for (int32 i = 0; i < count; i++) {
307 Manipulator* manipulator =
308 (Manipulator*)fManipulators.ItemAtFast(i);
309 if (manipulator->ShowContextMenu(where))
310 return;
311 }
312 }
313
314
315