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