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: Control.cpp 23 // Author: Marc Flerackers (mflerackers@androme.be) 24 // Description: BControl is the base class for user-event handling objects. 25 //------------------------------------------------------------------------------ 26 27 // Standard Includes ----------------------------------------------------------- 28 #include <string.h> 29 #include <malloc.h> 30 31 // System Includes ------------------------------------------------------------- 32 #include <Control.h> 33 #include <PropertyInfo.h> 34 #include <Window.h> 35 #include <Errors.h> 36 37 // Project Includes ------------------------------------------------------------ 38 39 // Local Includes -------------------------------------------------------------- 40 41 // Local Defines --------------------------------------------------------------- 42 43 // Globals --------------------------------------------------------------------- 44 static property_info prop_list[] = 45 { 46 { 47 "Enabled", 48 { B_GET_PROPERTY, 0 }, 49 { B_DIRECT_SPECIFIER, 0 }, 50 "Returns whether or not the BControl is currently enabled.", 0, 51 { B_BOOL_TYPE, 0 } 52 }, 53 { 54 "Enabled", 55 { B_SET_PROPERTY, 0 }, 56 { B_DIRECT_SPECIFIER, 0 }, 57 "Enables or disables the BControl.", 0, 58 { B_BOOL_TYPE, 0 } 59 }, 60 { 61 "Label", 62 { B_GET_PROPERTY, 0 }, 63 { B_DIRECT_SPECIFIER, 0 }, 64 "Returns the BControl's label.", 0, 65 { B_STRING_TYPE, 0 } 66 }, 67 { 68 "Label", 69 { B_SET_PROPERTY, 0 }, 70 { B_DIRECT_SPECIFIER, 0 }, 71 "Sets the label of the BControl.", 0, 72 { B_STRING_TYPE, 0 } 73 }, 74 { 75 "Value", 76 { B_GET_PROPERTY, 0 }, 77 { B_DIRECT_SPECIFIER, 0 }, 78 "Returns the BControl's value.", 0, 79 { B_INT32_TYPE, 0 } 80 }, 81 { 82 "Value", 83 { B_SET_PROPERTY, 0 }, 84 { B_DIRECT_SPECIFIER, 0 }, 85 "Sets the value of the BControl.", 0, 86 { B_INT32_TYPE, 0 }, 87 }, 88 { 0 } 89 }; 90 91 //------------------------------------------------------------------------------ 92 BControl::BControl(BRect frame, const char *name, const char *label, BMessage *message, 93 uint32 resizingMode, uint32 flags) 94 : BView(frame, name, resizingMode, flags), 95 BInvoker(message, NULL), 96 fValue(B_CONTROL_OFF), 97 fEnabled(true), 98 fFocusChanging(false), 99 fTracking(false), 100 fWantsNav(true) 101 { 102 fLabel = strdup(label); 103 } 104 //------------------------------------------------------------------------------ 105 BControl::~BControl() 106 { 107 if (fLabel) 108 free(fLabel); 109 } 110 //------------------------------------------------------------------------------ 111 BControl::BControl(BMessage *archive) : BView(archive) 112 { 113 const char *label; 114 115 if (archive->FindInt32("_val", &fValue) != B_OK) 116 fValue = B_CONTROL_OFF; 117 118 if (archive->FindString("_label", &label) != B_OK) 119 fLabel = NULL; 120 else 121 SetLabel(label); 122 123 if ( archive->FindBool("_disable", &fEnabled) != B_OK) 124 fEnabled = true; 125 else 126 fEnabled = !fEnabled; 127 128 fFocusChanging = false; 129 fTracking = false; 130 fWantsNav = true; 131 132 BMessage message; 133 134 if (archive->FindMessage("_msg", &message) == B_OK) 135 SetMessage(new BMessage(message)); 136 } 137 //------------------------------------------------------------------------------ 138 BArchivable *BControl::Instantiate(BMessage *archive) 139 { 140 if (validate_instantiation(archive, "BControl")) 141 return new BControl(archive); 142 else 143 return NULL; 144 } 145 //------------------------------------------------------------------------------ 146 status_t BControl::Archive(BMessage *archive, bool deep) const 147 { 148 status_t err = BView::Archive(archive, deep); 149 150 if (err != B_OK) 151 return err; 152 153 if (Message()) 154 err = archive->AddMessage("_msg", Message ()); 155 156 if (err != B_OK) 157 return err; 158 159 if (fLabel) 160 err = archive->AddString("_label", fLabel); 161 162 if (err != B_OK ) 163 return err; 164 165 if (fValue != B_CONTROL_OFF) 166 err = archive->AddInt32("_val", fValue); 167 168 if (err != B_OK) 169 return err; 170 171 if (!fEnabled) 172 err = archive->AddBool("_disable", true); 173 174 return err; 175 } 176 //------------------------------------------------------------------------------ 177 void BControl::WindowActivated(bool active) 178 { 179 if (IsFocus()) 180 { 181 Draw(Bounds()); 182 Flush(); 183 } 184 185 BView::WindowActivated(active); 186 } 187 //------------------------------------------------------------------------------ 188 void BControl::AttachedToWindow() 189 { 190 if (Parent()) 191 SetViewColor(Parent()->ViewColor()); 192 193 if (Target() == NULL) 194 BInvoker::SetTarget(BMessenger(Window(), NULL)); 195 196 BView::AttachedToWindow(); 197 } 198 //------------------------------------------------------------------------------ 199 void BControl::MessageReceived(BMessage *message) 200 { 201 switch (message->what) 202 { 203 case B_CONTROL_INVOKED: 204 Invoke(); 205 break; 206 207 case B_GET_PROPERTY: 208 case B_SET_PROPERTY: 209 { 210 BPropertyInfo propInfo(prop_list); 211 BMessage specifier; 212 const char *property; 213 214 if (message->GetCurrentSpecifier(NULL, &specifier) != B_OK || 215 specifier.FindString("property", &property) != B_OK) 216 return; 217 218 switch (propInfo.FindMatch(message, 0, &specifier, specifier.what, property)) 219 { 220 case B_ERROR: 221 { 222 BView::MessageReceived(message); 223 break; 224 } 225 case 0: 226 { 227 BMessage reply; 228 reply.AddBool("result", fEnabled); 229 reply.AddBool("error", B_OK); 230 message->SendReply(&reply); 231 break; 232 } 233 case 1: 234 { 235 bool enabled; 236 message->FindBool("data", &enabled); 237 SetEnabled(enabled); 238 break; 239 } 240 case 2: 241 { 242 BMessage reply; 243 reply.AddString("result", fLabel); 244 reply.AddBool("error", B_OK); 245 message->SendReply(&reply); 246 break; 247 } 248 case 3: 249 { 250 const char *label; 251 message->FindString("data", &label); 252 SetLabel(label); 253 break; 254 } 255 case 4: 256 { 257 BMessage reply; 258 reply.AddInt32("result", fValue); 259 reply.AddBool("error", B_OK); 260 message->SendReply(&reply); 261 break; 262 } 263 case 5: 264 { 265 int32 value; 266 message->FindInt32("data", &value); 267 SetValue(value); 268 break; 269 } 270 } 271 272 break; 273 } 274 default: 275 { 276 BView::MessageReceived(message); 277 break; 278 } 279 } 280 } 281 //------------------------------------------------------------------------------ 282 void BControl::MakeFocus(bool focused) 283 { 284 BView::MakeFocus(focused); 285 286 if(Window()) 287 { 288 fFocusChanging = true; 289 Draw(Bounds()); 290 Flush(); 291 fFocusChanging = false; 292 } 293 } 294 //------------------------------------------------------------------------------ 295 void BControl::KeyDown(const char *bytes, int32 numBytes) 296 { 297 if (numBytes == 1) 298 { 299 switch (bytes[0]) 300 { 301 case B_ENTER: 302 case B_SPACE: 303 if (Value()) 304 SetValue(B_CONTROL_OFF); 305 else 306 SetValue(B_CONTROL_ON); 307 308 BInvoker::Invoke(); 309 break; 310 311 default: 312 BView::KeyDown(bytes, numBytes); 313 } 314 } 315 else 316 BView::KeyDown(bytes, numBytes); 317 } 318 //------------------------------------------------------------------------------ 319 void BControl::MouseDown(BPoint point) 320 { 321 BView::MouseDown(point); 322 } 323 //------------------------------------------------------------------------------ 324 void BControl::MouseUp(BPoint point) 325 { 326 BView::MouseUp(point); 327 } 328 //------------------------------------------------------------------------------ 329 void BControl::MouseMoved(BPoint point, uint32 transit, const BMessage *message) 330 { 331 BView::MouseMoved(point, transit, message); 332 } 333 //------------------------------------------------------------------------------ 334 void BControl::DetachedFromWindow() 335 { 336 BView::DetachedFromWindow(); 337 } 338 //------------------------------------------------------------------------------ 339 void BControl::SetLabel(const char *string) 340 { 341 if (strcmp(fLabel, string) == 0) 342 return; 343 344 if (fLabel) 345 free(fLabel); 346 347 fLabel = strdup(string); 348 349 Invalidate(); 350 } 351 //------------------------------------------------------------------------------ 352 const char *BControl::Label() const 353 { 354 return fLabel; 355 } 356 //------------------------------------------------------------------------------ 357 void BControl::SetValue(int32 value) 358 { 359 if (fValue == value) 360 return; 361 362 fValue = value; 363 364 if (Window()) 365 { 366 Draw(Bounds()); 367 Flush(); 368 } 369 } 370 //------------------------------------------------------------------------------ 371 int32 BControl::Value() const 372 { 373 return fValue; 374 } 375 //------------------------------------------------------------------------------ 376 void BControl::SetEnabled(bool enabled) 377 { 378 if (fEnabled == enabled) 379 return; 380 381 fEnabled = enabled; 382 383 if (fEnabled) 384 BView::SetFlags(Flags() | B_NAVIGABLE); 385 else 386 BView::SetFlags(Flags() & ~B_NAVIGABLE); 387 388 if (Window()) 389 { 390 Draw(Bounds()); 391 Flush(); 392 } 393 } 394 //------------------------------------------------------------------------------ 395 bool BControl::IsEnabled() const 396 { 397 return fEnabled; 398 } 399 //------------------------------------------------------------------------------ 400 void BControl::GetPreferredSize(float *width, float *height) 401 { 402 *width = 1.0f; 403 *height = 1.0f; 404 } 405 //------------------------------------------------------------------------------ 406 void BControl::ResizeToPreferred() 407 { 408 BView::ResizeToPreferred(); 409 } 410 //------------------------------------------------------------------------------ 411 status_t BControl::Invoke(BMessage *message) 412 { 413 if (message) 414 { 415 BMessage copy(*message); 416 copy.AddInt64("when", (int64)system_time()); 417 copy.AddPointer("source", this); 418 return BInvoker::Invoke(©); 419 } 420 else if ( Message () ) 421 { 422 BMessage copy (*Message()); 423 copy.AddInt64 ("when", (int64)system_time()); 424 copy.AddPointer ("source", this); 425 return BInvoker::Invoke(©); 426 } 427 428 return B_BAD_VALUE; 429 } 430 //------------------------------------------------------------------------------ 431 BHandler *BControl::ResolveSpecifier(BMessage *message, int32 index, 432 BMessage *specifier, int32 what, 433 const char *property) 434 { 435 BPropertyInfo propInfo(prop_list); 436 BHandler *target = NULL; 437 438 switch (propInfo.FindMatch(message, 0, specifier, what, property)) 439 { 440 case B_ERROR: 441 break; 442 443 case 0: 444 case 1: 445 case 2: 446 case 3: 447 case 4: 448 case 5: 449 target = this; 450 break; 451 } 452 453 if (!target) 454 target = BView::ResolveSpecifier(message, index, specifier, what, 455 property); 456 457 return target; 458 } 459 //------------------------------------------------------------------------------ 460 status_t BControl::GetSupportedSuites(BMessage *message) 461 { 462 status_t err; 463 464 if (message == NULL) 465 return B_BAD_VALUE; 466 467 err = message->AddString("suites", "suite/vnd.Be-control"); 468 469 if (err != B_OK) 470 return err; 471 472 BPropertyInfo prop_info(prop_list); 473 err = message->AddFlat("messages", &prop_info); 474 475 if (err != B_OK) 476 return err; 477 478 return BView::GetSupportedSuites(message); 479 } 480 //------------------------------------------------------------------------------ 481 void BControl::AllAttached() 482 { 483 BView::AllAttached(); 484 } 485 //------------------------------------------------------------------------------ 486 void BControl::AllDetached() 487 { 488 BView::AllDetached(); 489 } 490 //------------------------------------------------------------------------------ 491 status_t BControl::Perform(perform_code d, void *arg) 492 { 493 return B_ERROR; 494 } 495 //------------------------------------------------------------------------------ 496 bool BControl::IsFocusChanging() const 497 { 498 return fFocusChanging; 499 } 500 //------------------------------------------------------------------------------ 501 bool BControl::IsTracking() const 502 { 503 return fTracking; 504 } 505 //------------------------------------------------------------------------------ 506 void BControl::SetTracking(bool state) 507 { 508 fTracking = state; 509 } 510 //------------------------------------------------------------------------------ 511 void BControl::SetValueNoUpdate(int32 value) 512 { 513 fValue = value; 514 } 515 516 //------------------------------------------------------------------------------ 517 void BControl::_ReservedControl1() {} 518 void BControl::_ReservedControl2() {} 519 void BControl::_ReservedControl3() {} 520 void BControl::_ReservedControl4() {} 521 //------------------------------------------------------------------------------ 522 BControl &BControl::operator=(const BControl &) 523 { 524 return *this; 525 } 526 //------------------------------------------------------------------------------ 527 void BControl::InitData(BMessage *data) 528 { 529 530 } 531 //------------------------------------------------------------------------------ 532 533 /* 534 * $Log $ 535 * 536 * $Id $ 537 * 538 */ 539