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