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