xref: /haiku/src/kits/interface/PictureButton.cpp (revision 204dee708a999d5a71d0cb9497650ee7cef85d0a)
1 /*
2  * Copyright 2001-2010, Haiku, Inc.
3  * Distributed under the terms of the MIT license.
4  *
5  * Authors:
6  *		Graham MacDonald (macdonag@btopenworld.com)
7  */
8 
9 #include <PictureButton.h>
10 
11 #include <new>
12 
13 #include <binary_compatibility/Interface.h>
14 
15 
16 BPictureButton::BPictureButton(BRect frame, const char* name,
17 		BPicture* off, BPicture* on, BMessage* message,
18 		uint32 behavior, uint32 resizeMask, uint32 flags)
19 	:
20 	BControl(frame, name, "", message, resizeMask, flags),
21 	fEnabledOff(new(std::nothrow) BPicture(*off)),
22 	fEnabledOn(new(std::nothrow) BPicture(*on)),
23 	fDisabledOff(NULL),
24 	fDisabledOn(NULL),
25 	fBehavior(behavior)
26 {
27 }
28 
29 
30 BPictureButton::BPictureButton(BMessage* data)
31 	:
32 	BControl(data),
33 	fEnabledOff(NULL),
34 	fEnabledOn(NULL),
35 	fDisabledOff(NULL),
36 	fDisabledOn(NULL)
37 {
38 	BMessage pictureArchive;
39 
40 	// Default to 1 state button if not here - is this valid?
41 	if (data->FindInt32 ("_behave", (int32* )&fBehavior) != B_OK)
42 		fBehavior = B_ONE_STATE_BUTTON;
43 
44 	// Now expand the pictures:
45 	if (data->FindMessage("_e_on", &pictureArchive) == B_OK)
46 		fEnabledOn = new(std::nothrow) BPicture(&pictureArchive);
47 
48 	if (data->FindMessage("_e_off", &pictureArchive) == B_OK)
49 		fEnabledOff = new(std::nothrow) BPicture(&pictureArchive);
50 
51 	if (data->FindMessage("_d_on", &pictureArchive) == B_OK)
52 		fDisabledOn = new(std::nothrow) BPicture(&pictureArchive);
53 
54 	if (data->FindMessage("_d_off", &pictureArchive) == B_OK)
55 		fDisabledOff = new(std::nothrow) BPicture(&pictureArchive);
56 }
57 
58 
59 BPictureButton::~BPictureButton()
60 {
61 	delete fEnabledOn;
62 	delete fEnabledOff;
63 	delete fDisabledOn;
64 	delete fDisabledOff;
65 }
66 
67 
68 // #pragma mark -
69 
70 
71 BArchivable*
72 BPictureButton::Instantiate(BMessage* data)
73 {
74 	if ( validate_instantiation(data, "BPictureButton"))
75 		return new (std::nothrow) BPictureButton(data);
76 
77 	return NULL;
78 }
79 
80 
81 status_t
82 BPictureButton::Archive(BMessage* data, bool deep) const
83 {
84 	status_t err = BControl::Archive(data, deep);
85 	if (err != B_OK)
86 		return err;
87 
88 	// Fill out message, depending on whether a deep copy is required or not.
89 	if (deep) {
90 		BMessage pictureArchive;
91 		if (fEnabledOn->Archive(&pictureArchive, deep) == B_OK) {
92 			err = data->AddMessage("_e_on", &pictureArchive);
93 			if (err != B_OK)
94 				return err;
95 		}
96 
97 		pictureArchive.MakeEmpty();
98 		if (fEnabledOff->Archive(&pictureArchive, deep) == B_OK) {
99 			err = data->AddMessage("_e_off", &pictureArchive);
100 			if (err != B_OK)
101 				return err;
102 		}
103 
104 		pictureArchive.MakeEmpty();
105 		if (fDisabledOn && fDisabledOn->Archive(&pictureArchive, deep) == B_OK) {
106 			err = data->AddMessage("_d_on", &pictureArchive);
107 			if (err != B_OK)
108 				return err;
109 		}
110 
111 		pictureArchive.MakeEmpty();
112 		if (fDisabledOff && fDisabledOff->Archive(&pictureArchive, deep) == B_OK) {
113 			err = data->AddMessage("_d_off", &pictureArchive);
114 			if (err != B_OK)
115 				return err;
116 		}
117 	}
118 
119 	return data->AddInt32("_behave", fBehavior);
120 }
121 
122 
123 // #pragma mark -
124 
125 
126 void
127 BPictureButton::AttachedToWindow()
128 {
129 	BControl::AttachedToWindow();
130 }
131 
132 
133 void
134 BPictureButton::DetachedFromWindow()
135 {
136 	BControl::DetachedFromWindow();
137 }
138 
139 
140 void
141 BPictureButton::AllAttached()
142 {
143 	BControl::AllAttached();
144 }
145 
146 
147 void
148 BPictureButton::AllDetached()
149 {
150 	BControl::AllDetached();
151 }
152 
153 
154 // #pragma mark -
155 
156 
157 void
158 BPictureButton::ResizeToPreferred()
159 {
160 	BControl::ResizeToPreferred();
161 }
162 
163 
164 void
165 BPictureButton::GetPreferredSize(float* _width, float* _height)
166 {
167 	BControl::GetPreferredSize(_width, _height);
168 }
169 
170 
171 void
172 BPictureButton::FrameMoved(BPoint newPosition)
173 {
174 	BControl::FrameMoved(newPosition);
175 }
176 
177 
178 void
179 BPictureButton::FrameResized(float newWidth, float newHeight)
180 {
181 	BControl::FrameResized(newWidth, newHeight);
182 }
183 
184 
185 // #pragma mark -
186 
187 
188 void
189 BPictureButton::WindowActivated(bool state)
190 {
191 	BControl::WindowActivated(state);
192 }
193 
194 
195 void
196 BPictureButton::MakeFocus(bool state)
197 {
198 	BControl::MakeFocus(state);
199 }
200 
201 
202 void
203 BPictureButton::Draw(BRect updateRect)
204 {
205 	if (IsEnabled()) {
206 		if (Value() == B_CONTROL_ON)
207 			DrawPicture(fEnabledOn);
208 		else
209 			DrawPicture(fEnabledOff);
210 	} else {
211 
212 		if (fDisabledOff == NULL
213 			|| (fDisabledOn == NULL && fBehavior == B_TWO_STATE_BUTTON))
214 			debugger("Need to set the 'disabled' pictures for this BPictureButton ");
215 
216 		if (Value() == B_CONTROL_ON)
217 			DrawPicture(fDisabledOn);
218 		else
219 			DrawPicture(fDisabledOff);
220 	}
221 
222 	if (IsFocus()) {
223 		SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
224 		StrokeRect(Bounds(), B_SOLID_HIGH);
225 	}
226 }
227 
228 
229 void
230 BPictureButton::MessageReceived(BMessage* msg)
231 {
232 	BControl::MessageReceived(msg);
233 }
234 
235 
236 void
237 BPictureButton::KeyDown(const char* bytes, int32 numBytes)
238 {
239 	if (numBytes == 1) {
240 		switch (bytes[0]) {
241 			case B_ENTER:
242 			case B_SPACE:
243 				if (fBehavior == B_ONE_STATE_BUTTON) {
244 					SetValue(B_CONTROL_ON);
245 					snooze(50000);
246 					SetValue(B_CONTROL_OFF);
247 				} else {
248 					if (Value() == B_CONTROL_ON)
249 						SetValue(B_CONTROL_OFF);
250 					else
251 						SetValue(B_CONTROL_ON);
252 				}
253 				Invoke();
254 				return;
255 		}
256 	}
257 
258 	BControl::KeyDown(bytes, numBytes);
259 }
260 
261 
262 void
263 BPictureButton::MouseDown(BPoint point)
264 {
265 	if (!IsEnabled()) {
266 		BControl::MouseDown(point);
267 		return;
268 	}
269 
270 	SetMouseEventMask(B_POINTER_EVENTS,
271 		B_NO_POINTER_HISTORY | B_SUSPEND_VIEW_FOCUS);
272 
273 	if (fBehavior == B_ONE_STATE_BUTTON) {
274 		SetValue(B_CONTROL_ON);
275 	} else {
276 		if (Value() == B_CONTROL_ON)
277 			SetValue(B_CONTROL_OFF);
278 		else
279 			SetValue(B_CONTROL_ON);
280 	}
281 	SetTracking(true);
282 }
283 
284 
285 void
286 BPictureButton::MouseUp(BPoint point)
287 {
288 	if (IsEnabled() && IsTracking()) {
289 		if (Bounds().Contains(point)) {
290 			if (fBehavior == B_ONE_STATE_BUTTON) {
291 				if (Value() == B_CONTROL_ON) {
292 					snooze(75000);
293 					SetValue(B_CONTROL_OFF);
294 				}
295 			}
296 			Invoke();
297 		}
298 
299 		SetTracking(false);
300 	}
301 }
302 
303 
304 void
305 BPictureButton::MouseMoved(BPoint point, uint32 transit, const BMessage* msg)
306 {
307 	if (IsEnabled() && IsTracking()) {
308 		if (transit == B_EXITED_VIEW)
309 			SetValue(B_CONTROL_OFF);
310 		else if (transit == B_ENTERED_VIEW)
311 			SetValue(B_CONTROL_ON);
312 	} else
313 		BControl::MouseMoved(point, transit, msg);
314 }
315 
316 
317 // #pragma mark -
318 
319 
320 void
321 BPictureButton::SetEnabledOn(BPicture* on)
322 {
323 	delete fEnabledOn;
324 	fEnabledOn = new (std::nothrow) BPicture(*on);
325 }
326 
327 
328 void
329 BPictureButton::SetEnabledOff(BPicture* off)
330 {
331 	delete fEnabledOff;
332 	fEnabledOff = new (std::nothrow) BPicture(*off);
333 }
334 
335 
336 void
337 BPictureButton::SetDisabledOn(BPicture* on)
338 {
339 	delete fDisabledOn;
340 	fDisabledOn = new (std::nothrow) BPicture(*on);
341 }
342 
343 
344 void
345 BPictureButton::SetDisabledOff(BPicture* off)
346 {
347 	delete fDisabledOff;
348 	fDisabledOff = new (std::nothrow) BPicture(*off);
349 }
350 
351 
352 BPicture*
353 BPictureButton::EnabledOn() const
354 {
355 	return fEnabledOn;
356 }
357 
358 
359 BPicture*
360 BPictureButton::EnabledOff() const
361 {
362 	return fEnabledOff;
363 }
364 
365 
366 BPicture*
367 BPictureButton::DisabledOn() const
368 {
369 	return fDisabledOn;
370 }
371 
372 
373 BPicture*
374 BPictureButton::DisabledOff() const
375 {
376 	return fDisabledOff;
377 }
378 
379 
380 void
381 BPictureButton::SetBehavior(uint32 behavior)
382 {
383 	fBehavior = behavior;
384 }
385 
386 
387 uint32
388 BPictureButton::Behavior() const
389 {
390 	return fBehavior;
391 }
392 
393 
394 void
395 BPictureButton::SetValue(int32 value)
396 {
397 	BControl::SetValue(value);
398 }
399 
400 
401 status_t
402 BPictureButton::Invoke(BMessage* msg)
403 {
404 	return BControl::Invoke(msg);
405 }
406 
407 
408 BHandler*
409 BPictureButton::ResolveSpecifier(BMessage* msg, int32 index,
410 	BMessage* specifier, int32 form, const char* property)
411 {
412 	return BControl::ResolveSpecifier(msg, index, specifier, form, property);
413 }
414 
415 
416 status_t
417 BPictureButton::GetSupportedSuites(BMessage* data)
418 {
419 	return BControl::GetSupportedSuites(data);
420 }
421 
422 
423 status_t
424 BPictureButton::Perform(perform_code code, void* _data)
425 {
426 	switch (code) {
427 		case PERFORM_CODE_MIN_SIZE:
428 			((perform_data_min_size*)_data)->return_value
429 				= BPictureButton::MinSize();
430 			return B_OK;
431 		case PERFORM_CODE_MAX_SIZE:
432 			((perform_data_max_size*)_data)->return_value
433 				= BPictureButton::MaxSize();
434 			return B_OK;
435 		case PERFORM_CODE_PREFERRED_SIZE:
436 			((perform_data_preferred_size*)_data)->return_value
437 				= BPictureButton::PreferredSize();
438 			return B_OK;
439 		case PERFORM_CODE_LAYOUT_ALIGNMENT:
440 			((perform_data_layout_alignment*)_data)->return_value
441 				= BPictureButton::LayoutAlignment();
442 			return B_OK;
443 		case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
444 			((perform_data_has_height_for_width*)_data)->return_value
445 				= BPictureButton::HasHeightForWidth();
446 			return B_OK;
447 		case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
448 		{
449 			perform_data_get_height_for_width* data
450 				= (perform_data_get_height_for_width*)_data;
451 			BPictureButton::GetHeightForWidth(data->width, &data->min, &data->max,
452 				&data->preferred);
453 			return B_OK;
454 		}
455 		case PERFORM_CODE_SET_LAYOUT:
456 		{
457 			perform_data_set_layout* data = (perform_data_set_layout*)_data;
458 			BPictureButton::SetLayout(data->layout);
459 			return B_OK;
460 		}
461 		case PERFORM_CODE_LAYOUT_INVALIDATED:
462 		{
463 			perform_data_layout_invalidated* data
464 				= (perform_data_layout_invalidated*)_data;
465 			BPictureButton::LayoutInvalidated(data->descendants);
466 			return B_OK;
467 		}
468 		case PERFORM_CODE_DO_LAYOUT:
469 		{
470 			BPictureButton::DoLayout();
471 			return B_OK;
472 		}
473 	}
474 
475 	return BControl::Perform(code, _data);
476 }
477 
478 
479 // #pragma mark -
480 
481 
482 void BPictureButton::_ReservedPictureButton1() {}
483 void BPictureButton::_ReservedPictureButton2() {}
484 void BPictureButton::_ReservedPictureButton3() {}
485 
486 
487 BPictureButton&
488 BPictureButton::operator=(const BPictureButton &button)
489 {
490 	return *this;
491 }
492 
493