xref: /haiku/src/kits/interface/PictureButton.cpp (revision 2c704682c473cd9e0f4b10d91c072f200e740cd8)
1 /*
2  * Copyright 2001-2009, 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 
92 		if (fEnabledOn->Archive(&pictureArchive, deep) == B_OK) {
93 			err = data->AddMessage("_e_on", &pictureArchive);
94 			if (err != B_OK)
95 				return err;
96 		}
97 
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 		if (fDisabledOn && fDisabledOn->Archive(&pictureArchive, deep) == B_OK) {
105 			err = data->AddMessage("_d_on", &pictureArchive);
106 			if (err != B_OK)
107 				return err;
108 		}
109 
110 		if (fDisabledOff && fDisabledOff->Archive(&pictureArchive, deep) == B_OK) {
111 			err = data->AddMessage("_d_off", &pictureArchive);
112 			if (err != B_OK)
113 				return err;
114 		}
115 	}
116 
117 	return data->AddInt32("_behave", fBehavior);
118 }
119 
120 
121 // #pragma mark -
122 
123 
124 void
125 BPictureButton::AttachedToWindow()
126 {
127 	BControl::AttachedToWindow();
128 }
129 
130 
131 void
132 BPictureButton::DetachedFromWindow()
133 {
134 	BControl::DetachedFromWindow();
135 }
136 
137 
138 void
139 BPictureButton::AllAttached()
140 {
141 	BControl::AllAttached();
142 }
143 
144 
145 void
146 BPictureButton::AllDetached()
147 {
148 	BControl::AllDetached();
149 }
150 
151 
152 // #pragma mark -
153 
154 
155 void
156 BPictureButton::ResizeToPreferred()
157 {
158 	BControl::ResizeToPreferred();
159 }
160 
161 
162 void
163 BPictureButton::GetPreferredSize(float* _width, float* _height)
164 {
165 	BControl::GetPreferredSize(_width, _height);
166 }
167 
168 
169 void
170 BPictureButton::FrameMoved(BPoint newPosition)
171 {
172 	BControl::FrameMoved(newPosition);
173 }
174 
175 
176 void
177 BPictureButton::FrameResized(float newWidth, float newHeight)
178 {
179 	BControl::FrameResized(newWidth, newHeight);
180 }
181 
182 
183 // #pragma mark -
184 
185 
186 void
187 BPictureButton::WindowActivated(bool state)
188 {
189 	BControl::WindowActivated(state);
190 }
191 
192 
193 void
194 BPictureButton::MakeFocus(bool state)
195 {
196 	BControl::MakeFocus(state);
197 }
198 
199 
200 void
201 BPictureButton::Draw(BRect updateRect)
202 {
203 	if (IsEnabled()) {
204 		if (Value() == B_CONTROL_ON)
205 			DrawPicture(fEnabledOn);
206 		else
207 			DrawPicture(fEnabledOff);
208 	} else {
209 
210 		if (fDisabledOff == NULL
211 			|| (fDisabledOn == NULL && fBehavior == B_TWO_STATE_BUTTON))
212 			debugger("Need to set the 'disabled' pictures for this BPictureButton ");
213 
214 		if (Value() == B_CONTROL_ON)
215 			DrawPicture(fDisabledOn);
216 		else
217 			DrawPicture(fDisabledOff);
218 	}
219 
220 	if (IsFocus()) {
221 		SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
222 		StrokeRect(Bounds(), B_SOLID_HIGH);
223 	}
224 }
225 
226 
227 void
228 BPictureButton::MessageReceived(BMessage* msg)
229 {
230 	BControl::MessageReceived(msg);
231 }
232 
233 
234 void
235 BPictureButton::KeyDown(const char* bytes, int32 numBytes)
236 {
237 	if (numBytes == 1) {
238 		switch (bytes[0]) {
239 			case B_ENTER:
240 			case B_SPACE:
241 				if (fBehavior == B_ONE_STATE_BUTTON) {
242 					SetValue(B_CONTROL_ON);
243 					snooze(50000);
244 					SetValue(B_CONTROL_OFF);
245 				} else {
246 					if (Value() == B_CONTROL_ON)
247 						SetValue(B_CONTROL_OFF);
248 					else
249 						SetValue(B_CONTROL_ON);
250 				}
251 				Invoke();
252 				return;
253 		}
254 	}
255 
256 	BControl::KeyDown(bytes, numBytes);
257 }
258 
259 
260 void
261 BPictureButton::MouseDown(BPoint point)
262 {
263 	if (!IsEnabled()) {
264 		BControl::MouseDown(point);
265 		return;
266 	}
267 
268 	SetMouseEventMask(B_POINTER_EVENTS,
269 		B_NO_POINTER_HISTORY | B_SUSPEND_VIEW_FOCUS);
270 
271 	if (fBehavior == B_ONE_STATE_BUTTON) {
272 		SetValue(B_CONTROL_ON);
273 	} else {
274 		if (Value() == B_CONTROL_ON)
275 			SetValue(B_CONTROL_OFF);
276 		else
277 			SetValue(B_CONTROL_ON);
278 	}
279 	SetTracking(true);
280 }
281 
282 
283 void
284 BPictureButton::MouseUp(BPoint point)
285 {
286 	if (IsEnabled() && IsTracking()) {
287 		if (Bounds().Contains(point)) {
288 			if (fBehavior == B_ONE_STATE_BUTTON) {
289 				if (Value() == B_CONTROL_ON) {
290 					snooze(75000);
291 					SetValue(B_CONTROL_OFF);
292 				}
293 			}
294 			Invoke();
295 		}
296 
297 		SetTracking(false);
298 	}
299 }
300 
301 
302 void
303 BPictureButton::MouseMoved(BPoint point, uint32 transit, const BMessage* msg)
304 {
305 	if (IsEnabled() && IsTracking()) {
306 		if (transit == B_EXITED_VIEW)
307 			SetValue(B_CONTROL_OFF);
308 		else if (transit == B_ENTERED_VIEW)
309 			SetValue(B_CONTROL_ON);
310 	} else
311 		BControl::MouseMoved(point, transit, msg);
312 }
313 
314 
315 // #pragma mark -
316 
317 
318 void
319 BPictureButton::SetEnabledOn(BPicture* on)
320 {
321 	delete fEnabledOn;
322 	fEnabledOn = new (std::nothrow) BPicture(*on);
323 }
324 
325 
326 void
327 BPictureButton::SetEnabledOff(BPicture* off)
328 {
329 	delete fEnabledOff;
330 	fEnabledOff = new (std::nothrow) BPicture(*off);
331 }
332 
333 
334 void
335 BPictureButton::SetDisabledOn(BPicture* on)
336 {
337 	delete fDisabledOn;
338 	fDisabledOn = new (std::nothrow) BPicture(*on);
339 }
340 
341 
342 void
343 BPictureButton::SetDisabledOff(BPicture* off)
344 {
345 	delete fDisabledOff;
346 	fDisabledOff = new (std::nothrow) BPicture(*off);
347 }
348 
349 
350 BPicture*
351 BPictureButton::EnabledOn() const
352 {
353 	return fEnabledOn;
354 }
355 
356 
357 BPicture*
358 BPictureButton::EnabledOff() const
359 {
360 	return fEnabledOff;
361 }
362 
363 
364 BPicture*
365 BPictureButton::DisabledOn() const
366 {
367 	return fDisabledOn;
368 }
369 
370 
371 BPicture*
372 BPictureButton::DisabledOff() const
373 {
374 	return fDisabledOff;
375 }
376 
377 
378 void
379 BPictureButton::SetBehavior(uint32 behavior)
380 {
381 	fBehavior = behavior;
382 }
383 
384 
385 uint32
386 BPictureButton::Behavior() const
387 {
388 	return fBehavior;
389 }
390 
391 
392 void
393 BPictureButton::SetValue(int32 value)
394 {
395 	BControl::SetValue(value);
396 }
397 
398 
399 status_t
400 BPictureButton::Invoke(BMessage* msg)
401 {
402 	return BControl::Invoke(msg);
403 }
404 
405 
406 BHandler*
407 BPictureButton::ResolveSpecifier(BMessage* msg, int32 index,
408 	BMessage* specifier, int32 form, const char* property)
409 {
410 	return BControl::ResolveSpecifier(msg, index, specifier, form, property);
411 }
412 
413 
414 status_t
415 BPictureButton::GetSupportedSuites(BMessage* data)
416 {
417 	return BControl::GetSupportedSuites(data);
418 }
419 
420 
421 status_t
422 BPictureButton::Perform(perform_code code, void* _data)
423 {
424 	switch (code) {
425 		case PERFORM_CODE_MIN_SIZE:
426 			((perform_data_min_size*)_data)->return_value
427 				= BPictureButton::MinSize();
428 			return B_OK;
429 		case PERFORM_CODE_MAX_SIZE:
430 			((perform_data_max_size*)_data)->return_value
431 				= BPictureButton::MaxSize();
432 			return B_OK;
433 		case PERFORM_CODE_PREFERRED_SIZE:
434 			((perform_data_preferred_size*)_data)->return_value
435 				= BPictureButton::PreferredSize();
436 			return B_OK;
437 		case PERFORM_CODE_LAYOUT_ALIGNMENT:
438 			((perform_data_layout_alignment*)_data)->return_value
439 				= BPictureButton::LayoutAlignment();
440 			return B_OK;
441 		case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
442 			((perform_data_has_height_for_width*)_data)->return_value
443 				= BPictureButton::HasHeightForWidth();
444 			return B_OK;
445 		case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
446 		{
447 			perform_data_get_height_for_width* data
448 				= (perform_data_get_height_for_width*)_data;
449 			BPictureButton::GetHeightForWidth(data->width, &data->min, &data->max,
450 				&data->preferred);
451 			return B_OK;
452 		}
453 		case PERFORM_CODE_SET_LAYOUT:
454 		{
455 			perform_data_set_layout* data = (perform_data_set_layout*)_data;
456 			BPictureButton::SetLayout(data->layout);
457 			return B_OK;
458 		}
459 		case PERFORM_CODE_INVALIDATE_LAYOUT:
460 		{
461 			perform_data_invalidate_layout* data
462 				= (perform_data_invalidate_layout*)_data;
463 			BPictureButton::InvalidateLayout(data->descendants);
464 			return B_OK;
465 		}
466 		case PERFORM_CODE_DO_LAYOUT:
467 		{
468 			BPictureButton::DoLayout();
469 			return B_OK;
470 		}
471 	}
472 
473 	return BControl::Perform(code, _data);
474 }
475 
476 
477 // #pragma mark -
478 
479 
480 void BPictureButton::_ReservedPictureButton1() {}
481 void BPictureButton::_ReservedPictureButton2() {}
482 void BPictureButton::_ReservedPictureButton3() {}
483 
484 
485 BPictureButton&
486 BPictureButton::operator=(const BPictureButton &button)
487 {
488 	return *this;
489 }
490 
491