xref: /haiku/src/apps/icon-o-matic/generic/gui/stateview/MultipleManipulatorState.cpp (revision b028e77473189065f2baefc6f5e10d451cf591e2)
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
19 MultipleManipulatorState::MultipleManipulatorState(StateView* view)
20 	: ViewState(view),
21 	  fManipulators(24),
22 	  fCurrentManipulator(NULL),
23 	  fPreviousManipulator(NULL)
24 {
25 }
26 
27 // destructor
28 MultipleManipulatorState::~MultipleManipulatorState()
29 {
30 	DeleteManipulators();
31 }
32 
33 // #pragma mark -
34 
35 // Init
36 void
37 MultipleManipulatorState::Init()
38 {
39 }
40 
41 // Cleanup
42 void
43 MultipleManipulatorState::Cleanup()
44 {
45 }
46 
47 // #pragma mark -
48 
49 // Draw
50 void
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
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
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
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*
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
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
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
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
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
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*
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
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
270 MultipleManipulatorState::CountManipulators() const
271 {
272 	return fManipulators.CountItems();
273 }
274 
275 // ManipulatorAt
276 Manipulator*
277 MultipleManipulatorState::ManipulatorAt(int32 index) const
278 {
279 	return (Manipulator*)fManipulators.ItemAt(index);
280 }
281 
282 // ManipulatorAtFast
283 Manipulator*
284 MultipleManipulatorState::ManipulatorAtFast(int32 index) const
285 {
286 	return (Manipulator*)fManipulators.ItemAtFast(index);
287 }
288 
289 // #pragma mark -
290 
291 // _UpdateViewCursor
292 void
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
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