xref: /haiku/src/kits/interface/PictureButton.cpp (revision 94fb5d40964b0046ecd2bbaa8f4cdc836b539019)
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:		PictureButton.cpp
23 //	Author:			Graham MacDonald (macdonag@btopenworld.com)
24 //	Description:	BPictureButton displays and controls a picture button in a
25 //					window.
26 //------------------------------------------------------------------------------
27 
28 // Standard Includes -----------------------------------------------------------
29 
30 // System Includes -------------------------------------------------------------
31 #include <PictureButton.h>
32 
33 
34 // Project Includes ------------------------------------------------------------
35 
36 // Local Includes --------------------------------------------------------------
37 
38 // Local Defines ---------------------------------------------------------------
39 
40 // Globals ---------------------------------------------------------------------
41 
42 //------------------------------------------------------------------------------
43 BPictureButton::BPictureButton (BRect frame,
44 								const char* name,
45 								BPicture *off,
46 								BPicture *on,
47 								BMessage *message,
48 								uint32 behavior = B_ONE_STATE_BUTTON,
49 								uint32 resizeMask = B_FOLLOW_LEFT | B_FOLLOW_TOP,
50 								uint32 flgs = B_WILL_DRAW | B_NAVIGABLE)
51 	: BControl (frame, name, "", message, resizeMask, flgs), fOutlined (false),
52 	  fBehavior (behavior)
53 {
54 	fEnabledOff = new BPicture(*off);
55 	fEnabledOn = new BPicture(*on);
56 	fDisabledOff = NULL;
57 	fDisabledOn = NULL;
58 }
59 
60 
61 /***********************************************************************
62  *  Method: BPictureButton::BPictureButton
63  *  Params: BMessage *data
64  * Effects:
65  ***********************************************************************/
66 BPictureButton::BPictureButton(BMessage *data) : BControl (data)
67 {
68 	BMessage pictureArchive;
69 
70 	// Default to 1 state button if not here - is this valid?
71 	if (data->FindInt32 ("_behave", (int32 *)&fBehavior ) != B_OK )
72 	{
73 		fBehavior = B_ONE_STATE_BUTTON;
74 	}
75 
76 	// Now expand the pictures:
77 	if (data->FindMessage("_e_on", &pictureArchive) == B_OK)
78 	{
79 		fEnabledOn = new BPicture(&pictureArchive);
80 	}
81 	if (data->FindMessage("_e_off", &pictureArchive) == B_OK)
82 	{
83 		fEnabledOff = new BPicture(&pictureArchive);
84 	}
85 
86 	if (fBehavior == B_TWO_STATE_BUTTON)
87 	{
88 		if (data->FindMessage("_d_on", &pictureArchive) == B_OK)
89 		{
90 			fDisabledOn = new BPicture(&pictureArchive);
91 		}
92 		if (data->FindMessage("_d_off", &pictureArchive) == B_OK)
93 		{
94 			fDisabledOff = new BPicture(&pictureArchive);
95 		}
96 	}
97 	else
98 	{
99 		fDisabledOn = fDisabledOff = NULL;
100 	}
101 }
102 
103 
104 /***********************************************************************
105  *  Method: BPictureButton::~BPictureButton
106  *  Params:
107  * Effects:
108  ***********************************************************************/
109 BPictureButton::~BPictureButton()
110 {
111 	delete fEnabledOn;
112 	delete fEnabledOff;
113 
114 	if (fBehavior == B_TWO_STATE_BUTTON)
115 	{
116 		delete fDisabledOn;
117 		delete fDisabledOff;
118 	}
119 }
120 
121 
122 /***********************************************************************
123  *  Method: BPictureButton::Instantiate
124  *  Params: BMessage *data
125  * Returns: BArchivable *
126  * Effects:
127  ***********************************************************************/
128 BArchivable *
129 BPictureButton::Instantiate (BMessage *data)
130 {
131 	// Do we ned to take into account deep copy of images?  I guess so!
132 	if ( validate_instantiation(data, "BPictureButton"))
133 	{
134 		return new BPictureButton(data);
135 	}
136 	else
137 	{
138 		return NULL;
139 	}
140 }
141 
142 
143 /***********************************************************************
144  *  Method: BPictureButton::Archive
145  *  Params: BMessage *data, bool deep
146  * Returns: status_t
147  * Effects:
148  ***********************************************************************/
149 status_t
150 BPictureButton::Archive (BMessage *data, bool deep) const
151 {
152 	status_t err = BControl::Archive(data, deep);
153 
154 	if (err != B_OK) return err;
155 
156 	// Do we need this?  Good practice!
157 	err = data->AddString("class", "BPictureButton");
158 
159 	if (err != B_OK) return err;
160 
161 	// Fill out message, depending on whether a deep copy is required or not.
162 	if (deep)
163 	{
164 		BMessage pictureArchive;
165 
166 		if (fEnabledOn->Archive(&pictureArchive, deep) == B_OK)
167 		{
168 			err = data->AddMessage("_e_on", &pictureArchive);
169 			if (err != B_OK) return err;
170 		}
171 
172 		if (fEnabledOff->Archive(&pictureArchive, deep) == B_OK)
173 		{
174 			err = data->AddMessage("_e_off", &pictureArchive);
175 			if (err != B_OK) return err;
176 		}
177 
178 		// Do we add messages for pictures that don't exist?
179 		if (fBehavior == B_TWO_STATE_BUTTON)
180 		{
181 			if (fDisabledOn->Archive(&pictureArchive, deep) == B_OK)
182 			{
183 				err = data->AddMessage("_d_on", &pictureArchive);
184 				if (err != B_OK) return err;
185 			}
186 
187 			if (fDisabledOff->Archive(&pictureArchive, deep) == B_OK)
188 			{
189 				err = data->AddMessage("_d_off", &pictureArchive);
190 				if (err != B_OK) return err;
191 			}
192 		}
193 	}
194 
195 	err = data->AddInt32("_behave", fBehavior);
196 
197 	return err;
198 }
199 
200 
201 /***********************************************************************
202  *  Method: BPictureButton::Draw
203  *  Params: BRect updateRect
204  * Returns: void
205  * Effects:
206  ***********************************************************************/
207 void
208 BPictureButton::Draw (BRect updateRect)
209 {
210 	BRect rect = Bounds();
211 
212 	// Need to check if TWO_STATE, if setEnabled=false, and if diabled picture is null
213 	// If so, and in debug, bring up an Alert, if so, and not in debug, output to stdout
214 
215 	// We should request the view's base color which normaly is (216,216,216)
216 	rgb_color color = ui_color(B_PANEL_BACKGROUND_COLOR);
217 
218 	if (fBehavior == B_ONE_STATE_BUTTON)
219 	{
220 		if (BControl::Value() == B_CONTROL_ON)
221 		{
222 			BView::DrawPicture(fEnabledOn);
223 		}
224 		else
225 		{
226 			BView::DrawPicture(fEnabledOff);
227 		}
228 	}
229 	else		// Must be B_TWO_STATE_BUTTON:
230 	{
231 		if (BControl::IsEnabled())
232 		{
233 			if (BControl::Value() == B_CONTROL_ON)
234 			{
235 				BView::DrawPicture(fEnabledOn);
236 			}
237 			else
238 			{
239 				BView::DrawPicture(fEnabledOff);
240 			}
241 		}
242 		else		// Must be Disabled:
243 		{
244 			if (BControl::Value() == B_CONTROL_ON)
245 			{
246 				if (fDisabledOn == NULL)
247 				{
248 					debugger("Need to set the 'disabled' pictures for this BPictureButton ");
249 				}
250 				BView::DrawPicture(fDisabledOn);
251 			}
252 			else
253 			{
254 				if (fDisabledOn == NULL)
255 				{
256 					debugger("Need to set the 'disabled' pictures for this BPictureButton ");
257 				}
258 				BView::DrawPicture(fDisabledOff);
259 			}
260 		}
261 	}
262 
263 	if (IsFocus())
264 	{
265 		SetHighColor( ui_color(B_KEYBOARD_NAVIGATION_COLOR) );
266 		StrokeRect(rect, B_SOLID_HIGH);
267 	}
268 }
269 
270 
271 /***********************************************************************
272  *  Method: BPictureButton::MouseDown
273  *  Params: BPoint where
274  * Returns: void
275  * Effects:
276  ***********************************************************************/
277 void
278 BPictureButton::MouseDown (BPoint point)
279 {
280 	if (!IsEnabled())
281 	{
282 		BControl::MouseDown(point);
283 		return;
284 	}
285 
286 	SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY | B_SUSPEND_VIEW_FOCUS);
287 
288 	if (fBehavior == B_ONE_STATE_BUTTON)
289 	{
290 		SetValue(B_CONTROL_ON);
291 	}
292 	else
293 	{
294 		if (Value() == B_CONTROL_ON)
295 		{
296 			SetValue(B_CONTROL_OFF);
297 		}
298 		else
299 		{
300 			SetValue(B_CONTROL_ON);
301 		}
302 	}
303 	SetTracking(true);
304 }
305 
306 
307 /***********************************************************************
308  *  Method: BPictureButton::MouseUp
309  *  Params: BPoint pt
310  * Returns: void
311  * Effects:
312  ***********************************************************************/
313 void
314 BPictureButton::MouseUp (BPoint point)
315 {
316 	if (IsEnabled() && IsTracking())
317 	{
318 		if (Bounds().Contains(point))
319 		{
320 			if (fBehavior == B_ONE_STATE_BUTTON)
321 			{
322 				if (Value() == B_CONTROL_ON)
323 				{
324 					snooze(75000);
325 					SetValue(B_CONTROL_OFF);
326 				}
327 			}
328 			BControl::Invoke();
329 		}
330 
331 		SetTracking(false);
332 	}
333 }
334 
335 
336 /***********************************************************************
337  *  Method: BPictureButton::MouseMoved
338  *  Params: BPoint pt, uint32 code, const BMessage *msg
339  * Returns: void
340  * Effects:
341  ***********************************************************************/
342 void
343 BPictureButton::MouseMoved (BPoint pt, uint32 code, const BMessage *msg)
344 {
345 	if (IsEnabled() && IsTracking())
346 	{
347 		if (code == B_EXITED_VIEW)
348 			SetValue(B_CONTROL_OFF);
349 		else if (code == B_ENTERED_VIEW)
350 			SetValue(B_CONTROL_ON);
351 	}
352 	else
353 	{
354 		BControl::MouseMoved(pt, code, msg);
355 	}
356 }
357 
358 
359 /***********************************************************************
360  *  Method: BPictureButton::KeyDown
361  *  Params: const char *bytes, int32 numBytes
362  * Returns: void
363  * Effects:
364  ***********************************************************************/
365 void
366 BPictureButton::KeyDown (const char *bytes, int32 numBytes)
367 {
368 	if (numBytes == 1)
369 	{
370 		switch (bytes[0])
371 		{
372 			case B_ENTER:
373 			case B_SPACE:
374 				if (fBehavior == B_ONE_STATE_BUTTON)
375 				{
376 					SetValue(B_CONTROL_ON);
377 					snooze(50000);
378 					SetValue(B_CONTROL_OFF);
379 				}
380 				else
381 				{
382 					if (Value() == B_CONTROL_ON)
383 					{
384 						SetValue(B_CONTROL_OFF);
385 					}
386 					else
387 					{
388 						SetValue(B_CONTROL_ON);
389 					}
390 				}
391 				Invoke();
392 				break;
393 
394 			default:
395 				BControl::KeyDown(bytes, numBytes);
396 		}
397 	}
398 	else
399 	{
400 		BControl::KeyDown(bytes, numBytes);
401 	}
402 }
403 
404 
405 /***********************************************************************
406  *  Method: BPictureButton::SetEnabledOn
407  *  Params: BPicture *on
408  * Returns: void
409  * Effects:
410  ***********************************************************************/
411 void
412 BPictureButton::SetEnabledOn (BPicture *on)
413 {
414 	if (!fEnabledOn)
415 	{
416 		delete fEnabledOn;
417 	}
418 	fEnabledOn = new BPicture (*on);
419 }
420 
421 
422 /***********************************************************************
423  *  Method: BPictureButton::SetEnabledOff
424  *  Params: BPicture *off
425  * Returns: void
426  * Effects:
427  ***********************************************************************/
428 void
429 BPictureButton::SetEnabledOff (BPicture *off)
430 {
431 	if (!fEnabledOff)
432 	{
433 		delete fEnabledOff;
434 	}
435 	fEnabledOff = new BPicture (*off);
436 }
437 
438 
439 /***********************************************************************
440  *  Method: BPictureButton::SetDisabledOn
441  *  Params: BPicture *on
442  * Returns: void
443  * Effects:
444  ***********************************************************************/
445 void
446 BPictureButton::SetDisabledOn (BPicture *on)
447 {
448 	if (!fDisabledOn)
449 	{
450 		delete fDisabledOn;
451 	}
452 	fDisabledOn = new BPicture (*on);
453 }
454 
455 
456 /***********************************************************************
457  *  Method: BPictureButton::SetDisabledOff
458  *  Params: BPicture *off
459  * Returns: void
460  * Effects:
461  ***********************************************************************/
462 void
463 BPictureButton::SetDisabledOff (BPicture *off)
464 {
465 	if (!fDisabledOff)
466 	{
467 		delete fDisabledOff;
468 	}
469 	fDisabledOff = new BPicture (*off);
470 }
471 
472 
473 /***********************************************************************
474  *  Method: BPictureButton::EnabledOn
475  *  Params:
476  * Returns: BPicture *
477  * Effects:
478  ***********************************************************************/
479 BPicture *
480 BPictureButton::EnabledOn () const
481 {
482 	return fEnabledOn;
483 }
484 
485 
486 /***********************************************************************
487  *  Method: BPictureButton::EnabledOff
488  *  Params:
489  * Returns: BPicture *
490  * Effects:
491  ***********************************************************************/
492 BPicture *
493 BPictureButton::EnabledOff () const
494 {
495 	return fEnabledOff;
496 }
497 
498 
499 /***********************************************************************
500  *  Method: BPictureButton::DisabledOn
501  *  Params:
502  * Returns: BPicture *
503  * Effects:
504  ***********************************************************************/
505 BPicture *
506 BPictureButton::DisabledOn () const
507 {
508 	return fDisabledOn;
509 }
510 
511 
512 /***********************************************************************
513  *  Method: BPictureButton::DisabledOff
514  *  Params:
515  * Returns: BPicture *
516  * Effects:
517  ***********************************************************************/
518 BPicture *
519 BPictureButton::DisabledOff() const
520 {
521 	return fDisabledOff;
522 }
523 
524 
525 /***********************************************************************
526  *  Method: BPictureButton::SetBehavior
527  *  Params: uint32 behavior
528  * Returns: void
529  * Effects:
530  ***********************************************************************/
531 void
532 BPictureButton::SetBehavior (uint32 behavior)
533 {
534 	fBehavior = behavior;
535 }
536 
537 
538 /***********************************************************************
539  *  Method: BPictureButton::Behavior
540  *  Params:
541  * Returns: uint32
542  * Effects:
543  ***********************************************************************/
544 uint32
545 BPictureButton::Behavior () const
546 {
547 	return fBehavior;
548 }
549 
550 
551 /***********************************************************************
552  *  Method: BPictureButton::MessageReceived
553  *  Params: BMessage *msg
554  * Returns: void
555  * Effects:
556  ***********************************************************************/
557 void
558 BPictureButton::MessageReceived (BMessage *msg)
559 {
560 	BControl::MessageReceived(msg);
561 }
562 
563 
564 /***********************************************************************
565  *  Method: BPictureButton::WindowActivated
566  *  Params: bool state
567  * Returns: void
568  * Effects:
569  ***********************************************************************/
570 void
571 BPictureButton::WindowActivated (bool state)
572 {
573 	BView::WindowActivated (state);
574 }
575 
576 
577 /***********************************************************************
578  *  Method: BPictureButton::AttachedToWindow
579  *  Params:
580  * Returns: void
581  * Effects:
582  ***********************************************************************/
583 void
584 BPictureButton::AttachedToWindow ()
585 {
586 	BControl::AttachedToWindow();
587 }
588 
589 
590 /***********************************************************************
591  *  Method: BPictureButton::DetachedFromWindow
592  *  Params:
593  * Returns: void
594  * Effects:
595  ***********************************************************************/
596 void
597 BPictureButton::DetachedFromWindow ()
598 {
599 	BView::DetachedFromWindow();
600 }
601 
602 
603 /***********************************************************************
604  *  Method: BPictureButton::SetValue
605  *  Params: int32 value
606  * Returns: void
607  * Effects:
608  ***********************************************************************/
609 void
610 BPictureButton::SetValue (int32 value)
611 {
612 	BControl::SetValue(value);
613 }
614 
615 
616 /***********************************************************************
617  *  Method: BPictureButton::Invoke
618  *  Params: BMessage *msg
619  * Returns: status_t
620  * Effects:
621  ***********************************************************************/
622 status_t
623 BPictureButton::Invoke (BMessage *msg)
624 {
625 	return BControl::Invoke(msg);
626 }
627 
628 
629 /***********************************************************************
630  *  Method: BPictureButton::FrameMoved
631  *  Params: BPoint new_position
632  * Returns: void
633  * Effects:
634  ***********************************************************************/
635 void
636 BPictureButton::FrameMoved (BPoint new_position)
637 {
638 	BView::FrameMoved (new_position);
639 }
640 
641 
642 /***********************************************************************
643  *  Method: BPictureButton::FrameResized
644  *  Params: float new_width, float new_height
645  * Returns: void
646  * Effects:
647  ***********************************************************************/
648 void
649 BPictureButton::FrameResized (float new_width, float new_height)
650 {
651 	BView::FrameResized (new_width, new_height);
652 }
653 
654 
655 /***********************************************************************
656  *  Method: BPictureButton::ResolveSpecifier
657  *  Params: BMessage *msg, int32 index, BMessage *specifier, int32 form, const char *property
658  * Returns: BHandler *
659  * Effects:
660  ***********************************************************************/
661 BHandler *
662 BPictureButton::ResolveSpecifier (BMessage *msg, int32 index, BMessage *specifier, int32 form, const char *property)
663 {
664 	return BControl::ResolveSpecifier(msg, index, specifier, form, property);
665 }
666 
667 
668 /***********************************************************************
669  *  Method: BPictureButton::GetSupportedSuites
670  *  Params: BMessage *data
671  * Returns: status_t
672  * Effects:
673  ***********************************************************************/
674 status_t
675 BPictureButton::GetSupportedSuites (BMessage *data)
676 {
677 	return BControl::GetSupportedSuites(data);
678 }
679 
680 
681 /***********************************************************************
682  *  Method: BPictureButton::ResizeToPreferred
683  *  Params:
684  * Returns: void
685  * Effects:
686  ***********************************************************************/
687 void
688 BPictureButton::ResizeToPreferred ()
689 {
690 	float w, h;
691 	GetPreferredSize (&w, &h);
692 	BView::ResizeTo (w,h);
693 }
694 
695 
696 /***********************************************************************
697  *  Method: BPictureButton::GetPreferredSize
698  *  Params: float *width, float *height
699  * Returns: void
700  * Effects:
701  ***********************************************************************/
702 void
703 BPictureButton::GetPreferredSize (float *width, float *height)
704 {
705 	// Need to do some test to see what the Be method returns...
706 }
707 
708 
709 /***********************************************************************
710  *  Method: BPictureButton::MakeFocus
711  *  Params: bool state
712  * Returns: void
713  * Effects:
714  ***********************************************************************/
715 void
716 BPictureButton::MakeFocus (bool state)
717 {
718 	BControl::MakeFocus(state);
719 }
720 
721 
722 /***********************************************************************
723  *  Method: BPictureButton::AllAttached
724  *  Params:
725  * Returns: void
726  * Effects:
727  ***********************************************************************/
728 void
729 BPictureButton::AllAttached ()
730 {
731 	BView::AllAttached();
732 }
733 
734 
735 /***********************************************************************
736  *  Method: BPictureButton::AllDetached
737  *  Params:
738  * Returns: void
739  * Effects:
740  ***********************************************************************/
741 void
742 BPictureButton::AllDetached ()
743 {
744 	BView::AllDetached();
745 }
746 
747 
748 /***********************************************************************
749  *  Method: BPictureButton::Perform
750  *  Params: perform_code d, void *arg
751  * Returns: status_t
752  * Effects:
753  ***********************************************************************/
754 status_t
755 BPictureButton::Perform (perform_code d, void *arg)
756 {
757 	// Really clutching at straws here....
758 	return B_ERROR;
759 }
760 
761 
762 /***********************************************************************
763  *  Method: BPictureButton::_ReservedPictureButton1
764  *  Params:
765  * Returns: void
766  * Effects:
767  ***********************************************************************/
768 void
769 BPictureButton::_ReservedPictureButton1 ()
770 {
771 }
772 
773 
774 /***********************************************************************
775  *  Method: BPictureButton::_ReservedPictureButton2
776  *  Params:
777  * Returns: void
778  * Effects:
779  ***********************************************************************/
780 void
781 BPictureButton::_ReservedPictureButton2()
782 {
783 }
784 
785 
786 /***********************************************************************
787  *  Method: BPictureButton::_ReservedPictureButton3
788  *  Params:
789  * Returns: void
790  * Effects:
791  ***********************************************************************/
792 void
793 BPictureButton::_ReservedPictureButton3()
794 {
795 }
796 
797 
798 /***********************************************************************
799  *  Method: BPictureButton::operator=
800  *  Params: const BPictureButton &
801  * Returns: BPictureButton &
802  * Effects:
803  ***********************************************************************/
804 BPictureButton &
805 BPictureButton::operator=(const BPictureButton &button)
806 {
807 	return *this;
808 }
809 
810 
811 /***********************************************************************
812  *  Method: BPictureButton::Redraw
813  *  Params:
814  * Returns: void
815  * Effects:
816  ***********************************************************************/
817 void
818 BPictureButton::Redraw()
819 {
820 }
821 
822 
823 /***********************************************************************
824  *  Method: BPictureButton::InitData
825  *  Params:
826  * Returns: void
827  * Effects:
828  ***********************************************************************/
829 void
830 BPictureButton::InitData()
831 {
832 }
833 
834