xref: /haiku/src/servers/input/MethodReplicant.cpp (revision 4f00613311d0bd6b70fa82ce19931c41f071ea4e)
1 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
2 //
3 //	Copyright (c) 2004, Haiku
4 //
5 //  This software is part of the Haiku distribution and is covered
6 //  by the Haiku license.
7 //
8 //
9 //  File:			MethodReplicant.cpp
10 //  Authors:		Jérôme Duval,
11 //
12 //  Description:	Input Server
13 //  Created:		October 13, 2004
14 //
15 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
16 
17 #include <Alert.h>
18 #include <AppDefs.h>
19 #include <Debug.h>
20 #include <Dragger.h>
21 #include <Bitmap.h>
22 #include <MenuItem.h>
23 #include <Message.h>
24 #include <Messenger.h>
25 #include <PopUpMenu.h>
26 
27 #include <string.h>
28 #include "MethodReplicant.h"
29 #include "remote_icon.h"
30 
31 #include "InputServerTypes.h"
32 
33 #ifdef DEBUG
34 	#define CALLED() PRINT(("CALLED %s \n", __PRETTY_FUNCTION__));
35 #else
36 	#define CALLED()
37 #endif
38 
39 
40 MethodReplicant::MethodReplicant(const char* signature)
41 	:	BView(BRect(0, 0, 15, 15), REPLICANT_CTL_NAME, B_FOLLOW_ALL, B_WILL_DRAW),
42 		fMenu("", false, false)
43 {
44 	// Background Bitmap
45 	fSegments = new BBitmap(BRect(0, 0, kRemoteWidth - 1, kRemoteHeight - 1), kRemoteColorSpace);
46 	fSegments->SetBits(kRemoteBits, kRemoteWidth*kRemoteHeight, 0, kRemoteColorSpace);
47 	// Background Color
48 	SetViewColor(184,184,184);
49 
50 	//add dragger
51 	BRect rect(Bounds());
52 	rect.left = rect.right-7.0;
53 	rect.top = rect.bottom-7.0;
54 	BDragger *dragger = new BDragger(rect, this, B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
55 	AddChild(dragger);
56 	dragger->SetViewColor(B_TRANSPARENT_32_BIT);
57 
58 	ASSERT(signature!=NULL);
59 	fSignature = strdup(signature);
60 
61 	fMenu.SetFont(be_plain_font);
62 	fMenu.SetRadioMode(true);
63 }
64 
65 
66 MethodReplicant::MethodReplicant(BMessage *message)
67 	:	BView(message),
68 		fMenu("", false, false)
69 {
70 	// Background Bitmap
71 	fSegments = new BBitmap(BRect(0, 0, kRemoteWidth - 1, kRemoteHeight - 1), kRemoteColorSpace);
72 	fSegments->SetBits(kRemoteBits, kRemoteWidth*kRemoteHeight, 0, kRemoteColorSpace);
73 
74 	const char *signature = NULL;
75 	message->FindString("add_on", &signature);
76 	ASSERT(signature!=NULL);
77 	fSignature = strdup(signature);
78 
79 	fMenu.SetFont(be_plain_font);
80 	fMenu.SetRadioMode(true);
81 }
82 
83 
84 MethodReplicant::~MethodReplicant()
85 {
86 	delete fSegments;
87 	delete fSignature;
88 }
89 
90 
91 // archiving overrides
92 MethodReplicant *
93 MethodReplicant::Instantiate(BMessage *data)
94 {
95 	CALLED();
96 	if (!validate_instantiation(data, REPLICANT_CTL_NAME))
97 		return NULL;
98 	return new MethodReplicant(data);
99 }
100 
101 
102 status_t
103 MethodReplicant::Archive(BMessage *data, bool deep) const
104 {
105 	BView::Archive(data, deep);
106 
107 	data->AddString("add_on", fSignature);
108 	return B_NO_ERROR;
109 }
110 
111 
112 void
113 MethodReplicant::AttachedToWindow()
114 {
115 	CALLED();
116 	BMessenger messenger(this);
117 	BMessage msg(IS_METHOD_REGISTER);
118 	msg.AddMessenger("address", messenger);
119 
120 	BMessenger inputMessenger(fSignature);
121 	if (inputMessenger.SendMessage(&msg)!=B_OK) {
122 		printf("error when contacting input_server\n");
123 	}
124 }
125 
126 
127 void
128 MethodReplicant::MessageReceived(BMessage *message)
129 {
130 	PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__, message->what>>24, message->what>>16, message->what>>8, message->what));
131 	PRINT_OBJECT(*message);
132 	switch (message->what) {
133 	case B_ABOUT_REQUESTED:
134 		(new BAlert("About Method Replicant", "Method Replicant (Replicant)\n"
135 			    "  Brought to you by Jérôme DUVAL.\n\n"
136 			    "Haiku, 2004","OK"))->Go();
137 		break;
138 	case IS_UPDATE_NAME:
139 		UpdateMethodName(message);
140 		break;
141 	case IS_UPDATE_ICON:
142 		UpdateMethodIcon(message);
143 		break;
144 	case IS_UPDATE_MENU:
145 		UpdateMethodMenu(message);
146 		break;
147 	case IS_UPDATE_METHOD:
148 		UpdateMethod(message);
149 		break;
150 	case IS_ADD_METHOD:
151 		AddMethod(message);
152 		break;
153 	case IS_REMOVE_METHOD:
154 		RemoveMethod(message);
155 		break;
156 
157 	default:
158 		BView::MessageReceived(message);
159 		break;
160 	}
161 }
162 
163 
164 void
165 MethodReplicant::Draw(BRect rect)
166 {
167 	BView::Draw(rect);
168 
169 	SetDrawingMode(B_OP_OVER);
170 	DrawBitmap(fSegments);
171 }
172 
173 
174 void
175 MethodReplicant::MouseDown(BPoint point)
176 {
177 	CALLED();
178 	uint32 mouseButtons;
179 	BPoint where;
180 	GetMouse(&where, &mouseButtons, true);
181 
182 	where = ConvertToScreen(point);
183 
184 	fMenu.SetTargetForItems(this);
185 	MethodMenuItem *item = (MethodMenuItem*)fMenu.Go(where, true, true, BRect(where - BPoint(4, 4),
186 		where + BPoint(4, 4)));
187 	if (item) {
188 		BMessage msg(IS_SET_METHOD);
189 		msg.AddInt32("cookie", item->Cookie());
190 		BMessenger messenger(fSignature);
191 		messenger.SendMessage(&msg);
192 	}
193 }
194 
195 
196 void
197 MethodReplicant::MouseUp(BPoint point)
198 {
199 	/* don't Quit() ! thanks for FFM users */
200 }
201 
202 
203 void
204 MethodReplicant::UpdateMethod(BMessage *message)
205 {
206 	CALLED();
207 	int32 cookie;
208         if (message->FindInt32("cookie", &cookie)!=B_OK) {
209                 fprintf(stderr, "can't find cookie in message\n");
210                 return;
211         }
212 
213 	MethodMenuItem *item = FindItemByCookie(cookie);
214         if (item == NULL) {
215                 fprintf(stderr, "can't find item with cookie %lx\n", cookie);
216                 return;
217         }
218 	item->SetMarked(true);
219 
220 	fSegments->SetBits(item->Icon(), kRemoteWidth*kRemoteHeight, 0, kRemoteColorSpace);
221 	Invalidate();
222 }
223 
224 
225 void
226 MethodReplicant::UpdateMethodIcon(BMessage *message)
227 {
228 	CALLED();
229 	int32 cookie;
230 	if (message->FindInt32("cookie", &cookie)!=B_OK) {
231 		fprintf(stderr, "can't find cookie in message\n");
232 		return;
233 	}
234 
235 	const uchar *data;
236 	ssize_t numBytes;
237 	if (message->FindData("icon", B_ANY_TYPE, (const void**)&data, &numBytes)!=B_OK) {
238 		fprintf(stderr, "can't find icon in message\n");
239 		return;
240 	}
241 
242 	MethodMenuItem *item = FindItemByCookie(cookie);
243 	if (item == NULL) {
244 		fprintf(stderr, "can't find item with cookie 0x%lx\n", cookie);
245 		return;
246 	}
247 
248 	item->SetIcon(data);
249 }
250 
251 
252 void
253 MethodReplicant::UpdateMethodMenu(BMessage *message)
254 {
255 	CALLED();
256 	int32 cookie;
257 	if (message->FindInt32("cookie", &cookie)!=B_OK) {
258 		fprintf(stderr, "can't find cookie in message\n");
259 		return;
260 	}
261 
262 	BMessage msg;
263 	if (message->FindMessage("menu", &msg)!=B_OK) {
264 		fprintf(stderr, "can't find menu in message\n");
265                 return;
266         }
267 	PRINT_OBJECT(msg);
268 
269 	BMessenger messenger;
270 	if (message->FindMessenger("target", &messenger)!=B_OK) {
271                 fprintf(stderr, "can't find target in message\n");
272                 return;
273         }
274 
275 	BMenu *menu = (BMenu *)BMenu::Instantiate(&msg);
276 	if (menu == NULL) {
277 		PRINT(("can't instantiate menu\n"));
278 	} else
279 		menu->SetTargetForItems(messenger);
280 
281 	MethodMenuItem *item = FindItemByCookie(cookie);
282 	if (item == NULL) {
283 		fprintf(stderr, "can't find item with cookie 0x%lx\n", cookie);
284 		return;
285 	}
286 	int32 index = fMenu.IndexOf(item);
287 
288 	MethodMenuItem *item2 = NULL;
289 	if (menu)
290 		item2 = new MethodMenuItem(cookie, item->Label(), item->Icon(),
291 			menu, messenger);
292 	else
293 		item2 = new MethodMenuItem(cookie, item->Label(), item->Icon());
294 	item = (MethodMenuItem*)fMenu.RemoveItem(index);
295 	fMenu.AddItem(item2, index);
296 	item2->SetMarked(item->IsMarked());
297 	delete item;
298 }
299 
300 
301 void
302 MethodReplicant::UpdateMethodName(BMessage *message)
303 {
304 	CALLED();
305 	int32 cookie;
306 	if (message->FindInt32("cookie", &cookie)!=B_OK) {
307 		fprintf(stderr, "can't find cookie in message\n");
308 		return;
309 	}
310 
311 	const char *name;
312 	if (message->FindString("name", &name)!=B_OK) {
313 		fprintf(stderr, "can't find name in message\n");
314 		return;
315 	}
316 
317 	MethodMenuItem *item = FindItemByCookie(cookie);
318 	if (item == NULL) {
319 		fprintf(stderr, "can't find item with cookie 0x%lx\n", cookie);
320 		return;
321 	}
322 
323 	item->SetName(name);
324 }
325 
326 
327 MethodMenuItem *
328 MethodReplicant::FindItemByCookie(int32 cookie)
329 {
330 	for (int32 i=0; i<fMenu.CountItems(); i++) {
331 		MethodMenuItem *item = (MethodMenuItem *)fMenu.ItemAt(i);
332 		PRINT(("cookie : 0x%lx\n", item->Cookie()));
333 		if (item->Cookie()==cookie)
334 			return item;
335 	}
336 
337 	return NULL;
338 }
339 
340 
341 void
342 MethodReplicant::AddMethod(BMessage *message)
343 {
344 	CALLED();
345 	int32 cookie;
346 	if (message->FindInt32("cookie", &cookie)!=B_OK) {
347 	        fprintf(stderr, "can't find cookie in message\n");
348 	        return;
349 	}
350 
351 	const char *name;
352 	if (message->FindString("name", &name)!=B_OK) {
353 		fprintf(stderr, "can't find name in message\n");
354 		return;
355 	}
356 
357 	const uchar *icon;
358 	ssize_t numBytes;
359 	if (message->FindData("icon", B_ANY_TYPE, (const void**)&icon, &numBytes)!=B_OK) {
360 		fprintf(stderr, "can't find icon in message\n");
361 		return;
362 	}
363 
364 	MethodMenuItem *item = FindItemByCookie(cookie);
365 	if (item != NULL) {
366 		fprintf(stderr, "item with cookie %lx already exists\n", cookie);
367 		return;
368 	}
369 
370 	item = new MethodMenuItem(cookie, name, icon);
371 	fMenu.AddItem(item);
372 	item->SetTarget(this);
373 
374 	if (fMenu.CountItems() == 1)
375 		item->SetMarked(true);
376 }
377 
378 
379 void
380 MethodReplicant::RemoveMethod(BMessage *message)
381 {
382 	CALLED();
383 	int32 cookie;
384 	if (message->FindInt32("cookie", &cookie)!=B_OK) {
385 		fprintf(stderr, "can't find cookie in message\n");
386 		return;
387 	}
388 
389 	MethodMenuItem *item = FindItemByCookie(cookie);
390 	if (item == NULL) {
391 		fprintf(stderr, "can't find item with cookie %lx\n", cookie);
392 		return;
393 	}
394 	fMenu.RemoveItem(item);
395 	delete item;
396 }
397