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