1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2001-2002, OpenBeOS 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 // DEALINGS IN THE SOFTWARE. 21 // 22 // File Name: PictureButton.cpp 23 // Author: Graham MacDonald (macdonag@btopenworld.com) 24 // Description: BPictureButton displays and controls a picture button in a 25 // window. 26 //------------------------------------------------------------------------------ 27 28 // Standard Includes ----------------------------------------------------------- 29 30 // System Includes ------------------------------------------------------------- 31 #include <PictureButton.h> 32 33 34 // Project Includes ------------------------------------------------------------ 35 36 // Local Includes -------------------------------------------------------------- 37 38 // Local Defines --------------------------------------------------------------- 39 40 // Globals --------------------------------------------------------------------- 41 42 //------------------------------------------------------------------------------ 43 BPictureButton::BPictureButton (BRect frame, 44 const char* name, 45 BPicture *off, 46 BPicture *on, 47 BMessage *message, 48 uint32 behavior, 49 uint32 resizeMask, 50 uint32 flgs) 51 : BControl (frame, name, "", message, resizeMask, flgs), fOutlined (false), 52 fBehavior (behavior) 53 { 54 fEnabledOff = new BPicture(*off); 55 fEnabledOn = new BPicture(*on); 56 fDisabledOff = NULL; 57 fDisabledOn = NULL; 58 } 59 60 61 /*********************************************************************** 62 * Method: BPictureButton::BPictureButton 63 * Params: BMessage *data 64 * Effects: 65 ***********************************************************************/ 66 BPictureButton::BPictureButton(BMessage *data) : BControl (data) 67 { 68 BMessage pictureArchive; 69 70 // Default to 1 state button if not here - is this valid? 71 if (data->FindInt32 ("_behave", (int32 *)&fBehavior ) != B_OK ) 72 { 73 fBehavior = B_ONE_STATE_BUTTON; 74 } 75 76 // Now expand the pictures: 77 if (data->FindMessage("_e_on", &pictureArchive) == B_OK) 78 { 79 fEnabledOn = new BPicture(&pictureArchive); 80 } 81 if (data->FindMessage("_e_off", &pictureArchive) == B_OK) 82 { 83 fEnabledOff = new BPicture(&pictureArchive); 84 } 85 86 if (fBehavior == B_TWO_STATE_BUTTON) 87 { 88 if (data->FindMessage("_d_on", &pictureArchive) == B_OK) 89 { 90 fDisabledOn = new BPicture(&pictureArchive); 91 } 92 if (data->FindMessage("_d_off", &pictureArchive) == B_OK) 93 { 94 fDisabledOff = new BPicture(&pictureArchive); 95 } 96 } 97 else 98 { 99 fDisabledOn = fDisabledOff = NULL; 100 } 101 } 102 103 104 /*********************************************************************** 105 * Method: BPictureButton::~BPictureButton 106 * Params: 107 * Effects: 108 ***********************************************************************/ 109 BPictureButton::~BPictureButton() 110 { 111 delete fEnabledOn; 112 delete fEnabledOff; 113 114 if (fBehavior == B_TWO_STATE_BUTTON) 115 { 116 delete fDisabledOn; 117 delete fDisabledOff; 118 } 119 } 120 121 122 /*********************************************************************** 123 * Method: BPictureButton::Instantiate 124 * Params: BMessage *data 125 * Returns: BArchivable * 126 * Effects: 127 ***********************************************************************/ 128 BArchivable * 129 BPictureButton::Instantiate (BMessage *data) 130 { 131 // Do we ned to take into account deep copy of images? I guess so! 132 if ( validate_instantiation(data, "BPictureButton")) 133 { 134 return new BPictureButton(data); 135 } 136 else 137 { 138 return NULL; 139 } 140 } 141 142 143 /*********************************************************************** 144 * Method: BPictureButton::Archive 145 * Params: BMessage *data, bool deep 146 * Returns: status_t 147 * Effects: 148 ***********************************************************************/ 149 status_t 150 BPictureButton::Archive (BMessage *data, bool deep) const 151 { 152 status_t err = BControl::Archive(data, deep); 153 154 if (err != B_OK) return err; 155 156 // Do we need this? Good practice! 157 err = data->AddString("class", "BPictureButton"); 158 159 if (err != B_OK) return err; 160 161 // Fill out message, depending on whether a deep copy is required or not. 162 if (deep) 163 { 164 BMessage pictureArchive; 165 166 if (fEnabledOn->Archive(&pictureArchive, deep) == B_OK) 167 { 168 err = data->AddMessage("_e_on", &pictureArchive); 169 if (err != B_OK) return err; 170 } 171 172 if (fEnabledOff->Archive(&pictureArchive, deep) == B_OK) 173 { 174 err = data->AddMessage("_e_off", &pictureArchive); 175 if (err != B_OK) return err; 176 } 177 178 // Do we add messages for pictures that don't exist? 179 if (fBehavior == B_TWO_STATE_BUTTON) 180 { 181 if (fDisabledOn->Archive(&pictureArchive, deep) == B_OK) 182 { 183 err = data->AddMessage("_d_on", &pictureArchive); 184 if (err != B_OK) return err; 185 } 186 187 if (fDisabledOff->Archive(&pictureArchive, deep) == B_OK) 188 { 189 err = data->AddMessage("_d_off", &pictureArchive); 190 if (err != B_OK) return err; 191 } 192 } 193 } 194 195 err = data->AddInt32("_behave", fBehavior); 196 197 return err; 198 } 199 200 201 /*********************************************************************** 202 * Method: BPictureButton::Draw 203 * Params: BRect updateRect 204 * Returns: void 205 * Effects: 206 ***********************************************************************/ 207 void 208 BPictureButton::Draw (BRect updateRect) 209 { 210 BRect rect = Bounds(); 211 212 // Need to check if TWO_STATE, if setEnabled=false, and if diabled picture is null 213 // If so, and in debug, bring up an Alert, if so, and not in debug, output to stdout 214 215 // We should request the view's base color which normaly is (216,216,216) 216 rgb_color color = ui_color(B_PANEL_BACKGROUND_COLOR); 217 218 if (fBehavior == B_ONE_STATE_BUTTON) 219 { 220 if (BControl::Value() == B_CONTROL_ON) 221 { 222 BView::DrawPicture(fEnabledOn); 223 } 224 else 225 { 226 BView::DrawPicture(fEnabledOff); 227 } 228 } 229 else // Must be B_TWO_STATE_BUTTON: 230 { 231 if (BControl::IsEnabled()) 232 { 233 if (BControl::Value() == B_CONTROL_ON) 234 { 235 BView::DrawPicture(fEnabledOn); 236 } 237 else 238 { 239 BView::DrawPicture(fEnabledOff); 240 } 241 } 242 else // Must be Disabled: 243 { 244 if (BControl::Value() == B_CONTROL_ON) 245 { 246 if (fDisabledOn == NULL) 247 { 248 debugger("Need to set the 'disabled' pictures for this BPictureButton "); 249 } 250 BView::DrawPicture(fDisabledOn); 251 } 252 else 253 { 254 if (fDisabledOn == NULL) 255 { 256 debugger("Need to set the 'disabled' pictures for this BPictureButton "); 257 } 258 BView::DrawPicture(fDisabledOff); 259 } 260 } 261 } 262 263 if (IsFocus()) 264 { 265 SetHighColor( ui_color(B_KEYBOARD_NAVIGATION_COLOR) ); 266 StrokeRect(rect, B_SOLID_HIGH); 267 } 268 } 269 270 271 /*********************************************************************** 272 * Method: BPictureButton::MouseDown 273 * Params: BPoint where 274 * Returns: void 275 * Effects: 276 ***********************************************************************/ 277 void 278 BPictureButton::MouseDown (BPoint point) 279 { 280 if (!IsEnabled()) 281 { 282 BControl::MouseDown(point); 283 return; 284 } 285 286 SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY | B_SUSPEND_VIEW_FOCUS); 287 288 if (fBehavior == B_ONE_STATE_BUTTON) 289 { 290 SetValue(B_CONTROL_ON); 291 } 292 else 293 { 294 if (Value() == B_CONTROL_ON) 295 { 296 SetValue(B_CONTROL_OFF); 297 } 298 else 299 { 300 SetValue(B_CONTROL_ON); 301 } 302 } 303 SetTracking(true); 304 } 305 306 307 /*********************************************************************** 308 * Method: BPictureButton::MouseUp 309 * Params: BPoint pt 310 * Returns: void 311 * Effects: 312 ***********************************************************************/ 313 void 314 BPictureButton::MouseUp (BPoint point) 315 { 316 if (IsEnabled() && IsTracking()) 317 { 318 if (Bounds().Contains(point)) 319 { 320 if (fBehavior == B_ONE_STATE_BUTTON) 321 { 322 if (Value() == B_CONTROL_ON) 323 { 324 snooze(75000); 325 SetValue(B_CONTROL_OFF); 326 } 327 } 328 BControl::Invoke(); 329 } 330 331 SetTracking(false); 332 } 333 } 334 335 336 /*********************************************************************** 337 * Method: BPictureButton::MouseMoved 338 * Params: BPoint pt, uint32 code, const BMessage *msg 339 * Returns: void 340 * Effects: 341 ***********************************************************************/ 342 void 343 BPictureButton::MouseMoved (BPoint pt, uint32 code, const BMessage *msg) 344 { 345 if (IsEnabled() && IsTracking()) 346 { 347 if (code == B_EXITED_VIEW) 348 SetValue(B_CONTROL_OFF); 349 else if (code == B_ENTERED_VIEW) 350 SetValue(B_CONTROL_ON); 351 } 352 else 353 { 354 BControl::MouseMoved(pt, code, msg); 355 } 356 } 357 358 359 /*********************************************************************** 360 * Method: BPictureButton::KeyDown 361 * Params: const char *bytes, int32 numBytes 362 * Returns: void 363 * Effects: 364 ***********************************************************************/ 365 void 366 BPictureButton::KeyDown (const char *bytes, int32 numBytes) 367 { 368 if (numBytes == 1) 369 { 370 switch (bytes[0]) 371 { 372 case B_ENTER: 373 case B_SPACE: 374 if (fBehavior == B_ONE_STATE_BUTTON) 375 { 376 SetValue(B_CONTROL_ON); 377 snooze(50000); 378 SetValue(B_CONTROL_OFF); 379 } 380 else 381 { 382 if (Value() == B_CONTROL_ON) 383 { 384 SetValue(B_CONTROL_OFF); 385 } 386 else 387 { 388 SetValue(B_CONTROL_ON); 389 } 390 } 391 Invoke(); 392 break; 393 394 default: 395 BControl::KeyDown(bytes, numBytes); 396 } 397 } 398 else 399 { 400 BControl::KeyDown(bytes, numBytes); 401 } 402 } 403 404 405 /*********************************************************************** 406 * Method: BPictureButton::SetEnabledOn 407 * Params: BPicture *on 408 * Returns: void 409 * Effects: 410 ***********************************************************************/ 411 void 412 BPictureButton::SetEnabledOn (BPicture *on) 413 { 414 if (!fEnabledOn) 415 { 416 delete fEnabledOn; 417 } 418 fEnabledOn = new BPicture (*on); 419 } 420 421 422 /*********************************************************************** 423 * Method: BPictureButton::SetEnabledOff 424 * Params: BPicture *off 425 * Returns: void 426 * Effects: 427 ***********************************************************************/ 428 void 429 BPictureButton::SetEnabledOff (BPicture *off) 430 { 431 if (!fEnabledOff) 432 { 433 delete fEnabledOff; 434 } 435 fEnabledOff = new BPicture (*off); 436 } 437 438 439 /*********************************************************************** 440 * Method: BPictureButton::SetDisabledOn 441 * Params: BPicture *on 442 * Returns: void 443 * Effects: 444 ***********************************************************************/ 445 void 446 BPictureButton::SetDisabledOn (BPicture *on) 447 { 448 if (!fDisabledOn) 449 { 450 delete fDisabledOn; 451 } 452 fDisabledOn = new BPicture (*on); 453 } 454 455 456 /*********************************************************************** 457 * Method: BPictureButton::SetDisabledOff 458 * Params: BPicture *off 459 * Returns: void 460 * Effects: 461 ***********************************************************************/ 462 void 463 BPictureButton::SetDisabledOff (BPicture *off) 464 { 465 if (!fDisabledOff) 466 { 467 delete fDisabledOff; 468 } 469 fDisabledOff = new BPicture (*off); 470 } 471 472 473 /*********************************************************************** 474 * Method: BPictureButton::EnabledOn 475 * Params: 476 * Returns: BPicture * 477 * Effects: 478 ***********************************************************************/ 479 BPicture * 480 BPictureButton::EnabledOn () const 481 { 482 return fEnabledOn; 483 } 484 485 486 /*********************************************************************** 487 * Method: BPictureButton::EnabledOff 488 * Params: 489 * Returns: BPicture * 490 * Effects: 491 ***********************************************************************/ 492 BPicture * 493 BPictureButton::EnabledOff () const 494 { 495 return fEnabledOff; 496 } 497 498 499 /*********************************************************************** 500 * Method: BPictureButton::DisabledOn 501 * Params: 502 * Returns: BPicture * 503 * Effects: 504 ***********************************************************************/ 505 BPicture * 506 BPictureButton::DisabledOn () const 507 { 508 return fDisabledOn; 509 } 510 511 512 /*********************************************************************** 513 * Method: BPictureButton::DisabledOff 514 * Params: 515 * Returns: BPicture * 516 * Effects: 517 ***********************************************************************/ 518 BPicture * 519 BPictureButton::DisabledOff() const 520 { 521 return fDisabledOff; 522 } 523 524 525 /*********************************************************************** 526 * Method: BPictureButton::SetBehavior 527 * Params: uint32 behavior 528 * Returns: void 529 * Effects: 530 ***********************************************************************/ 531 void 532 BPictureButton::SetBehavior (uint32 behavior) 533 { 534 fBehavior = behavior; 535 } 536 537 538 /*********************************************************************** 539 * Method: BPictureButton::Behavior 540 * Params: 541 * Returns: uint32 542 * Effects: 543 ***********************************************************************/ 544 uint32 545 BPictureButton::Behavior () const 546 { 547 return fBehavior; 548 } 549 550 551 /*********************************************************************** 552 * Method: BPictureButton::MessageReceived 553 * Params: BMessage *msg 554 * Returns: void 555 * Effects: 556 ***********************************************************************/ 557 void 558 BPictureButton::MessageReceived (BMessage *msg) 559 { 560 BControl::MessageReceived(msg); 561 } 562 563 564 /*********************************************************************** 565 * Method: BPictureButton::WindowActivated 566 * Params: bool state 567 * Returns: void 568 * Effects: 569 ***********************************************************************/ 570 void 571 BPictureButton::WindowActivated (bool state) 572 { 573 BView::WindowActivated (state); 574 } 575 576 577 /*********************************************************************** 578 * Method: BPictureButton::AttachedToWindow 579 * Params: 580 * Returns: void 581 * Effects: 582 ***********************************************************************/ 583 void 584 BPictureButton::AttachedToWindow () 585 { 586 BControl::AttachedToWindow(); 587 } 588 589 590 /*********************************************************************** 591 * Method: BPictureButton::DetachedFromWindow 592 * Params: 593 * Returns: void 594 * Effects: 595 ***********************************************************************/ 596 void 597 BPictureButton::DetachedFromWindow () 598 { 599 BView::DetachedFromWindow(); 600 } 601 602 603 /*********************************************************************** 604 * Method: BPictureButton::SetValue 605 * Params: int32 value 606 * Returns: void 607 * Effects: 608 ***********************************************************************/ 609 void 610 BPictureButton::SetValue (int32 value) 611 { 612 BControl::SetValue(value); 613 } 614 615 616 /*********************************************************************** 617 * Method: BPictureButton::Invoke 618 * Params: BMessage *msg 619 * Returns: status_t 620 * Effects: 621 ***********************************************************************/ 622 status_t 623 BPictureButton::Invoke (BMessage *msg) 624 { 625 return BControl::Invoke(msg); 626 } 627 628 629 /*********************************************************************** 630 * Method: BPictureButton::FrameMoved 631 * Params: BPoint new_position 632 * Returns: void 633 * Effects: 634 ***********************************************************************/ 635 void 636 BPictureButton::FrameMoved (BPoint new_position) 637 { 638 BView::FrameMoved (new_position); 639 } 640 641 642 /*********************************************************************** 643 * Method: BPictureButton::FrameResized 644 * Params: float new_width, float new_height 645 * Returns: void 646 * Effects: 647 ***********************************************************************/ 648 void 649 BPictureButton::FrameResized (float new_width, float new_height) 650 { 651 BView::FrameResized (new_width, new_height); 652 } 653 654 655 /*********************************************************************** 656 * Method: BPictureButton::ResolveSpecifier 657 * Params: BMessage *msg, int32 index, BMessage *specifier, int32 form, const char *property 658 * Returns: BHandler * 659 * Effects: 660 ***********************************************************************/ 661 BHandler * 662 BPictureButton::ResolveSpecifier (BMessage *msg, int32 index, BMessage *specifier, int32 form, const char *property) 663 { 664 return BControl::ResolveSpecifier(msg, index, specifier, form, property); 665 } 666 667 668 /*********************************************************************** 669 * Method: BPictureButton::GetSupportedSuites 670 * Params: BMessage *data 671 * Returns: status_t 672 * Effects: 673 ***********************************************************************/ 674 status_t 675 BPictureButton::GetSupportedSuites (BMessage *data) 676 { 677 return BControl::GetSupportedSuites(data); 678 } 679 680 681 /*********************************************************************** 682 * Method: BPictureButton::ResizeToPreferred 683 * Params: 684 * Returns: void 685 * Effects: 686 ***********************************************************************/ 687 void 688 BPictureButton::ResizeToPreferred () 689 { 690 float w, h; 691 GetPreferredSize (&w, &h); 692 BView::ResizeTo (w,h); 693 } 694 695 696 /*********************************************************************** 697 * Method: BPictureButton::GetPreferredSize 698 * Params: float *width, float *height 699 * Returns: void 700 * Effects: 701 ***********************************************************************/ 702 void 703 BPictureButton::GetPreferredSize (float *width, float *height) 704 { 705 // Need to do some test to see what the Be method returns... 706 } 707 708 709 /*********************************************************************** 710 * Method: BPictureButton::MakeFocus 711 * Params: bool state 712 * Returns: void 713 * Effects: 714 ***********************************************************************/ 715 void 716 BPictureButton::MakeFocus (bool state) 717 { 718 BControl::MakeFocus(state); 719 } 720 721 722 /*********************************************************************** 723 * Method: BPictureButton::AllAttached 724 * Params: 725 * Returns: void 726 * Effects: 727 ***********************************************************************/ 728 void 729 BPictureButton::AllAttached () 730 { 731 BView::AllAttached(); 732 } 733 734 735 /*********************************************************************** 736 * Method: BPictureButton::AllDetached 737 * Params: 738 * Returns: void 739 * Effects: 740 ***********************************************************************/ 741 void 742 BPictureButton::AllDetached () 743 { 744 BView::AllDetached(); 745 } 746 747 748 /*********************************************************************** 749 * Method: BPictureButton::Perform 750 * Params: perform_code d, void *arg 751 * Returns: status_t 752 * Effects: 753 ***********************************************************************/ 754 status_t 755 BPictureButton::Perform (perform_code d, void *arg) 756 { 757 // Really clutching at straws here.... 758 return B_ERROR; 759 } 760 761 762 /*********************************************************************** 763 * Method: BPictureButton::_ReservedPictureButton1 764 * Params: 765 * Returns: void 766 * Effects: 767 ***********************************************************************/ 768 void 769 BPictureButton::_ReservedPictureButton1 () 770 { 771 } 772 773 774 /*********************************************************************** 775 * Method: BPictureButton::_ReservedPictureButton2 776 * Params: 777 * Returns: void 778 * Effects: 779 ***********************************************************************/ 780 void 781 BPictureButton::_ReservedPictureButton2() 782 { 783 } 784 785 786 /*********************************************************************** 787 * Method: BPictureButton::_ReservedPictureButton3 788 * Params: 789 * Returns: void 790 * Effects: 791 ***********************************************************************/ 792 void 793 BPictureButton::_ReservedPictureButton3() 794 { 795 } 796 797 798 /*********************************************************************** 799 * Method: BPictureButton::operator= 800 * Params: const BPictureButton & 801 * Returns: BPictureButton & 802 * Effects: 803 ***********************************************************************/ 804 BPictureButton & 805 BPictureButton::operator=(const BPictureButton &button) 806 { 807 return *this; 808 } 809 810 811 /*********************************************************************** 812 * Method: BPictureButton::Redraw 813 * Params: 814 * Returns: void 815 * Effects: 816 ***********************************************************************/ 817 void 818 BPictureButton::Redraw() 819 { 820 } 821 822 823 /*********************************************************************** 824 * Method: BPictureButton::InitData 825 * Params: 826 * Returns: void 827 * Effects: 828 ***********************************************************************/ 829 void 830 BPictureButton::InitData() 831 { 832 } 833 834