xref: /haiku/src/kits/interface/PictureButton.cpp (revision 746cac055adc6ac3308c7bc2d29040fb95689cc9)
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 	fDisabledOff(NULL),
20 	fDisabledOn(NULL),
21 	fOutlined(false),
22 	fBehavior(behavior)
23 {
24 	fEnabledOff = new BPicture(*off);
25 	fEnabledOn = new BPicture(*on);
26 }
27 
28 
29 BPictureButton::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 BPicture(&pictureArchive);
45 
46 	if (data->FindMessage("_e_off", &pictureArchive) == B_OK)
47 		fEnabledOff = new BPicture(&pictureArchive);
48 
49 	if (data->FindMessage("_d_on", &pictureArchive) == B_OK)
50 		fDisabledOn = new BPicture(&pictureArchive);
51 
52 	if (data->FindMessage("_d_off", &pictureArchive) == B_OK)
53 		fDisabledOff = new BPicture(&pictureArchive);
54 }
55 
56 
57 BPictureButton::~BPictureButton()
58 {
59 	delete fEnabledOn;
60 	delete fEnabledOff;
61 	delete fDisabledOn;
62 	delete fDisabledOff;
63 }
64 
65 
66 BArchivable *
67 BPictureButton::Instantiate(BMessage *data)
68 {
69 	if ( validate_instantiation(data, "BPictureButton"))
70 		return new BPictureButton(data);
71 
72 	return NULL;
73 }
74 
75 
76 status_t
77 BPictureButton::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 
116 void
117 BPictureButton::Draw(BRect updateRect)
118 {
119 	BRect rect = Bounds();
120 
121 	// We should request the view's base color which normaly is (216,216,216)
122 	rgb_color color = ui_color(B_PANEL_BACKGROUND_COLOR);
123 
124 	if (IsEnabled()) {
125 		if (Value() == B_CONTROL_ON)
126 			DrawPicture(fEnabledOn);
127 		else
128 			DrawPicture(fEnabledOff);
129 	} else {
130 
131 		if (fDisabledOff == NULL
132 			|| (fDisabledOn == NULL && fBehavior == B_TWO_STATE_BUTTON))
133 			debugger("Need to set the 'disabled' pictures for this BPictureButton ");
134 
135 		if (Value() == B_CONTROL_ON)
136 			DrawPicture(fDisabledOn);
137 		else
138 			DrawPicture(fDisabledOff);
139 	}
140 
141 	if (IsFocus()) {
142 		SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
143 		StrokeRect(rect, B_SOLID_HIGH);
144 	}
145 }
146 
147 
148 void
149 BPictureButton::MouseDown(BPoint point)
150 {
151 	if (!IsEnabled()) {
152 		BControl::MouseDown(point);
153 		return;
154 	}
155 
156 	SetMouseEventMask(B_POINTER_EVENTS,
157 		B_NO_POINTER_HISTORY | B_SUSPEND_VIEW_FOCUS);
158 
159 	if (fBehavior == B_ONE_STATE_BUTTON) {
160 		SetValue(B_CONTROL_ON);
161 	} else {
162 		if (Value() == B_CONTROL_ON)
163 			SetValue(B_CONTROL_OFF);
164 		else
165 			SetValue(B_CONTROL_ON);
166 	}
167 	SetTracking(true);
168 }
169 
170 
171 void
172 BPictureButton::MouseUp(BPoint point)
173 {
174 	if (IsEnabled() && IsTracking()) {
175 		if (Bounds().Contains(point)) {
176 			if (fBehavior == B_ONE_STATE_BUTTON) {
177 				if (Value() == B_CONTROL_ON) {
178 					snooze(75000);
179 					SetValue(B_CONTROL_OFF);
180 				}
181 			}
182 			Invoke();
183 		}
184 
185 		SetTracking(false);
186 	}
187 }
188 
189 
190 void
191 BPictureButton::MouseMoved(BPoint point, uint32 transit, const BMessage *msg)
192 {
193 	if (IsEnabled() && IsTracking()) {
194 		if (transit == B_EXITED_VIEW)
195 			SetValue(B_CONTROL_OFF);
196 		else if (transit == B_ENTERED_VIEW)
197 			SetValue(B_CONTROL_ON);
198 	} else
199 		BControl::MouseMoved(point, transit, msg);
200 }
201 
202 
203 void
204 BPictureButton::KeyDown(const char *bytes, int32 numBytes)
205 {
206 	if (numBytes == 1) {
207 		switch (bytes[0]) {
208 			case B_ENTER:
209 			case B_SPACE:
210 				if (fBehavior == B_ONE_STATE_BUTTON) {
211 					SetValue(B_CONTROL_ON);
212 					snooze(50000);
213 					SetValue(B_CONTROL_OFF);
214 				} else {
215 					if (Value() == B_CONTROL_ON)
216 						SetValue(B_CONTROL_OFF);
217 					else
218 						SetValue(B_CONTROL_ON);
219 				}
220 				Invoke();
221 				return;
222 		}
223 	}
224 
225 	BControl::KeyDown(bytes, numBytes);
226 }
227 
228 
229 void
230 BPictureButton::SetEnabledOn(BPicture *on)
231 {
232 	delete fEnabledOn;
233 	fEnabledOn = new BPicture(*on);
234 }
235 
236 
237 void
238 BPictureButton::SetEnabledOff(BPicture *off)
239 {
240 	delete fEnabledOff;
241 	fEnabledOff = new BPicture(*off);
242 }
243 
244 
245 void
246 BPictureButton::SetDisabledOn(BPicture *on)
247 {
248 	delete fDisabledOn;
249 	fDisabledOn = new BPicture(*on);
250 }
251 
252 
253 void
254 BPictureButton::SetDisabledOff(BPicture *off)
255 {
256 	delete fDisabledOff;
257 	fDisabledOff = new BPicture(*off);
258 }
259 
260 
261 BPicture *
262 BPictureButton::EnabledOn() const
263 {
264 	return fEnabledOn;
265 }
266 
267 
268 BPicture *
269 BPictureButton::EnabledOff() const
270 {
271 	return fEnabledOff;
272 }
273 
274 
275 BPicture *
276 BPictureButton::DisabledOn() const
277 {
278 	return fDisabledOn;
279 }
280 
281 
282 BPicture *
283 BPictureButton::DisabledOff() const
284 {
285 	return fDisabledOff;
286 }
287 
288 
289 void
290 BPictureButton::SetBehavior(uint32 behavior)
291 {
292 	fBehavior = behavior;
293 }
294 
295 
296 uint32
297 BPictureButton::Behavior() const
298 {
299 	return fBehavior;
300 }
301 
302 
303 void
304 BPictureButton::MessageReceived(BMessage *msg)
305 {
306 	BControl::MessageReceived(msg);
307 }
308 
309 
310 void
311 BPictureButton::WindowActivated(bool state)
312 {
313 	BControl::WindowActivated(state);
314 }
315 
316 
317 void
318 BPictureButton::AttachedToWindow()
319 {
320 	BControl::AttachedToWindow();
321 }
322 
323 
324 void
325 BPictureButton::DetachedFromWindow()
326 {
327 	BControl::DetachedFromWindow();
328 }
329 
330 
331 void
332 BPictureButton::SetValue(int32 value)
333 {
334 	BControl::SetValue(value);
335 }
336 
337 
338 status_t
339 BPictureButton::Invoke(BMessage *msg)
340 {
341 	return BControl::Invoke(msg);
342 }
343 
344 
345 void
346 BPictureButton::FrameMoved(BPoint newPosition)
347 {
348 	BControl::FrameMoved(newPosition);
349 }
350 
351 
352 void
353 BPictureButton::FrameResized(float newWidth, float newHeight)
354 {
355 	BControl::FrameResized(newWidth, newHeight);
356 }
357 
358 
359 BHandler *
360 BPictureButton::ResolveSpecifier(BMessage *msg, int32 index,
361 	BMessage *specifier, int32 form, const char *property)
362 {
363 	return BControl::ResolveSpecifier(msg, index, specifier, form, property);
364 }
365 
366 
367 status_t
368 BPictureButton::GetSupportedSuites(BMessage *data)
369 {
370 	return BControl::GetSupportedSuites(data);
371 }
372 
373 
374 void
375 BPictureButton::ResizeToPreferred()
376 {
377 	BControl::ResizeToPreferred();
378 }
379 
380 
381 void
382 BPictureButton::GetPreferredSize(float* _width, float* _height)
383 {
384 	// Need to do some test to see what the Be method returns...
385 	BControl::GetPreferredSize(_width, _height);
386 }
387 
388 
389 void
390 BPictureButton::MakeFocus(bool state)
391 {
392 	BControl::MakeFocus(state);
393 }
394 
395 
396 void
397 BPictureButton::AllAttached()
398 {
399 	BControl::AllAttached();
400 }
401 
402 
403 void
404 BPictureButton::AllDetached()
405 {
406 	BControl::AllDetached();
407 }
408 
409 
410 status_t
411 BPictureButton::Perform(perform_code d, void *arg)
412 {
413 	return BControl::Perform(d, arg);
414 }
415 
416 
417 void BPictureButton::_ReservedPictureButton1() {}
418 void BPictureButton::_ReservedPictureButton2() {}
419 void BPictureButton::_ReservedPictureButton3() {}
420 
421 
422 BPictureButton &
423 BPictureButton::operator=(const BPictureButton &button)
424 {
425 	return *this;
426 }
427 
428 
429 void
430 BPictureButton::Redraw()
431 {
432 }
433 
434 
435 void
436 BPictureButton::InitData()
437 {
438 }
439 
440