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