xref: /haiku/src/apps/icon-o-matic/generic/gui/stateview/MultipleManipulatorState.cpp (revision 3e216965baa8d58a67bf7372e2bfa13d999f5a9d)
1 /*
2  * Copyright 2006, 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 	int32 count = fManipulators.CountItems();
176 	for (int32 i = 0; i < count; i++) {
177 		Manipulator* manipulator =
178 			(Manipulator*)fManipulators.ItemAtFast(i);
179 		if (manipulator->HandleKeyDown(key, modifiers, _command))
180 			return true;
181 	}
182 	return false;
183 }
184 
185 // HandleKeyUp
186 bool
187 MultipleManipulatorState::HandleKeyUp(uint32 key, uint32 modifiers,
188 									  Command** _command)
189 {
190 	int32 count = fManipulators.CountItems();
191 	for (int32 i = 0; i < count; i++) {
192 		Manipulator* manipulator =
193 			(Manipulator*)fManipulators.ItemAtFast(i);
194 		if (manipulator->HandleKeyUp(key, modifiers, _command))
195 			return true;
196 	}
197 	return false;
198 }
199 
200 // #pragma mark -
201 
202 // AddManipulator
203 bool
204 MultipleManipulatorState::AddManipulator(Manipulator* manipulator)
205 {
206 	if (!manipulator)
207 		return false;
208 
209 	if (fManipulators.AddItem((void*)manipulator)) {
210 		manipulator->AttachedToView(fView);
211 		fView->Invalidate(manipulator->Bounds());
212 		return true;
213 	}
214 	return false;
215 }
216 
217 // RemoveManipulator
218 Manipulator*
219 MultipleManipulatorState::RemoveManipulator(int32 index)
220 {
221 	Manipulator* manipulator = (Manipulator*)fManipulators.RemoveItem(index);
222 
223 	if (manipulator == fCurrentManipulator)
224 		fCurrentManipulator = NULL;
225 
226 	if (manipulator) {
227 		fView->Invalidate(manipulator->Bounds());
228 		manipulator->DetachedFromView(fView);
229 	}
230 
231 	return manipulator;
232 }
233 
234 // DeleteManipulators
235 void
236 MultipleManipulatorState::DeleteManipulators()
237 {
238 	BRect dirty(LONG_MAX, LONG_MAX, LONG_MIN, LONG_MIN);
239 
240 	int32 count = fManipulators.CountItems();
241 	for (int32 i = 0; i < count; i++) {
242 		Manipulator* m = (Manipulator*)fManipulators.ItemAtFast(i);
243 		dirty = dirty | m->Bounds();
244 		m->DetachedFromView(fView);
245 		delete m;
246 	}
247 	fManipulators.MakeEmpty();
248 	fCurrentManipulator = NULL;
249 	fPreviousManipulator = NULL;
250 
251 	fView->Invalidate(dirty);
252 	_UpdateCursor();
253 }
254 
255 // CountManipulators
256 int32
257 MultipleManipulatorState::CountManipulators() const
258 {
259 	return fManipulators.CountItems();
260 }
261 
262 // ManipulatorAt
263 Manipulator*
264 MultipleManipulatorState::ManipulatorAt(int32 index) const
265 {
266 	return (Manipulator*)fManipulators.ItemAt(index);
267 }
268 
269 // ManipulatorAtFast
270 Manipulator*
271 MultipleManipulatorState::ManipulatorAtFast(int32 index) const
272 {
273 	return (Manipulator*)fManipulators.ItemAtFast(index);
274 }
275 
276 // #pragma mark -
277 
278 // _UpdateViewCursor
279 void
280 MultipleManipulatorState::_UpdateCursor()
281 {
282 	if (fCurrentManipulator)
283 		fCurrentManipulator->UpdateCursor();
284 	else
285 		fView->SetViewCursor(B_CURSOR_SYSTEM_DEFAULT);
286 }
287 
288 // _ShowContextMenu
289 void
290 MultipleManipulatorState::_ShowContextMenu(BPoint where)
291 {
292 	int32 count = fManipulators.CountItems();
293 	for (int32 i = 0; i < count; i++) {
294 		Manipulator* manipulator =
295 			(Manipulator*)fManipulators.ItemAtFast(i);
296 		if (manipulator->ShowContextMenu(where))
297 			return;
298 	}
299 }
300 
301 
302