xref: /haiku/src/kits/interface/Control.cpp (revision 38f832c7eb696038294df0341e08acceca4716b3)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, OpenBeOS
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		Control.cpp
23 //	Author:			Marc Flerackers (mflerackers@androme.be)
24 //	Description:	BControl is the base class for user-event handling objects.
25 //------------------------------------------------------------------------------
26 
27 // Standard Includes -----------------------------------------------------------
28 #include <string.h>
29 #include <malloc.h>
30 
31 // System Includes -------------------------------------------------------------
32 #include <Control.h>
33 #include <PropertyInfo.h>
34 #include <Window.h>
35 #include <Errors.h>
36 
37 // Project Includes ------------------------------------------------------------
38 
39 // Local Includes --------------------------------------------------------------
40 
41 // Local Defines ---------------------------------------------------------------
42 
43 // Globals ---------------------------------------------------------------------
44 static property_info prop_list[] =
45 {
46 	{
47 		"Enabled",
48 		{ B_GET_PROPERTY, 0 },
49 		{ B_DIRECT_SPECIFIER, 0 },
50 		"Returns whether or not the BControl is currently enabled.", 0,
51 		{ B_BOOL_TYPE, 0 }
52 	},
53 	{
54 		"Enabled",
55 		{ B_SET_PROPERTY, 0 },
56 		{ B_DIRECT_SPECIFIER, 0 },
57 		"Enables or disables the BControl.", 0,
58 		{ B_BOOL_TYPE, 0 }
59 	},
60 	{
61 		"Label",
62 		{ B_GET_PROPERTY, 0 },
63 		{ B_DIRECT_SPECIFIER, 0 },
64 		"Returns the BControl's label.", 0,
65 		{ B_STRING_TYPE, 0 }
66 	},
67 	{
68 		"Label",
69 		{ B_SET_PROPERTY, 0 },
70 		{ B_DIRECT_SPECIFIER, 0 },
71 		"Sets the label of the BControl.", 0,
72 		{ B_STRING_TYPE, 0 }
73 	},
74 	{
75 		"Value",
76 		{ B_GET_PROPERTY, 0 },
77 		{ B_DIRECT_SPECIFIER, 0 },
78 		"Returns the BControl's value.", 0,
79 		{ B_INT32_TYPE, 0 }
80 	},
81 	{
82 		"Value",
83 		{ B_SET_PROPERTY, 0 },
84 		{ B_DIRECT_SPECIFIER, 0 },
85 		"Sets the value of the BControl.", 0,
86 		{ B_INT32_TYPE, 0 },
87 	},
88 	{ 0 }
89 };
90 
91 //------------------------------------------------------------------------------
92 BControl::BControl(BRect frame, const char *name, const char *label, BMessage *message,
93 					uint32 resizingMode, uint32 flags)
94 	:	BView(frame, name, resizingMode, flags),
95 		BInvoker(message, NULL),
96 		fValue(B_CONTROL_OFF),
97 		fEnabled(true),
98 		fFocusChanging(false),
99 		fTracking(false),
100 		fWantsNav(true)
101 {
102 	fLabel = strdup(label);
103 }
104 //------------------------------------------------------------------------------
105 BControl::~BControl()
106 {
107 	if (fLabel)
108 		free(fLabel);
109 }
110 //------------------------------------------------------------------------------
111 BControl::BControl(BMessage *archive) : BView(archive)
112 {
113 	const char *label;
114 
115 	if (archive->FindInt32("_val", &fValue) != B_OK)
116 		fValue = B_CONTROL_OFF;
117 
118 	if (archive->FindString("_label", &label) != B_OK)
119 		fLabel = NULL;
120 	else
121 		SetLabel(label);
122 
123 	if ( archive->FindBool("_disable", &fEnabled) != B_OK)
124 		fEnabled = true;
125 	else
126 		fEnabled = !fEnabled;
127 
128 	fFocusChanging = false;
129 	fTracking = false;
130 	fWantsNav = true;
131 
132 	BMessage message;
133 
134 	if (archive->FindMessage("_msg", &message) == B_OK)
135 		SetMessage(new BMessage(message));
136 }
137 //------------------------------------------------------------------------------
138 BArchivable *BControl::Instantiate(BMessage *archive)
139 {
140 	if (validate_instantiation(archive, "BControl"))
141 		return new BControl(archive);
142 	else
143 		return NULL;
144 }
145 //------------------------------------------------------------------------------
146 status_t BControl::Archive(BMessage *archive, bool deep) const
147 {
148 	status_t err = BView::Archive(archive, deep);
149 
150 	if (err != B_OK)
151 		return err;
152 
153 	if (Message())
154 		err = archive->AddMessage("_msg", Message ());
155 
156 	if (err != B_OK)
157 		return err;
158 
159 	if (fLabel)
160 		err = archive->AddString("_label", fLabel);
161 
162 	if (err != B_OK )
163 		return err;
164 
165 	if (fValue != B_CONTROL_OFF)
166 		err = archive->AddInt32("_val", fValue);
167 
168 	if (err != B_OK)
169 		return err;
170 
171 	if (!fEnabled)
172 		err = archive->AddBool("_disable", true);
173 
174 	return err;
175 }
176 //------------------------------------------------------------------------------
177 void BControl::WindowActivated(bool active)
178 {
179 	if (IsFocus())
180 	{
181 		Draw(Bounds());
182 		Flush();
183 	}
184 
185 	BView::WindowActivated(active);
186 }
187 //------------------------------------------------------------------------------
188 void BControl::AttachedToWindow()
189 {
190 	if (Parent())
191 		SetViewColor(Parent()->ViewColor());
192 
193 	if (Target() == NULL)
194 		BInvoker::SetTarget(BMessenger(Window(), NULL));
195 
196 	BView::AttachedToWindow();
197 }
198 //------------------------------------------------------------------------------
199 void BControl::MessageReceived(BMessage *message)
200 {
201 	switch (message->what)
202 	{
203 		case B_CONTROL_INVOKED:
204 			Invoke();
205 			break;
206 
207 		case B_GET_PROPERTY:
208 		case B_SET_PROPERTY:
209 		{
210 			BPropertyInfo propInfo(prop_list);
211 			BMessage specifier;
212 			const char *property;
213 
214 			if (message->GetCurrentSpecifier(NULL, &specifier) != B_OK ||
215 				specifier.FindString("property", &property) != B_OK)
216 				return;
217 
218 			switch (propInfo.FindMatch(message, 0, &specifier, specifier.what, property))
219 			{
220 				case B_ERROR:
221 				{
222 					BView::MessageReceived(message);
223 					break;
224 				}
225 				case 0:
226 				{
227 					BMessage reply;
228 					reply.AddBool("result", fEnabled);
229 					reply.AddBool("error", B_OK);
230 					message->SendReply(&reply);
231 					break;
232 				}
233 				case 1:
234 				{
235 					bool enabled;
236 					message->FindBool("data", &enabled);
237 					SetEnabled(enabled);
238 					break;
239 				}
240 				case 2:
241 				{
242 					BMessage reply;
243 					reply.AddString("result", fLabel);
244 					reply.AddBool("error", B_OK);
245 					message->SendReply(&reply);
246 					break;
247 				}
248 				case 3:
249 				{
250 					const char *label;
251 					message->FindString("data", &label);
252 					SetLabel(label);
253 					break;
254 				}
255 				case 4:
256 				{
257 					BMessage reply;
258 					reply.AddInt32("result", fValue);
259 					reply.AddBool("error", B_OK);
260 					message->SendReply(&reply);
261 					break;
262 				}
263 				case 5:
264 				{
265 					int32 value;
266 					message->FindInt32("data", &value);
267 					SetValue(value);
268 					break;
269 				}
270 			}
271 
272 			break;
273 		}
274 		default:
275 		{
276 			BView::MessageReceived(message);
277 			break;
278 		}
279 	}
280 }
281 //------------------------------------------------------------------------------
282 void BControl::MakeFocus(bool focused)
283 {
284 	BView::MakeFocus(focused);
285 
286  	if(Window())
287 	{
288 		fFocusChanging = true;
289 		Draw(Bounds());
290 		Flush();
291 		fFocusChanging = false;
292 	}
293 }
294 //------------------------------------------------------------------------------
295 void BControl::KeyDown(const char *bytes, int32 numBytes)
296 {
297 	if (numBytes == 1)
298 	{
299 		switch (bytes[0])
300 		{
301 			case B_ENTER:
302 			case B_SPACE:
303 				if (Value())
304 					SetValue(B_CONTROL_OFF);
305 				else
306 					SetValue(B_CONTROL_ON);
307 
308 				BInvoker::Invoke();
309 				break;
310 
311 			default:
312 				BView::KeyDown(bytes, numBytes);
313 		}
314 	}
315 	else
316 		BView::KeyDown(bytes, numBytes);
317 }
318 //------------------------------------------------------------------------------
319 void BControl::MouseDown(BPoint point)
320 {
321 	BView::MouseDown(point);
322 }
323 //------------------------------------------------------------------------------
324 void BControl::MouseUp(BPoint point)
325 {
326 	BView::MouseUp(point);
327 }
328 //------------------------------------------------------------------------------
329 void BControl::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
330 {
331 	BView::MouseMoved(point, transit, message);
332 }
333 //------------------------------------------------------------------------------
334 void BControl::DetachedFromWindow()
335 {
336 	BView::DetachedFromWindow();
337 }
338 //------------------------------------------------------------------------------
339 void BControl::SetLabel(const char *string)
340 {
341 	if (strcmp(fLabel, string) == 0)
342 		return;
343 
344 	if (fLabel)
345 		free(fLabel);
346 
347 	fLabel = strdup(string);
348 
349 	Invalidate();
350 }
351 //------------------------------------------------------------------------------
352 const char *BControl::Label() const
353 {
354 	return fLabel;
355 }
356 //------------------------------------------------------------------------------
357 void BControl::SetValue(int32 value)
358 {
359 	if (fValue == value)
360 		return;
361 
362 	fValue = value;
363 
364  	if (Window())
365 	{
366 		Draw(Bounds());
367 		Flush();
368 	}
369 }
370 //------------------------------------------------------------------------------
371 int32 BControl::Value() const
372 {
373 	return fValue;
374 }
375 //------------------------------------------------------------------------------
376 void BControl::SetEnabled(bool enabled)
377 {
378 	if (fEnabled == enabled)
379 		return;
380 
381 	fEnabled = enabled;
382 
383 	if (fEnabled)
384 		BView::SetFlags(Flags() | B_NAVIGABLE);
385 	else
386 		BView::SetFlags(Flags() & ~B_NAVIGABLE);
387 
388 	if (Window())
389 	{
390 		Draw(Bounds());
391 		Flush();
392 	}
393 }
394 //------------------------------------------------------------------------------
395 bool BControl::IsEnabled() const
396 {
397 	return fEnabled;
398 }
399 //------------------------------------------------------------------------------
400 void BControl::GetPreferredSize(float *width, float *height)
401 {
402 	*width = 1.0f;
403 	*height = 1.0f;
404 }
405 //------------------------------------------------------------------------------
406 void BControl::ResizeToPreferred()
407 {
408 	BView::ResizeToPreferred();
409 }
410 //------------------------------------------------------------------------------
411 status_t BControl::Invoke(BMessage *message)
412 {
413 	if (message)
414 	{
415 		BMessage copy(*message);
416 		copy.AddInt64("when", (int64)system_time());
417 		copy.AddPointer("source", this);
418 		return BInvoker::Invoke(&copy);
419 	}
420 	else if ( Message () )
421 	{
422 		BMessage copy (*Message());
423 		copy.AddInt64 ("when", (int64)system_time());
424 		copy.AddPointer ("source", this);
425 		return BInvoker::Invoke(&copy);
426 	}
427 
428 	return B_BAD_VALUE;
429 }
430 //------------------------------------------------------------------------------
431 BHandler *BControl::ResolveSpecifier(BMessage *message, int32 index,
432 									 BMessage *specifier, int32 what,
433 									 const char *property)
434 {
435 	BPropertyInfo propInfo(prop_list);
436 	BHandler *target = NULL;
437 
438 	switch (propInfo.FindMatch(message, 0, specifier, what, property))
439 	{
440 		case B_ERROR:
441 			break;
442 
443 		case 0:
444 		case 1:
445 		case 2:
446 		case 3:
447 		case 4:
448 		case 5:
449 			target = this;
450 			break;
451 	}
452 
453 	if (!target)
454 		target = BView::ResolveSpecifier(message, index, specifier, what,
455 		property);
456 
457 	return target;
458 }
459 //------------------------------------------------------------------------------
460 status_t BControl::GetSupportedSuites(BMessage *message)
461 {
462 	status_t err;
463 
464 	if (message == NULL)
465 		return B_BAD_VALUE;
466 
467 	err = message->AddString("suites", "suite/vnd.Be-control");
468 
469 	if (err != B_OK)
470 		return err;
471 
472 	BPropertyInfo prop_info(prop_list);
473 	err = message->AddFlat("messages", &prop_info);
474 
475 	if (err != B_OK)
476 		return err;
477 
478 	return BView::GetSupportedSuites(message);
479 }
480 //------------------------------------------------------------------------------
481 void BControl::AllAttached()
482 {
483 	BView::AllAttached();
484 }
485 //------------------------------------------------------------------------------
486 void BControl::AllDetached()
487 {
488 	BView::AllDetached();
489 }
490 //------------------------------------------------------------------------------
491 status_t BControl::Perform(perform_code d, void *arg)
492 {
493 	return B_ERROR;
494 }
495 //------------------------------------------------------------------------------
496 bool BControl::IsFocusChanging() const
497 {
498 	return fFocusChanging;
499 }
500 //------------------------------------------------------------------------------
501 bool BControl::IsTracking() const
502 {
503 	return fTracking;
504 }
505 //------------------------------------------------------------------------------
506 void BControl::SetTracking(bool state)
507 {
508 	fTracking = state;
509 }
510 //------------------------------------------------------------------------------
511 void BControl::SetValueNoUpdate(int32 value)
512 {
513 	fValue = value;
514 }
515 
516 //------------------------------------------------------------------------------
517 void BControl::_ReservedControl1() {}
518 void BControl::_ReservedControl2() {}
519 void BControl::_ReservedControl3() {}
520 void BControl::_ReservedControl4() {}
521 //------------------------------------------------------------------------------
522 BControl &BControl::operator=(const BControl &)
523 {
524 	return *this;
525 }
526 //------------------------------------------------------------------------------
527 void BControl::InitData(BMessage *data)
528 {
529 
530 }
531 //------------------------------------------------------------------------------
532 
533 /*
534  * $Log $
535  *
536  * $Id  $
537  *
538  */
539