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