1 /* 2 * Copyright 2001-2005, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Adrian Oanca <adioanca@cotty.iren.ro> 7 * Axel Dörfler, axeld@pinc-software.de 8 */ 9 10 11 #include <BeBuild.h> 12 #include <InterfaceDefs.h> 13 #include <PropertyInfo.h> 14 #include <Handler.h> 15 #include <View.h> 16 #include <Window.h> 17 #include <Message.h> 18 #include <MessageQueue.h> 19 #include <Rect.h> 20 #include <Point.h> 21 #include <Region.h> 22 #include <Font.h> 23 #include <ScrollBar.h> 24 #include <Cursor.h> 25 #include <Bitmap.h> 26 #include <Picture.h> 27 #include <Polygon.h> 28 #include <Shape.h> 29 #include <Button.h> 30 #include <Shelf.h> 31 #include <MenuBar.h> 32 #include <String.h> 33 #include <SupportDefs.h> 34 #include <Application.h> 35 36 #include <AppMisc.h> 37 #include <ViewAux.h> 38 #include <TokenSpace.h> 39 #include <MessageUtils.h> 40 #include <ColorUtils.h> 41 #include <AppServerLink.h> 42 #include <PortLink.h> 43 #include <ServerProtocol.h> 44 45 #ifdef USING_MESSAGE4 46 #include <MessagePrivate.h> 47 #endif 48 49 #include <math.h> 50 #include <stdio.h> 51 52 53 //#define DEBUG_BVIEW 54 #ifdef DEBUG_BVIEW 55 # include <stdio.h> 56 # define STRACE(x) printf x 57 # define BVTRACE PrintToStream() 58 #else 59 # define STRACE(x) ; 60 # define BVTRACE ; 61 #endif 62 63 #define MAX_ATTACHMENT_SIZE 49152 64 65 66 static property_info sViewPropInfo[] = { 67 { "Frame", { B_GET_PROPERTY, 0 }, 68 { B_DIRECT_SPECIFIER, 0 }, "Returns the view's frame rectangle.",0 }, 69 70 { "Frame", { B_SET_PROPERTY, 0 }, 71 { B_DIRECT_SPECIFIER, 0 }, "Sets the view's frame rectangle.",0 }, 72 73 { "Hidden", { B_GET_PROPERTY, 0 }, 74 { B_DIRECT_SPECIFIER, 0 }, "Returns true if the view is hidden; false otherwise.",0 }, 75 76 { "Hidden", { B_SET_PROPERTY, 0 }, 77 { B_DIRECT_SPECIFIER, 0 }, "Hides or shows the view.",0 }, 78 79 { "Shelf", { 0 }, 80 { B_DIRECT_SPECIFIER, 0 }, "Directs the scripting message to the shelf.",0 }, 81 82 { "View", { B_COUNT_PROPERTIES, 0 }, 83 { B_DIRECT_SPECIFIER, 0 }, "Returns the number of of child views.",0 }, 84 85 { "View", { 0 }, 86 { B_INDEX_SPECIFIER, 0 }, "Directs the scripting message to the specified view.",0 }, 87 88 { "View", { 0 }, 89 { B_REVERSE_INDEX_SPECIFIER, 0 }, "Directs the scripting message to the specified view.",0 }, 90 91 { "View", { 0 }, 92 { B_NAME_SPECIFIER, 0 }, "Directs the scripting message to the specified view.",0 }, 93 94 { 0, { 0 }, { 0 }, 0, 0 } 95 }; 96 97 98 // General Functions 99 //------------------------------------------------------------------------------ 100 101 102 static inline uint32 103 get_uint32_color(rgb_color color) 104 { 105 return *(uint32 *)&color; 106 } 107 108 109 static inline void 110 set_rgb_color(rgb_color &color, uint8 r, uint8 g, uint8 b, uint8 a = 255) 111 { 112 color.red = r; 113 color.green = g; 114 color.blue = b; 115 color.alpha = a; 116 } 117 118 119 // #pragma mark - 120 121 122 namespace BPrivate { 123 124 ViewState::ViewState() 125 { 126 pen_location.Set(0, 0); 127 pen_size = 1.0; 128 129 // This probably needs to be set to bounds by the owning BView 130 clipping_region.MakeEmpty(); 131 132 set_rgb_color(high_color, 0, 0, 0); 133 set_rgb_color(low_color, 255, 255, 255); 134 view_color = low_color; 135 136 pattern = B_SOLID_HIGH; 137 drawing_mode = B_OP_COPY; 138 139 origin.Set(0, 0); 140 141 line_join = B_MITER_JOIN; 142 line_cap = B_BUTT_CAP; 143 miter_limit = B_DEFAULT_MITER_LIMIT; 144 145 alpha_source_mode = B_PIXEL_ALPHA; 146 alpha_function_mode = B_ALPHA_OVERLAY; 147 148 scale = 1.0; 149 150 font = *be_plain_font; 151 font_flags = font.Flags(); 152 font_aliasing = false; 153 154 /* 155 INFO: We include(invalidate) only B_VIEW_CLIP_REGION_BIT flag 156 because we should get the clipping region from app_server. 157 The other flags do not need to be included because the data they 158 represent is already in sync with app_server - app_server uses the 159 same init(default) values. 160 */ 161 valid_flags = ~B_VIEW_CLIP_REGION_BIT; 162 163 archiving_flags = B_VIEW_FRAME_BIT; 164 } 165 166 167 void 168 ViewState::UpdateServerFontState(BPrivate::PortLink &link) 169 { 170 link.StartMessage(AS_LAYER_SET_FONT_STATE); 171 link.Attach<uint16>(font_flags); 172 173 // always present. 174 if (font_flags & B_FONT_FAMILY_AND_STYLE) { 175 uint32 fontID; 176 fontID = font.FamilyAndStyle(); 177 178 link.Attach<uint32>(fontID); 179 } 180 181 if (font_flags & B_FONT_SIZE) 182 link.Attach<float>(font.Size()); 183 184 if (font_flags & B_FONT_SHEAR) 185 link.Attach<float>(font.Shear()); 186 187 if (font_flags & B_FONT_ROTATION) 188 link.Attach<float>(font.Rotation()); 189 190 if (font_flags & B_FONT_SPACING) 191 link.Attach<uint8>(font.Spacing()); 192 193 if (font_flags & B_FONT_ENCODING) 194 link.Attach<uint8>(font.Encoding()); 195 196 if (font_flags & B_FONT_FACE) 197 link.Attach<uint16>(font.Face()); 198 199 if (font_flags & B_FONT_FLAGS) 200 link.Attach<uint32>(font.Flags()); 201 } 202 203 204 void 205 ViewState::UpdateServerState(BPrivate::PortLink &link) 206 { 207 UpdateServerFontState(link); 208 209 link.StartMessage(AS_LAYER_SET_STATE); 210 link.Attach<BPoint>(pen_location); 211 link.Attach<float>(pen_size); 212 link.Attach<rgb_color>(high_color); 213 link.Attach<rgb_color>(low_color); 214 link.Attach< ::pattern>(pattern); 215 link.Attach<int8>((int8)drawing_mode); 216 link.Attach<BPoint>(origin); 217 link.Attach<int8>((int8)line_join); 218 link.Attach<int8>((int8)line_cap); 219 link.Attach<float>(miter_limit); 220 link.Attach<int8>((int8)alpha_source_mode); 221 link.Attach<int8>((int8)alpha_function_mode); 222 link.Attach<float>(scale); 223 link.Attach<bool>(font_aliasing); 224 225 // we send the 'local' clipping region... if we have one... 226 int32 count = clipping_region.CountRects(); 227 228 link.Attach<int32>(count); 229 for (int32 i = 0; i < count; i++) 230 link.Attach<BRect>(clipping_region.RectAt(i)); 231 232 // Although we might have a 'local' clipping region, when we call 233 // BView::GetClippingRegion() we ask for the 'global' one and it 234 // is kept on server, so we must invalidate B_VIEW_CLIP_REGION_BIT flag 235 236 valid_flags = ~B_VIEW_CLIP_REGION_BIT; 237 } 238 239 240 void 241 ViewState::UpdateFrom(BPrivate::PortLink &link) 242 { 243 link.StartMessage(AS_LAYER_GET_STATE); 244 245 int32 code; 246 if (link.FlushWithReply(code) != B_OK 247 || code != SERVER_TRUE) 248 return; 249 250 uint32 fontID; 251 float size; 252 float shear; 253 float rotation; 254 uint8 spacing; 255 uint8 encoding; 256 uint16 face; 257 uint32 flags; 258 259 // read and set the font state 260 link.Read<int32>((int32 *)&fontID); 261 link.Read<float>(&size); 262 link.Read<float>(&shear); 263 link.Read<float>(&rotation); 264 link.Read<int8>((int8 *)&spacing); 265 link.Read<int8>((int8 *)&encoding); 266 link.Read<int16>((int16 *)&face); 267 link.Read<int32>((int32 *)&flags); 268 269 font_flags = B_FONT_ALL; 270 font.SetFamilyAndStyle(fontID); 271 font.SetSize(size); 272 font.SetShear(shear); 273 font.SetRotation(rotation); 274 font.SetSpacing(spacing); 275 font.SetEncoding(encoding); 276 font.SetFace(face); 277 font.SetFlags(flags); 278 279 // read and set view's state 280 link.Read<BPoint>(&pen_location); 281 link.Read<float>(&pen_size); 282 link.Read<rgb_color>(&high_color); 283 link.Read<rgb_color>(&low_color); 284 link.Read< ::pattern>(&pattern); 285 link.Read<BPoint>(&origin); 286 287 int8 drawingMode; 288 link.Read<int8>((int8 *)&drawingMode); 289 drawing_mode = (::drawing_mode)drawingMode; 290 291 link.Read<int8>((int8 *)&line_cap); 292 link.Read<int8>((int8 *)&line_join); 293 link.Read<float>(&miter_limit); 294 link.Read<int8>((int8 *)&alpha_source_mode); 295 link.Read<int8>((int8 *)&alpha_function_mode); 296 link.Read<float>(&scale); 297 link.Read<bool>(&font_aliasing); 298 299 // no need to read the clipping region, as it's invalid 300 // next time we need it anyway 301 302 valid_flags = ~B_VIEW_CLIP_REGION_BIT; 303 } 304 305 } // namespace BPrivate 306 307 308 // #pragma mark - 309 310 311 BView::BView(BRect frame, const char *name, uint32 resizingMode, uint32 flags) 312 : BHandler(name) 313 { 314 _InitData(frame, name, resizingMode, flags); 315 } 316 317 318 BView::BView(BMessage *archive) 319 : BHandler(archive) 320 { 321 uint32 resizingMode; 322 uint32 flags; 323 BRect frame; 324 325 archive->FindRect("_frame", &frame); 326 if (archive->FindInt32("_resize_mode", (int32 *)&resizingMode) != B_OK) 327 resizingMode = 0; 328 329 if (archive->FindInt32("_flags", (int32 *)&flags) != B_OK) 330 flags = 0; 331 332 _InitData(frame, Name(), resizingMode, flags); 333 334 font_family family; 335 font_style style; 336 if (archive->FindString("_fname", 0, (const char **)&family) == B_OK 337 && archive->FindString("_fname", 1, (const char **)&style) == B_OK) { 338 BFont font; 339 font.SetFamilyAndStyle(family, style); 340 341 float size; 342 if (archive->FindFloat("_fflt", 0, &size) == B_OK) 343 font.SetSize(size); 344 345 float shear; 346 if (archive->FindFloat("_fflt", 1, &shear) == B_OK) 347 font.SetShear(shear); 348 349 float rotation; 350 if (archive->FindFloat("_fflt", 2, &rotation) == B_OK) 351 font.SetRotation(rotation); 352 353 SetFont(&font, B_FONT_FAMILY_AND_STYLE | B_FONT_SIZE 354 | B_FONT_SHEAR | B_FONT_ROTATION); 355 } 356 357 rgb_color color; 358 if (archive->FindInt32("_color", 0, (int32 *)&color) == B_OK) 359 SetHighColor(color); 360 if (archive->FindInt32("_color", 1, (int32 *)&color) == B_OK) 361 SetLowColor(color); 362 if (archive->FindInt32("_color", 2, (int32 *)&color) == B_OK) 363 SetViewColor(color); 364 365 uint32 evMask; 366 uint32 options; 367 if (archive->FindInt32("_evmask", 0, (int32 *)&evMask) == B_OK 368 && archive->FindInt32("_evmask", 1, (int32 *)&options) == B_OK) 369 SetEventMask(evMask, options); 370 371 BPoint origin; 372 if (archive->FindPoint("_origin", &origin) == B_OK) 373 SetOrigin(origin); 374 375 float penSize; 376 if (archive->FindFloat("_psize", &penSize) == B_OK) 377 SetPenSize(penSize); 378 379 BPoint penLocation; 380 if (archive->FindPoint("_ploc", &penLocation) == B_OK) 381 MovePenTo(penLocation); 382 383 int16 lineCap; 384 int16 lineJoin; 385 float lineMiter; 386 if (archive->FindInt16("_lmcapjoin", 0, &lineCap) == B_OK 387 && archive->FindInt16("_lmcapjoin", 1, &lineJoin) == B_OK 388 && archive->FindFloat("_lmmiter", &lineMiter) == B_OK) 389 SetLineMode((cap_mode)lineCap, (join_mode)lineJoin, lineMiter); 390 391 int16 alphaBlend; 392 int16 modeBlend; 393 if (archive->FindInt16("_blend", 0, &alphaBlend) == B_OK 394 && archive->FindInt16("_blend", 1, &modeBlend) == B_OK) 395 SetBlendingMode( (source_alpha)alphaBlend, (alpha_function)modeBlend); 396 397 uint32 drawingMode; 398 if (archive->FindInt32("_dmod", (int32 *)&drawingMode) == B_OK) 399 SetDrawingMode((drawing_mode)drawingMode); 400 401 BMessage msg; 402 int32 i = 0; 403 while (archive->FindMessage("_views", i++, &msg) == B_OK) { 404 BArchivable *object = instantiate_object(&msg); 405 BView *child = dynamic_cast<BView *>(object); 406 if (child) 407 AddChild(child); 408 } 409 } 410 411 412 BArchivable * 413 BView::Instantiate(BMessage *data) 414 { 415 if (!validate_instantiation(data , "BView")) 416 return NULL; 417 418 return new BView(data); 419 } 420 421 422 status_t 423 BView::Archive(BMessage *data, bool deep) const 424 { 425 status_t retval = BHandler::Archive(data, deep); 426 if (retval != B_OK) 427 return retval; 428 429 if (fState->archiving_flags & B_VIEW_FRAME_BIT) 430 data->AddRect("_frame", Bounds().OffsetToCopy(fParentOffset)); 431 432 if (fState->archiving_flags & B_VIEW_RESIZE_BIT) 433 data->AddInt32("_resize_mode", ResizingMode()); 434 435 if (fState->archiving_flags & B_VIEW_FLAGS_BIT) 436 data->AddInt32("_flags", Flags()); 437 438 if (fState->archiving_flags & B_VIEW_EVENT_MASK_BIT) { 439 data->AddInt32("_evmask", fEventMask); 440 data->AddInt32("_evmask", fEventOptions); 441 } 442 443 if (fState->archiving_flags & B_VIEW_FONT_BIT) { 444 BFont font; 445 GetFont(&font); 446 447 font_family family; 448 font_style style; 449 font.GetFamilyAndStyle(&family, &style); 450 data->AddString("_fname", family); 451 data->AddString("_fname", style); 452 453 data->AddFloat("_fflt", font.Size()); 454 data->AddFloat("_fflt", font.Shear()); 455 data->AddFloat("_fflt", font.Rotation()); 456 } 457 458 // colors 459 460 if (fState->archiving_flags & B_VIEW_HIGH_COLOR_BIT) 461 data->AddInt32("_color", get_uint32_color(HighColor())); 462 463 if (fState->archiving_flags & B_VIEW_LOW_COLOR_BIT) 464 data->AddInt32("_color", get_uint32_color(LowColor())); 465 466 if (fState->archiving_flags & B_VIEW_VIEW_COLOR_BIT) 467 data->AddInt32("_color", get_uint32_color(ViewColor())); 468 469 // NOTE: we do not use this flag any more 470 // if ( 1 ){ 471 // data->AddInt32("_dbuf", 1); 472 // } 473 474 if (fState->archiving_flags & B_VIEW_ORIGIN_BIT) 475 data->AddPoint("_origin", Origin()); 476 477 if (fState->archiving_flags & B_VIEW_PEN_SIZE_BIT) 478 data->AddFloat("_psize", PenSize()); 479 480 if (fState->archiving_flags & B_VIEW_PEN_LOCATION_BIT) 481 data->AddPoint("_ploc", PenLocation()); 482 483 if (fState->archiving_flags & B_VIEW_LINE_MODES_BIT) { 484 data->AddInt16("_lmcapjoin", (int16)LineCapMode()); 485 data->AddInt16("_lmcapjoin", (int16)LineJoinMode()); 486 data->AddFloat("_lmmiter", LineMiterLimit()); 487 } 488 489 if (fState->archiving_flags & B_VIEW_BLENDING_BIT) { 490 source_alpha alphaSourceMode; 491 alpha_function alphaFunctionMode; 492 GetBlendingMode(&alphaSourceMode, &alphaFunctionMode); 493 494 data->AddInt16("_blend", (int16)alphaSourceMode); 495 data->AddInt16("_blend", (int16)alphaFunctionMode); 496 } 497 498 if (fState->archiving_flags & B_VIEW_DRAWING_MODE_BIT) 499 data->AddInt32("_dmod", DrawingMode()); 500 501 if (deep) { 502 int32 i = 0; 503 BView *child; 504 505 while ((child = ChildAt(i++)) != NULL) { 506 BMessage childArchive; 507 508 retval = child->Archive(&childArchive, deep); 509 if (retval == B_OK) 510 data->AddMessage("_views", &childArchive); 511 } 512 } 513 514 return retval; 515 } 516 517 518 BView::~BView() 519 { 520 STRACE(("BView(%s)::~BView()\n", this->Name())); 521 522 if (fOwner) 523 debugger("Trying to delete a view that belongs to a window. Call RemoveSelf first."); 524 525 RemoveSelf(); 526 527 // TODO: see about BShelf! must I delete it here? is it deleted by the window? 528 529 // we also delete all our children 530 531 BView *child = fFirstChild; 532 while (child) { 533 BView *nextChild = child->fNextSibling; 534 535 delete child; 536 child = nextChild; 537 } 538 539 if (fVerScroller) 540 fVerScroller->SetTarget((BView*)NULL); 541 if (fHorScroller) 542 fHorScroller->SetTarget((BView*)NULL); 543 544 SetName(NULL); 545 546 delete fState; 547 } 548 549 550 BRect 551 BView::Bounds() const 552 { 553 // do we need to update our bounds? 554 if (!fState->IsValid(B_VIEW_FRAME_BIT) && fOwner) { 555 check_lock(); 556 557 fOwner->fLink->StartMessage(AS_LAYER_GET_COORD); 558 559 int32 code; 560 if (fOwner->fLink->FlushWithReply(code) == B_OK 561 && code == SERVER_TRUE) { 562 fOwner->fLink->Read<BPoint>(const_cast<BPoint *>(&fParentOffset)); 563 fOwner->fLink->Read<BRect>(const_cast<BRect *>(&fBounds)); 564 fState->valid_flags |= B_VIEW_FRAME_BIT; 565 } 566 } 567 568 return fBounds; 569 } 570 571 572 void 573 BView::ConvertToParent(BPoint *point) const 574 { 575 if (!fParent) 576 return; 577 578 check_lock_no_pick(); 579 580 // TODO: handle scale 581 582 // our local coordinate transformation 583 *point -= Origin(); 584 585 // our bounds location within the parent 586 *point += fParentOffset; 587 } 588 589 590 BPoint 591 BView::ConvertToParent(BPoint point) const 592 { 593 ConvertToParent(&point); 594 595 return point; 596 } 597 598 599 void 600 BView::ConvertFromParent(BPoint *point) const 601 { 602 if (!fParent) 603 return; 604 605 check_lock_no_pick(); 606 607 // TODO: handle scale 608 609 // our bounds location within the parent 610 *point -= fParentOffset; 611 612 // our local coordinate transformation 613 *point += Origin(); 614 } 615 616 617 BPoint 618 BView::ConvertFromParent(BPoint point) const 619 { 620 ConvertFromParent(&point); 621 622 return point; 623 } 624 625 626 void 627 BView::ConvertToParent(BRect *rect) const 628 { 629 if (!fParent) 630 return; 631 632 check_lock_no_pick(); 633 634 // TODO: handle scale 635 636 BPoint origin = Origin(); 637 638 // our local coordinate transformation 639 rect->OffsetBy(-origin.x, -origin.y); 640 641 // our bounds location within the parent 642 rect->OffsetBy(fParentOffset); 643 } 644 645 646 BRect 647 BView::ConvertToParent(BRect rect) const 648 { 649 ConvertToParent(&rect); 650 651 return rect; 652 } 653 654 655 void 656 BView::ConvertFromParent(BRect *rect) const 657 { 658 if (!fParent) 659 return; 660 661 check_lock_no_pick(); 662 663 // TODO: handle scale 664 665 // our bounds location within the parent 666 rect->OffsetBy(-fParentOffset.x, -fParentOffset.y); 667 668 // our local coordinate transformation 669 rect->OffsetBy(Origin()); 670 } 671 672 673 BRect 674 BView::ConvertFromParent(BRect rect) const 675 { 676 ConvertFromParent(&rect); 677 678 return rect; 679 } 680 681 682 void 683 BView::ConvertToScreen(BPoint *pt) const 684 { 685 if (!fParent) { 686 if (fOwner) 687 fOwner->ConvertToScreen(pt); 688 689 return; 690 } 691 692 do_owner_check_no_pick(); 693 694 ConvertToParent(pt); 695 fParent->ConvertToScreen(pt); 696 } 697 698 699 BPoint 700 BView::ConvertToScreen(BPoint pt) const 701 { 702 ConvertToScreen(&pt); 703 704 return pt; 705 } 706 707 708 void 709 BView::ConvertFromScreen(BPoint *pt) const 710 { 711 if (!fParent) { 712 if (fOwner) 713 fOwner->ConvertFromScreen(pt); 714 715 return; 716 } 717 718 do_owner_check_no_pick(); 719 720 ConvertFromParent(pt); 721 fParent->ConvertFromScreen(pt); 722 } 723 724 725 BPoint 726 BView::ConvertFromScreen(BPoint pt) const 727 { 728 ConvertFromScreen(&pt); 729 730 return pt; 731 } 732 733 734 void 735 BView::ConvertToScreen(BRect *rect) const 736 { 737 if (!fParent) { 738 if (fOwner) 739 fOwner->ConvertToScreen(rect); 740 741 return; 742 } 743 744 do_owner_check_no_pick(); 745 746 ConvertToParent(rect); 747 fParent->ConvertToScreen(rect); 748 } 749 750 751 BRect 752 BView::ConvertToScreen(BRect rect) const 753 { 754 ConvertToScreen(&rect); 755 756 return rect; 757 } 758 759 760 void 761 BView::ConvertFromScreen(BRect *rect) const 762 { 763 if (!fParent) { 764 if (fOwner) 765 fOwner->ConvertFromScreen(rect); 766 767 return; 768 } 769 770 do_owner_check_no_pick(); 771 772 ConvertFromParent(rect); 773 fParent->ConvertFromScreen(rect); 774 } 775 776 777 BRect 778 BView::ConvertFromScreen(BRect rect) const 779 { 780 ConvertFromScreen(&rect); 781 782 return rect; 783 } 784 785 786 uint32 787 BView::Flags() const 788 { 789 check_lock_no_pick(); 790 return fFlags & ~_RESIZE_MASK_; 791 } 792 793 794 void 795 BView::SetFlags(uint32 flags) 796 { 797 if (Flags() == flags) 798 return; 799 800 if (fOwner) { 801 if (flags & B_PULSE_NEEDED) { 802 check_lock_no_pick(); 803 if (!fOwner->fPulseEnabled) 804 fOwner->SetPulseRate(500000); 805 } 806 807 if (flags & (B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE 808 | B_FRAME_EVENTS | B_SUBPIXEL_PRECISE)) { 809 check_lock(); 810 811 fOwner->fLink->StartMessage(AS_LAYER_SET_FLAGS); 812 fOwner->fLink->Attach<uint32>(flags); 813 } 814 } 815 816 /* Some useful info: 817 fFlags is a unsigned long (32 bits) 818 * bits 1-16 are used for BView's flags 819 * bits 17-32 are used for BView' resize mask 820 * _RESIZE_MASK_ is used for that. Look into View.h to see how 821 it's defined 822 */ 823 fFlags = (flags & ~_RESIZE_MASK_) | (fFlags & _RESIZE_MASK_); 824 825 fState->archiving_flags |= B_VIEW_FLAGS_BIT; 826 } 827 828 829 BRect 830 BView::Frame() const 831 { 832 check_lock_no_pick(); 833 834 return Bounds().OffsetToCopy(fParentOffset.x, fParentOffset.y); 835 } 836 837 838 void 839 BView::Hide() 840 { 841 if (fOwner && fShowLevel == 0) { 842 check_lock(); 843 fOwner->fLink->StartMessage(AS_LAYER_HIDE); 844 } 845 fShowLevel++; 846 } 847 848 849 void 850 BView::Show() 851 { 852 fShowLevel--; 853 if (fOwner && fShowLevel == 0) { 854 check_lock(); 855 fOwner->fLink->StartMessage(AS_LAYER_SHOW); 856 } 857 } 858 859 860 bool 861 BView::IsFocus() const 862 { 863 if (fOwner) { 864 check_lock_no_pick(); 865 return fOwner->CurrentFocus() == this; 866 } else 867 return false; 868 } 869 870 871 bool 872 BView::IsHidden(const BView *lookingFrom) const 873 { 874 if (fShowLevel > 0) 875 return true; 876 877 // may we be egocentric? 878 if (lookingFrom == this) 879 return false; 880 881 // we have the same visibility state as our 882 // parent, if there is one 883 if (fParent) 884 return fParent->IsHidden(lookingFrom); 885 886 // if we're the top view, and we're interested 887 // in the "global" view, we're inheriting the 888 // state of the window's visibility 889 if (fOwner && lookingFrom == NULL) 890 return fOwner->IsHidden(); 891 892 return false; 893 } 894 895 896 bool 897 BView::IsHidden() const 898 { 899 return IsHidden(NULL); 900 } 901 902 903 bool 904 BView::IsPrinting() const 905 { 906 return f_is_printing; 907 } 908 909 910 BPoint 911 BView::LeftTop() const 912 { 913 return fParentOffset; 914 } 915 916 917 void 918 BView::SetOrigin(BPoint pt) 919 { 920 SetOrigin(pt.x, pt.y); 921 } 922 923 924 void 925 BView::SetOrigin(float x, float y) 926 { 927 if (fState->IsValid(B_VIEW_ORIGIN_BIT) 928 && x == fState->origin.x && y == fState->origin.y) 929 return; 930 931 if (do_owner_check()) { 932 fOwner->fLink->StartMessage(AS_LAYER_SET_ORIGIN); 933 fOwner->fLink->Attach<float>(x); 934 fOwner->fLink->Attach<float>(y); 935 936 fState->valid_flags |= B_VIEW_ORIGIN_BIT; 937 } 938 939 // TODO: Bounds() is effected by SetOrigin() (?), 940 // so should we set the COORD_BIT too? 941 942 // our local coord system origin has changed, so when archiving we'll add this too 943 fState->archiving_flags |= B_VIEW_ORIGIN_BIT; 944 } 945 946 947 BPoint 948 BView::Origin() const 949 { 950 if (!fState->IsValid(B_VIEW_ORIGIN_BIT)) { 951 do_owner_check(); 952 953 fOwner->fLink->StartMessage(AS_LAYER_GET_ORIGIN); 954 955 int32 code; 956 if (fOwner->fLink->FlushWithReply(code) == B_OK 957 && code == SERVER_TRUE) { 958 fOwner->fLink->Read<BPoint>(&fState->origin); 959 960 fState->valid_flags |= B_VIEW_ORIGIN_BIT; 961 } 962 } 963 964 return fState->origin; 965 } 966 967 968 void 969 BView::SetResizingMode(uint32 mode) 970 { 971 if (fOwner) { 972 check_lock(); 973 974 fOwner->fLink->StartMessage(AS_LAYER_RESIZE_MODE); 975 fOwner->fLink->Attach<uint32>(mode); 976 } 977 978 // look at SetFlags() for more info on the below line 979 fFlags = (fFlags & ~_RESIZE_MASK_) | (mode & _RESIZE_MASK_); 980 981 // our resize mode has changed, so when archiving we'll add this too 982 fState->archiving_flags |= B_VIEW_RESIZE_BIT; 983 } 984 985 986 uint32 987 BView::ResizingMode() const 988 { 989 return fFlags & _RESIZE_MASK_; 990 } 991 992 993 void 994 BView::SetViewCursor(const BCursor *cursor, bool sync) 995 { 996 if (!cursor) 997 return; 998 999 if (!fOwner) 1000 debugger("View method requires owner and doesn't have one"); 1001 1002 check_lock(); 1003 1004 fOwner->fLink->StartMessage(AS_LAYER_CURSOR); 1005 fOwner->fLink->Attach<int32>(cursor->m_serverToken); 1006 1007 if (sync) 1008 fOwner->fLink->Flush(); 1009 } 1010 1011 1012 void 1013 BView::Flush(void) const 1014 { 1015 if (fOwner) 1016 fOwner->Flush(); 1017 } 1018 1019 1020 void 1021 BView::Sync(void) const 1022 { 1023 do_owner_check_no_pick(); 1024 if (fOwner) 1025 fOwner->Sync(); 1026 } 1027 1028 1029 BWindow * 1030 BView::Window() const 1031 { 1032 return fOwner; 1033 } 1034 1035 1036 // #pragma mark - 1037 // Hook Functions 1038 1039 1040 void 1041 BView::AttachedToWindow() 1042 { 1043 // Hook function 1044 STRACE(("\tHOOK: BView(%s)::AttachedToWindow()\n", Name())); 1045 } 1046 1047 1048 void 1049 BView::AllAttached() 1050 { 1051 // Hook function 1052 STRACE(("\tHOOK: BView(%s)::AllAttached()\n", Name())); 1053 } 1054 1055 1056 void 1057 BView::DetachedFromWindow() 1058 { 1059 // Hook function 1060 STRACE(("\tHOOK: BView(%s)::DetachedFromWindow()\n", Name())); 1061 } 1062 1063 1064 void 1065 BView::AllDetached() 1066 { 1067 // Hook function 1068 STRACE(("\tHOOK: BView(%s)::AllDetached()\n", Name())); 1069 } 1070 1071 1072 void 1073 BView::Draw(BRect updateRect) 1074 { 1075 // Hook function 1076 STRACE(("\tHOOK: BView(%s)::Draw()\n", Name())); 1077 } 1078 1079 1080 void 1081 BView::DrawAfterChildren(BRect r) 1082 { 1083 // HOOK function 1084 STRACE(("\tHOOK: BView(%s)::DrawAfterChildren()\n", Name())); 1085 } 1086 1087 1088 void 1089 BView::FrameMoved(BPoint newPosition) 1090 { 1091 // Hook function 1092 STRACE(("\tHOOK: BView(%s)::FrameMoved()\n", Name())); 1093 } 1094 1095 1096 void 1097 BView::FrameResized(float newWidth, float newHeight) 1098 { 1099 // Hook function 1100 STRACE(("\tHOOK: BView(%s)::FrameResized()\n", Name())); 1101 } 1102 1103 1104 void 1105 BView::GetPreferredSize(float* _width, float* _height) 1106 { 1107 STRACE(("\tHOOK: BView(%s)::GetPreferredSize()\n", Name())); 1108 1109 *_width = fBounds.Width(); 1110 *_height = fBounds.Height(); 1111 } 1112 1113 1114 void 1115 BView::ResizeToPreferred() 1116 { 1117 STRACE(("\tHOOK: BView(%s)::ResizeToPreferred()\n", Name())); 1118 1119 float width; 1120 float height; 1121 GetPreferredSize(&width, &height); 1122 1123 ResizeTo(width, height); 1124 } 1125 1126 1127 void 1128 BView::KeyDown(const char* bytes, int32 numBytes) 1129 { 1130 // Hook function 1131 STRACE(("\tHOOK: BView(%s)::KeyDown()\n", Name())); 1132 1133 if (Window()) 1134 Window()->_KeyboardNavigation(); 1135 } 1136 1137 1138 void 1139 BView::KeyUp(const char* bytes, int32 numBytes) 1140 { 1141 // Hook function 1142 STRACE(("\tHOOK: BView(%s)::KeyUp()\n", Name())); 1143 } 1144 1145 1146 void 1147 BView::MouseDown(BPoint where) 1148 { 1149 // Hook function 1150 STRACE(("\tHOOK: BView(%s)::MouseDown()\n", Name())); 1151 } 1152 1153 1154 void 1155 BView::MouseUp(BPoint where) 1156 { 1157 // Hook function 1158 STRACE(("\tHOOK: BView(%s)::MouseUp()\n", Name())); 1159 } 1160 1161 1162 void 1163 BView::MouseMoved(BPoint where, uint32 code, const BMessage* a_message) 1164 { 1165 // Hook function 1166 STRACE(("\tHOOK: BView(%s)::MouseMoved()\n", Name())); 1167 } 1168 1169 1170 void 1171 BView::Pulse() 1172 { 1173 // Hook function 1174 STRACE(("\tHOOK: BView(%s)::Pulse()\n", Name())); 1175 } 1176 1177 1178 void 1179 BView::TargetedByScrollView(BScrollView* scroll_view) 1180 { 1181 // Hook function 1182 STRACE(("\tHOOK: BView(%s)::TargetedByScrollView()\n", Name())); 1183 } 1184 1185 1186 void 1187 BView::WindowActivated(bool state) 1188 { 1189 // Hook function 1190 STRACE(("\tHOOK: BView(%s)::WindowActivated()\n", Name())); 1191 } 1192 1193 1194 // #pragma mark - 1195 // Input Functions 1196 1197 1198 void 1199 BView::BeginRectTracking(BRect startRect, uint32 style) 1200 { 1201 if (do_owner_check()) { 1202 fOwner->fLink->StartMessage(AS_LAYER_BEGIN_RECT_TRACK); 1203 fOwner->fLink->Attach<BRect>(startRect); 1204 fOwner->fLink->Attach<int32>(style); 1205 } 1206 } 1207 1208 1209 void 1210 BView::EndRectTracking() 1211 { 1212 if (do_owner_check()) 1213 fOwner->fLink->StartMessage(AS_LAYER_END_RECT_TRACK); 1214 } 1215 1216 1217 void 1218 BView::DragMessage(BMessage *message, BRect dragRect, BHandler *replyTo) 1219 { 1220 if (!message || !dragRect.IsValid()) 1221 return; 1222 1223 if (replyTo == NULL) 1224 replyTo = this; 1225 1226 if (replyTo->Looper() == NULL) 1227 debugger("DragMessage: warning - the Handler needs a looper"); 1228 1229 do_owner_check_no_pick(); 1230 1231 BPoint offset; 1232 1233 if (!message->HasInt32("buttons")) { 1234 BMessage *msg = fOwner->CurrentMessage(); 1235 uint32 buttons; 1236 1237 if (msg) { 1238 if (msg->FindInt32("buttons", (int32 *)&buttons) != B_OK) { 1239 BPoint point; 1240 GetMouse(&point, &buttons, false); 1241 } 1242 1243 BPoint point; 1244 if (msg->FindPoint("be:view_where", &point) == B_OK) 1245 offset = point - dragRect.LeftTop(); 1246 } else { 1247 BPoint point; 1248 GetMouse(&point, &buttons, false); 1249 } 1250 1251 message->AddInt32("buttons", buttons); 1252 } 1253 1254 #ifndef USING_MESSAGE4 1255 _set_message_reply_(message, BMessenger(replyTo, replyTo->Looper())); 1256 #else 1257 BMessage::Private(message).SetReply(BMessenger(replyTo, replyTo->Looper())); 1258 #endif 1259 1260 int32 bufferSize = message->FlattenedSize(); 1261 char *buffer = new char[bufferSize]; 1262 message->Flatten(buffer, bufferSize); 1263 1264 fOwner->fLink->StartMessage(AS_LAYER_DRAG_RECT); 1265 fOwner->fLink->Attach<BRect>(dragRect); 1266 fOwner->fLink->Attach<BPoint>(offset); 1267 fOwner->fLink->Attach<int32>(bufferSize); 1268 fOwner->fLink->Attach(buffer, bufferSize); 1269 fOwner->fLink->Flush(); 1270 1271 delete [] buffer; 1272 } 1273 1274 1275 void 1276 BView::DragMessage(BMessage *message, BBitmap *image, BPoint offset, 1277 BHandler *replyTo) 1278 { 1279 DragMessage(message, image, B_OP_COPY, offset, replyTo); 1280 } 1281 1282 1283 void 1284 BView::DragMessage(BMessage *message, BBitmap *image, 1285 drawing_mode dragMode, BPoint offset, BHandler *replyTo) 1286 { 1287 // ToDo: is this correct? Isn't \a image allowed to be NULL? 1288 if (message == NULL || image == NULL) 1289 return; 1290 1291 if (replyTo == NULL) 1292 replyTo = this; 1293 1294 if (replyTo->Looper() == NULL) 1295 debugger("DragMessage: warning - the Handler needs a looper"); 1296 1297 do_owner_check_no_pick(); 1298 1299 if (!message->HasInt32("buttons")) { 1300 BMessage *msg = fOwner->CurrentMessage(); 1301 uint32 buttons; 1302 1303 if (msg == NULL || msg->FindInt32("buttons", (int32 *)&buttons) != B_OK) { 1304 BPoint point; 1305 GetMouse(&point, &buttons, false); 1306 } 1307 1308 message->AddInt32("buttons", buttons); 1309 } 1310 1311 #ifndef USING_MESSAGE4 1312 _set_message_reply_(message, BMessenger(replyTo, replyTo->Looper())); 1313 #else 1314 BMessage::Private(message).SetReply(BMessenger(replyTo, replyTo->Looper())); 1315 #endif 1316 1317 int32 bufferSize = message->FlattenedSize(); 1318 char *buffer = new char[bufferSize]; 1319 message->Flatten(buffer, bufferSize); 1320 1321 fOwner->fLink->StartMessage(AS_LAYER_DRAG_IMAGE); 1322 fOwner->fLink->Attach<int32>(image->get_server_token()); 1323 fOwner->fLink->Attach<int32>((int32)dragMode); 1324 fOwner->fLink->Attach<BPoint>(offset); 1325 fOwner->fLink->Attach<int32>(bufferSize); 1326 fOwner->fLink->Attach(buffer, bufferSize); 1327 1328 delete [] buffer; 1329 1330 // TODO: in app_server the bitmap refCount must be incremented 1331 // WRITE this into specs!!!! 1332 1333 delete image; 1334 } 1335 1336 1337 void 1338 BView::GetMouse(BPoint *location, uint32 *buttons, bool checkMessageQueue) 1339 { 1340 do_owner_check(); 1341 1342 if (checkMessageQueue) { 1343 BMessageQueue *queue = Window()->MessageQueue(); 1344 queue->Lock(); 1345 1346 Window()->UpdateIfNeeded(); 1347 1348 // Look out for mouse update messages 1349 1350 BMessage *msg; 1351 for (int32 i = 0; (msg = queue->FindMessage(i)) != NULL; i++) { 1352 switch (msg->what) { 1353 case B_MOUSE_UP: 1354 case B_MOUSE_DOWN: 1355 case B_MOUSE_MOVED: 1356 msg->FindPoint("screen_where", location); 1357 msg->FindInt32("buttons", (int32 *)buttons); 1358 1359 ConvertFromScreen(location); 1360 1361 queue->RemoveMessage(msg); 1362 delete msg; 1363 1364 queue->Unlock(); 1365 return; 1366 } 1367 } 1368 queue->Unlock(); 1369 } 1370 1371 // If no mouse update message has been found in the message queue, 1372 // we get the current mouse location and buttons from the app_server 1373 1374 fOwner->fLink->StartMessage(AS_GET_MOUSE); 1375 1376 int32 code; 1377 if (fOwner->fLink->FlushWithReply(code) == B_OK 1378 && code == SERVER_TRUE) { 1379 fOwner->fLink->Read<BPoint>(location); 1380 fOwner->fLink->Read<uint32>(buttons); 1381 1382 // TODO: See above comment about coordinates 1383 ConvertFromScreen(location); 1384 } else 1385 buttons = 0; 1386 } 1387 1388 1389 void 1390 BView::MakeFocus(bool focusState) 1391 { 1392 if (fOwner) { 1393 // TODO: If this view has focus and focusState==false, 1394 // will there really be no other view with focus? No 1395 // cycling to the next one? 1396 BView *focus = fOwner->CurrentFocus(); 1397 if (focusState) { 1398 // Unfocus a previous focus view 1399 if (focus && focus != this) 1400 focus->MakeFocus(false); 1401 // if we want to make this view the current focus view 1402 fOwner->fFocus = this; 1403 fOwner->SetPreferredHandler(this); 1404 } else { 1405 // we want to unfocus this view, but only if it actually has focus 1406 if (focus == this) { 1407 fOwner->fFocus = NULL; 1408 fOwner->SetPreferredHandler(NULL); 1409 } 1410 } 1411 } 1412 } 1413 1414 1415 BScrollBar * 1416 BView::ScrollBar(orientation posture) const 1417 { 1418 switch (posture) { 1419 case B_VERTICAL: 1420 return fVerScroller; 1421 1422 case B_HORIZONTAL: 1423 return fHorScroller; 1424 1425 default: 1426 return NULL; 1427 } 1428 } 1429 1430 1431 void 1432 BView::ScrollBy(float dh, float dv) 1433 { 1434 // scrolling by fractional values is not supported, is it? 1435 dh = roundf(dh); 1436 dv = roundf(dv); 1437 1438 // no reason to process this further if no scroll is intended. 1439 if (dh == 0 && dv == 0) 1440 return; 1441 1442 check_lock(); 1443 1444 // if we're attached to a window tell app_server about this change 1445 if (fOwner) { 1446 fOwner->fLink->StartMessage(AS_LAYER_SCROLL); 1447 fOwner->fLink->Attach<float>(dh); 1448 fOwner->fLink->Attach<float>(dv); 1449 1450 fOwner->fLink->Flush(); 1451 1452 fState->valid_flags &= ~(B_VIEW_FRAME_BIT | B_VIEW_ORIGIN_BIT); 1453 } 1454 1455 // we modify our bounds rectangle by dh/dv coord units hor/ver. 1456 fBounds.OffsetBy(dh, dv); 1457 // fState->coordSysOrigin += BPoint(dh, dv); 1458 1459 // then set the new values of the scrollbars 1460 if (fHorScroller) 1461 fHorScroller->SetValue(fBounds.left); 1462 if (fVerScroller) 1463 fVerScroller->SetValue(fBounds.top); 1464 } 1465 1466 1467 void 1468 BView::ScrollTo(BPoint where) 1469 { 1470 ScrollBy(where.x - fBounds.left, where.y - fBounds.top); 1471 } 1472 1473 1474 status_t 1475 BView::SetEventMask(uint32 mask, uint32 options) 1476 { 1477 if (fEventMask == mask && fEventOptions == options) 1478 return B_ERROR; 1479 1480 fEventMask = mask | (fEventMask & 0xFFFF0000); 1481 fEventOptions = options; 1482 1483 fState->archiving_flags |= B_VIEW_EVENT_MASK_BIT; 1484 1485 if (fOwner) { 1486 check_lock(); 1487 1488 fOwner->fLink->StartMessage(AS_LAYER_SET_EVENT_MASK); 1489 fOwner->fLink->Attach<uint32>(mask); 1490 fOwner->fLink->Attach<uint32>(options); 1491 } 1492 1493 return B_OK; 1494 } 1495 1496 1497 uint32 1498 BView::EventMask() 1499 { 1500 return fEventMask; 1501 } 1502 1503 1504 status_t 1505 BView::SetMouseEventMask(uint32 mask, uint32 options) 1506 { 1507 // fEventMask = (mask << 16) | (fEventMask & 0x0000FFFF); 1508 // fEventOptions = (options << 16) | (options & 0x0000FFFF); 1509 1510 if (do_owner_check() 1511 && fOwner->CurrentMessage() 1512 && fOwner->CurrentMessage()->what == B_MOUSE_DOWN) { 1513 fOwner->fLink->StartMessage(AS_LAYER_SET_MOUSE_EVENT_MASK); 1514 fOwner->fLink->Attach<uint32>(mask); 1515 fOwner->fLink->Attach<uint32>(options); 1516 1517 return B_OK; 1518 } 1519 return B_ERROR; 1520 } 1521 1522 1523 // #pragma mark - 1524 // Graphic State Functions 1525 1526 1527 void 1528 BView::SetLineMode(cap_mode lineCap, join_mode lineJoin, float miterLimit) 1529 { 1530 if (fState->IsValid(B_VIEW_LINE_MODES_BIT) 1531 && lineCap == fState->line_cap && lineJoin == fState->line_join 1532 && miterLimit == fState->miter_limit) 1533 return; 1534 1535 if (fOwner) { 1536 check_lock(); 1537 1538 fOwner->fLink->StartMessage(AS_LAYER_SET_LINE_MODE); 1539 fOwner->fLink->Attach<int8>((int8)lineCap); 1540 fOwner->fLink->Attach<int8>((int8)lineJoin); 1541 fOwner->fLink->Attach<float>(miterLimit); 1542 1543 fState->valid_flags |= B_VIEW_LINE_MODES_BIT; 1544 } 1545 1546 fState->line_cap = lineCap; 1547 fState->line_join = lineJoin; 1548 fState->miter_limit = miterLimit; 1549 1550 fState->archiving_flags |= B_VIEW_LINE_MODES_BIT; 1551 } 1552 1553 1554 join_mode 1555 BView::LineJoinMode() const 1556 { 1557 // This will update the current state, if necessary 1558 if (!fState->IsValid(B_VIEW_LINE_MODES_BIT)) 1559 LineMiterLimit(); 1560 1561 return fState->line_join; 1562 } 1563 1564 1565 cap_mode 1566 BView::LineCapMode() const 1567 { 1568 // This will update the current state, if necessary 1569 if (!fState->IsValid(B_VIEW_LINE_MODES_BIT)) 1570 LineMiterLimit(); 1571 1572 return fState->line_cap; 1573 } 1574 1575 1576 float 1577 BView::LineMiterLimit() const 1578 { 1579 if (!fState->IsValid(B_VIEW_LINE_MODES_BIT) && fOwner) { 1580 check_lock(); 1581 1582 fOwner->fLink->StartMessage(AS_LAYER_GET_LINE_MODE); 1583 1584 int32 code; 1585 if (fOwner->fLink->FlushWithReply(code) == B_OK 1586 && code == SERVER_TRUE) { 1587 int8 cap, join; 1588 fOwner->fLink->Read<int8>((int8 *)&cap); 1589 fOwner->fLink->Read<int8>((int8 *)&join); 1590 fOwner->fLink->Read<float>(&fState->miter_limit); 1591 1592 fState->line_cap = (cap_mode)cap; 1593 fState->line_join = (join_mode)join; 1594 } 1595 1596 fState->valid_flags |= B_VIEW_LINE_MODES_BIT; 1597 } 1598 1599 return fState->miter_limit; 1600 } 1601 1602 1603 void 1604 BView::PushState() 1605 { 1606 do_owner_check(); 1607 1608 fOwner->fLink->StartMessage(AS_LAYER_PUSH_STATE); 1609 1610 // initialize origin and scale 1611 fState->valid_flags |= B_VIEW_SCALE_BIT | B_VIEW_ORIGIN_BIT; 1612 fState->scale = 1.0f; 1613 fState->origin.Set(0, 0); 1614 } 1615 1616 1617 void 1618 BView::PopState() 1619 { 1620 do_owner_check(); 1621 1622 fOwner->fLink->StartMessage(AS_LAYER_POP_STATE); 1623 1624 // invalidate all flags (except those that are not part of pop/push) 1625 fState->valid_flags = B_VIEW_VIEW_COLOR_BIT; 1626 } 1627 1628 1629 void 1630 BView::SetScale(float scale) const 1631 { 1632 if (fState->IsValid(B_VIEW_SCALE_BIT) && scale == fState->scale) 1633 return; 1634 1635 if (fOwner) { 1636 check_lock(); 1637 1638 fOwner->fLink->StartMessage(AS_LAYER_SET_SCALE); 1639 fOwner->fLink->Attach<float>(scale); 1640 1641 fState->valid_flags |= B_VIEW_SCALE_BIT; 1642 } 1643 1644 fState->scale = scale; 1645 fState->archiving_flags |= B_VIEW_SCALE_BIT; 1646 } 1647 1648 1649 float 1650 BView::Scale() const 1651 { 1652 if (!fState->IsValid(B_VIEW_SCALE_BIT) && fOwner) { 1653 check_lock(); 1654 1655 fOwner->fLink->StartMessage(AS_LAYER_GET_SCALE); 1656 1657 int32 code; 1658 if (fOwner->fLink->FlushWithReply(code) == B_OK 1659 && code == SERVER_TRUE) 1660 fOwner->fLink->Read<float>(&fState->scale); 1661 1662 fState->valid_flags |= B_VIEW_SCALE_BIT; 1663 } 1664 1665 return fState->scale; 1666 } 1667 1668 1669 void 1670 BView::SetDrawingMode(drawing_mode mode) 1671 { 1672 if (fState->IsValid(B_VIEW_DRAWING_MODE_BIT) 1673 && mode == fState->drawing_mode) 1674 return; 1675 1676 if (fOwner) { 1677 check_lock(); 1678 1679 fOwner->fLink->StartMessage(AS_LAYER_SET_DRAW_MODE); 1680 fOwner->fLink->Attach<int8>((int8)mode); 1681 1682 fState->valid_flags |= B_VIEW_DRAWING_MODE_BIT; 1683 } 1684 1685 fState->drawing_mode = mode; 1686 fState->archiving_flags |= B_VIEW_DRAWING_MODE_BIT; 1687 } 1688 1689 1690 drawing_mode 1691 BView::DrawingMode() const 1692 { 1693 if (!fState->IsValid(B_VIEW_DRAWING_MODE_BIT) && fOwner) { 1694 check_lock(); 1695 1696 fOwner->fLink->StartMessage(AS_LAYER_GET_DRAW_MODE); 1697 1698 int32 code; 1699 if (fOwner->fLink->FlushWithReply(code) == B_OK 1700 && code == SERVER_TRUE) { 1701 int8 drawingMode; 1702 fOwner->fLink->Read<int8>(&drawingMode); 1703 1704 fState->drawing_mode = (drawing_mode)drawingMode; 1705 fState->valid_flags |= B_VIEW_DRAWING_MODE_BIT; 1706 } 1707 } 1708 1709 return fState->drawing_mode; 1710 } 1711 1712 1713 void 1714 BView::SetBlendingMode(source_alpha sourceAlpha, alpha_function alphaFunction) 1715 { 1716 if (fState->IsValid(B_VIEW_BLENDING_BIT) 1717 && sourceAlpha == fState->alpha_source_mode 1718 && alphaFunction == fState->alpha_function_mode) 1719 return; 1720 1721 if (fOwner) { 1722 check_lock(); 1723 1724 fOwner->fLink->StartMessage(AS_LAYER_SET_BLEND_MODE); 1725 fOwner->fLink->Attach<int8>((int8)sourceAlpha); 1726 fOwner->fLink->Attach<int8>((int8)alphaFunction); 1727 1728 fState->valid_flags |= B_VIEW_BLENDING_BIT; 1729 } 1730 1731 fState->alpha_source_mode = sourceAlpha; 1732 fState->alpha_function_mode = alphaFunction; 1733 1734 fState->archiving_flags |= B_VIEW_BLENDING_BIT; 1735 } 1736 1737 1738 void 1739 BView::GetBlendingMode(source_alpha *_sourceAlpha, 1740 alpha_function *_alphaFunction) const 1741 { 1742 if (!fState->IsValid(B_VIEW_BLENDING_BIT) && fOwner) { 1743 check_lock(); 1744 1745 fOwner->fLink->StartMessage(AS_LAYER_GET_BLEND_MODE); 1746 1747 int32 code; 1748 if (fOwner->fLink->FlushWithReply(code) == B_OK 1749 && code == SERVER_TRUE) { 1750 int8 alphaSourceMode, alphaFunctionMode; 1751 fOwner->fLink->Read<int8>(&alphaSourceMode); 1752 fOwner->fLink->Read<int8>(&alphaFunctionMode); 1753 1754 fState->alpha_source_mode = (source_alpha)alphaSourceMode; 1755 fState->alpha_function_mode = (alpha_function)alphaFunctionMode; 1756 1757 fState->valid_flags |= B_VIEW_BLENDING_BIT; 1758 } 1759 } 1760 1761 if (_sourceAlpha) 1762 *_sourceAlpha = fState->alpha_source_mode; 1763 1764 if (_alphaFunction) 1765 *_alphaFunction = fState->alpha_function_mode; 1766 } 1767 1768 1769 void 1770 BView::MovePenTo(BPoint point) 1771 { 1772 MovePenTo(point.x, point.y); 1773 } 1774 1775 1776 void 1777 BView::MovePenTo(float x, float y) 1778 { 1779 if (fState->IsValid(B_VIEW_PEN_LOCATION_BIT) 1780 && x == fState->pen_location.x && y == fState->pen_location.y) 1781 return; 1782 1783 if (fOwner) { 1784 check_lock(); 1785 1786 fOwner->fLink->StartMessage(AS_LAYER_SET_PEN_LOC); 1787 fOwner->fLink->Attach<float>(x); 1788 fOwner->fLink->Attach<float>(y); 1789 1790 fState->valid_flags |= B_VIEW_PEN_LOCATION_BIT; 1791 } 1792 1793 fState->pen_location.x = x; 1794 fState->pen_location.y = y; 1795 1796 fState->archiving_flags |= B_VIEW_PEN_LOCATION_BIT; 1797 } 1798 1799 1800 void 1801 BView::MovePenBy(float x, float y) 1802 { 1803 // this will update the pen location if necessary 1804 if (!fState->IsValid(B_VIEW_PEN_LOCATION_BIT)) 1805 PenLocation(); 1806 1807 MovePenTo(fState->pen_location.x + x, fState->pen_location.y + y); 1808 } 1809 1810 1811 BPoint 1812 BView::PenLocation() const 1813 { 1814 if (!fState->IsValid(B_VIEW_PEN_LOCATION_BIT) && fOwner) { 1815 check_lock(); 1816 1817 fOwner->fLink->StartMessage(AS_LAYER_GET_PEN_LOC); 1818 1819 int32 code; 1820 if (fOwner->fLink->FlushWithReply(code) == B_OK 1821 && code == SERVER_TRUE) { 1822 fOwner->fLink->Read<BPoint>(&fState->pen_location); 1823 1824 fState->valid_flags |= B_VIEW_PEN_LOCATION_BIT; 1825 } 1826 } 1827 1828 return fState->pen_location; 1829 } 1830 1831 1832 void 1833 BView::SetPenSize(float size) 1834 { 1835 if (fState->IsValid(B_VIEW_PEN_SIZE_BIT) && size == fState->pen_size) 1836 return; 1837 1838 if (fOwner) { 1839 check_lock(); 1840 1841 fOwner->fLink->StartMessage(AS_LAYER_SET_PEN_SIZE); 1842 fOwner->fLink->Attach<float>(size); 1843 1844 fState->valid_flags |= B_VIEW_PEN_SIZE_BIT; 1845 } 1846 1847 fState->pen_size = size; 1848 fState->archiving_flags |= B_VIEW_PEN_SIZE_BIT; 1849 } 1850 1851 1852 float 1853 BView::PenSize() const 1854 { 1855 if (!fState->IsValid(B_VIEW_PEN_SIZE_BIT) && fOwner) { 1856 check_lock(); 1857 1858 fOwner->fLink->StartMessage(AS_LAYER_GET_PEN_SIZE); 1859 1860 int32 code; 1861 if (fOwner->fLink->FlushWithReply(code) == B_OK 1862 && code == SERVER_TRUE) { 1863 fOwner->fLink->Read<float>(&fState->pen_size); 1864 1865 fState->valid_flags |= B_VIEW_PEN_SIZE_BIT; 1866 } 1867 } 1868 1869 return fState->pen_size; 1870 } 1871 1872 1873 void 1874 BView::SetHighColor(rgb_color color) 1875 { 1876 // are we up-to-date already? 1877 if (fState->IsValid(B_VIEW_HIGH_COLOR_BIT) 1878 && fState->high_color == color) 1879 return; 1880 1881 if (fOwner) { 1882 check_lock(); 1883 1884 fOwner->fLink->StartMessage(AS_LAYER_SET_HIGH_COLOR); 1885 fOwner->fLink->Attach<rgb_color>(color); 1886 1887 fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT; 1888 } 1889 1890 set_rgb_color(fState->high_color, color.red, color.green, 1891 color.blue, color.alpha); 1892 1893 fState->archiving_flags |= B_VIEW_HIGH_COLOR_BIT; 1894 } 1895 1896 1897 rgb_color 1898 BView::HighColor() const 1899 { 1900 if (!fState->IsValid(B_VIEW_HIGH_COLOR_BIT) && fOwner) { 1901 check_lock(); 1902 1903 fOwner->fLink->StartMessage(AS_LAYER_GET_HIGH_COLOR); 1904 1905 int32 code; 1906 if (fOwner->fLink->FlushWithReply(code) == B_OK 1907 && code == SERVER_TRUE) { 1908 fOwner->fLink->Read<rgb_color>(&fState->high_color); 1909 1910 fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT; 1911 } 1912 } 1913 1914 return fState->high_color; 1915 } 1916 1917 1918 void 1919 BView::SetLowColor(rgb_color color) 1920 { 1921 if (fState->IsValid(B_VIEW_LOW_COLOR_BIT) 1922 && fState->low_color == color) 1923 return; 1924 1925 if (fOwner) { 1926 check_lock(); 1927 1928 fOwner->fLink->StartMessage(AS_LAYER_SET_LOW_COLOR); 1929 fOwner->fLink->Attach<rgb_color>(color); 1930 1931 fState->valid_flags |= B_VIEW_LOW_COLOR_BIT; 1932 } 1933 1934 set_rgb_color(fState->low_color, color.red, color.green, 1935 color.blue, color.alpha); 1936 1937 fState->archiving_flags |= B_VIEW_LOW_COLOR_BIT; 1938 } 1939 1940 1941 rgb_color 1942 BView::LowColor() const 1943 { 1944 if (!fState->IsValid(B_VIEW_LOW_COLOR_BIT) && fOwner) { 1945 check_lock(); 1946 1947 fOwner->fLink->StartMessage(AS_LAYER_GET_LOW_COLOR); 1948 1949 int32 code; 1950 if (fOwner->fLink->FlushWithReply(code) == B_OK 1951 && code == SERVER_TRUE) { 1952 fOwner->fLink->Read<rgb_color>(&fState->low_color); 1953 1954 fState->valid_flags |= B_VIEW_LOW_COLOR_BIT; 1955 } 1956 } 1957 1958 return fState->low_color; 1959 } 1960 1961 1962 void 1963 BView::SetViewColor(rgb_color color) 1964 { 1965 if (fState->IsValid(B_VIEW_VIEW_COLOR_BIT) && fState->view_color == color) 1966 return; 1967 1968 if (fOwner) { 1969 check_lock(); 1970 1971 fOwner->fLink->StartMessage(AS_LAYER_SET_VIEW_COLOR); 1972 fOwner->fLink->Attach<rgb_color>(color); 1973 1974 fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT; 1975 } 1976 1977 set_rgb_color(fState->view_color, color.red, color.green, 1978 color.blue, color.alpha); 1979 1980 fState->archiving_flags |= B_VIEW_VIEW_COLOR_BIT; 1981 } 1982 1983 1984 rgb_color 1985 BView::ViewColor() const 1986 { 1987 if (!fState->IsValid(B_VIEW_VIEW_COLOR_BIT) && fOwner) { 1988 check_lock(); 1989 1990 fOwner->fLink->StartMessage(AS_LAYER_GET_VIEW_COLOR); 1991 1992 int32 code; 1993 if (fOwner->fLink->FlushWithReply(code) == B_OK 1994 && code == SERVER_TRUE) { 1995 fOwner->fLink->Read<rgb_color>(&fState->view_color); 1996 1997 fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT; 1998 } 1999 } 2000 2001 return fState->view_color; 2002 } 2003 2004 2005 void 2006 BView::ForceFontAliasing(bool enable) 2007 { 2008 if (fState->IsValid(B_VIEW_FONT_ALIASING_BIT) && enable == fState->font_aliasing) 2009 return; 2010 2011 if (fOwner) { 2012 check_lock(); 2013 2014 fOwner->fLink->StartMessage(AS_LAYER_PRINT_ALIASING); 2015 fOwner->fLink->Attach<bool>(enable); 2016 2017 fState->valid_flags |= B_VIEW_FONT_ALIASING_BIT; 2018 } 2019 2020 fState->font_aliasing = enable; 2021 fState->archiving_flags |= B_VIEW_FONT_ALIASING_BIT; 2022 } 2023 2024 2025 void 2026 BView::SetFont(const BFont* font, uint32 mask) 2027 { 2028 if (!font || mask == 0) 2029 return; 2030 2031 if (mask == B_FONT_ALL) { 2032 fState->font = *font; 2033 } else { 2034 // ToDo: move this into a BFont method 2035 if (mask & B_FONT_FAMILY_AND_STYLE) 2036 fState->font.SetFamilyAndStyle(font->FamilyAndStyle()); 2037 2038 if (mask & B_FONT_SIZE) 2039 fState->font.SetSize(font->Size()); 2040 2041 if (mask & B_FONT_SHEAR) 2042 fState->font.SetShear(font->Shear()); 2043 2044 if (mask & B_FONT_ROTATION) 2045 fState->font.SetRotation(font->Rotation()); 2046 2047 if (mask & B_FONT_SPACING) 2048 fState->font.SetSpacing(font->Spacing()); 2049 2050 if (mask & B_FONT_ENCODING) 2051 fState->font.SetEncoding(font->Encoding()); 2052 2053 if (mask & B_FONT_FACE) 2054 fState->font.SetFace(font->Face()); 2055 2056 if (mask & B_FONT_FLAGS) 2057 fState->font.SetFlags(font->Flags()); 2058 } 2059 2060 fState->font_flags = mask; 2061 2062 if (fOwner) { 2063 check_lock(); 2064 do_owner_check(); 2065 2066 fState->UpdateServerFontState(*fOwner->fLink); 2067 } 2068 } 2069 2070 2071 #if !_PR3_COMPATIBLE_ 2072 void 2073 BView::GetFont(BFont *font) const 2074 #else 2075 void 2076 BView:GetFont(BFont *font) 2077 #endif 2078 { 2079 *font = fState->font; 2080 } 2081 2082 2083 void 2084 BView::GetFontHeight(font_height *height) const 2085 { 2086 fState->font.GetHeight(height); 2087 } 2088 2089 2090 void 2091 BView::SetFontSize(float size) 2092 { 2093 BFont font; 2094 font.SetSize(size); 2095 2096 SetFont(&font, B_FONT_SIZE); 2097 } 2098 2099 2100 float 2101 BView::StringWidth(const char *string) const 2102 { 2103 return fState->font.StringWidth(string); 2104 } 2105 2106 2107 float 2108 BView::StringWidth(const char* string, int32 length) const 2109 { 2110 return fState->font.StringWidth(string, length); 2111 } 2112 2113 2114 void 2115 BView::GetStringWidths(char *stringArray[],int32 lengthArray[], 2116 int32 numStrings, float widthArray[]) const 2117 { 2118 fState->font.GetStringWidths(const_cast<const char **>(stringArray), 2119 const_cast<const int32 *>(lengthArray), numStrings, widthArray); 2120 } 2121 2122 2123 void 2124 BView::TruncateString(BString *in_out, uint32 mode, float width) const 2125 { 2126 fState->font.TruncateString(in_out, mode, width); 2127 } 2128 2129 2130 void 2131 BView::ClipToPicture(BPicture *picture, BPoint where, bool sync) 2132 { 2133 DoPictureClip(picture, where, false, sync); 2134 } 2135 2136 2137 void 2138 BView::ClipToInversePicture(BPicture *picture, 2139 BPoint where, bool sync) 2140 { 2141 DoPictureClip(picture, where, true, sync); 2142 } 2143 2144 2145 void 2146 BView::GetClippingRegion(BRegion* region) const 2147 { 2148 if (!region) 2149 return; 2150 2151 // TODO: For now, the clipping bit is ignored, since the client has no 2152 // idea when the clipping in the server changed. -Stephan 2153 2154 // if (!fState->IsValid(B_VIEW_CLIP_REGION_BIT) && fOwner && do_owner_check()) { 2155 if (fOwner && do_owner_check()) { 2156 fOwner->fLink->StartMessage(AS_LAYER_GET_CLIP_REGION); 2157 2158 int32 code; 2159 if (fOwner->fLink->FlushWithReply(code) == B_OK 2160 && code == SERVER_TRUE) { 2161 int32 count; 2162 fOwner->fLink->Read<int32>(&count); 2163 2164 fState->clipping_region.MakeEmpty(); 2165 2166 for (int32 i = 0; i < count; i++) { 2167 BRect rect; 2168 fOwner->fLink->Read<BRect>(&rect); 2169 2170 fState->clipping_region.Include(rect); 2171 } 2172 fState->valid_flags |= B_VIEW_CLIP_REGION_BIT; 2173 } 2174 } else { 2175 fState->clipping_region.MakeEmpty(); 2176 } 2177 2178 *region = fState->clipping_region; 2179 } 2180 2181 2182 void 2183 BView::ConstrainClippingRegion(BRegion* region) 2184 { 2185 if (do_owner_check()) { 2186 int32 count = 0; 2187 if (region) 2188 count = region->CountRects(); 2189 2190 fOwner->fLink->StartMessage(AS_LAYER_SET_CLIP_REGION); 2191 2192 // '0' means that in the app_server, there won't be any 'local' 2193 // clipping region (it will be = NULL) 2194 2195 // TODO: note this in the specs 2196 fOwner->fLink->Attach<int32>(count); 2197 for (int32 i = 0; i < count; i++) 2198 fOwner->fLink->Attach<BRect>(region->RectAt(i)); 2199 2200 // we flush here because app_server waits for all the rects 2201 fOwner->fLink->Flush(); 2202 2203 fState->valid_flags &= ~B_VIEW_CLIP_REGION_BIT; 2204 fState->archiving_flags |= B_VIEW_CLIP_REGION_BIT; 2205 } 2206 } 2207 2208 2209 // #pragma mark - Drawing Functions 2210 //--------------------------------------------------------------------------- 2211 2212 2213 void 2214 BView::DrawBitmapAsync(const BBitmap *bitmap, BRect srcRect, BRect dstRect) 2215 { 2216 if (!bitmap || !srcRect.IsValid() || !dstRect.IsValid()) 2217 return; 2218 2219 if (fOwner) { 2220 check_lock(); 2221 2222 fOwner->fLink->StartMessage(AS_LAYER_DRAW_BITMAP_ASYNC_IN_RECT); 2223 fOwner->fLink->Attach<int32>(bitmap->get_server_token()); 2224 fOwner->fLink->Attach<BRect>(dstRect); 2225 fOwner->fLink->Attach<BRect>(srcRect); 2226 } 2227 } 2228 2229 2230 void 2231 BView::DrawBitmapAsync(const BBitmap *bitmap, BRect dstRect) 2232 { 2233 if (!bitmap || !dstRect.IsValid()) 2234 return; 2235 2236 DrawBitmapAsync(bitmap, bitmap->Bounds(), dstRect); 2237 } 2238 2239 2240 void 2241 BView::DrawBitmapAsync(const BBitmap *bitmap) 2242 { 2243 DrawBitmapAsync(bitmap, PenLocation()); 2244 } 2245 2246 2247 void 2248 BView::DrawBitmapAsync(const BBitmap *bitmap, BPoint where) 2249 { 2250 if (bitmap == NULL) 2251 return; 2252 2253 if (fOwner) { 2254 check_lock(); 2255 2256 fOwner->fLink->StartMessage(AS_LAYER_DRAW_BITMAP_ASYNC_AT_POINT); 2257 fOwner->fLink->Attach<int32>(bitmap->get_server_token()); 2258 fOwner->fLink->Attach<BPoint>(where); 2259 } 2260 } 2261 2262 2263 void 2264 BView::DrawBitmap(const BBitmap *bitmap) 2265 { 2266 DrawBitmap(bitmap, PenLocation()); 2267 } 2268 2269 2270 void 2271 BView::DrawBitmap(const BBitmap *bitmap, BPoint where) 2272 { 2273 if (bitmap == NULL) 2274 return; 2275 2276 if (fOwner) { 2277 check_lock(); 2278 2279 fOwner->fLink->StartMessage(AS_LAYER_DRAW_BITMAP_SYNC_AT_POINT); 2280 fOwner->fLink->Attach<int32>(bitmap->get_server_token()); 2281 fOwner->fLink->Attach<BPoint>(where); 2282 fOwner->fLink->Flush(); 2283 } 2284 } 2285 2286 2287 void 2288 BView::DrawBitmap(const BBitmap *bitmap, BRect dstRect) 2289 { 2290 if (!bitmap || !dstRect.IsValid()) 2291 return; 2292 2293 DrawBitmap(bitmap, bitmap->Bounds(), dstRect); 2294 } 2295 2296 2297 void 2298 BView::DrawBitmap(const BBitmap *bitmap, BRect srcRect, BRect dstRect) 2299 { 2300 if ( !bitmap || !srcRect.IsValid() || !dstRect.IsValid()) 2301 return; 2302 2303 if (fOwner) { 2304 check_lock(); 2305 2306 fOwner->fLink->StartMessage(AS_LAYER_DRAW_BITMAP_SYNC_IN_RECT); 2307 fOwner->fLink->Attach<int32>(bitmap->get_server_token()); 2308 fOwner->fLink->Attach<BRect>(dstRect); 2309 fOwner->fLink->Attach<BRect>(srcRect); 2310 fOwner->fLink->Flush(); 2311 } 2312 } 2313 2314 2315 void 2316 BView::DrawChar(char c) 2317 { 2318 DrawString(&c, 1, PenLocation()); 2319 } 2320 2321 2322 void 2323 BView::DrawChar(char c, BPoint location) 2324 { 2325 DrawString(&c, 1, location); 2326 } 2327 2328 2329 void 2330 BView::DrawString(const char *string, escapement_delta *delta) 2331 { 2332 DrawString(string, strlen(string), PenLocation(), delta); 2333 } 2334 2335 2336 void 2337 BView::DrawString(const char *string, BPoint location, escapement_delta *delta) 2338 { 2339 DrawString(string, strlen(string), location, delta); 2340 } 2341 2342 2343 void 2344 BView::DrawString(const char *string, int32 length, escapement_delta *delta) 2345 { 2346 DrawString(string, length, PenLocation(), delta); 2347 } 2348 2349 2350 void 2351 BView::DrawString(const char *string, int32 length, BPoint location, 2352 escapement_delta *delta) 2353 { 2354 if (string == NULL || length < 1) 2355 return; 2356 2357 if (fOwner) { 2358 check_lock(); 2359 2360 fOwner->fLink->StartMessage(AS_DRAW_STRING); 2361 fOwner->fLink->Attach<int32>(length); 2362 fOwner->fLink->Attach<BPoint>(location); 2363 2364 // Quite often delta will be NULL, so we have to accomodate this. 2365 if (delta) 2366 fOwner->fLink->Attach<escapement_delta>(*delta); 2367 else { 2368 escapement_delta tdelta; 2369 tdelta.space = 0; 2370 tdelta.nonspace = 0; 2371 2372 fOwner->fLink->Attach<escapement_delta>(tdelta); 2373 } 2374 2375 fOwner->fLink->AttachString(string, length); 2376 2377 // this modifies our pen location, so we invalidate the flag. 2378 fState->valid_flags &= ~B_VIEW_PEN_LOCATION_BIT; 2379 } 2380 } 2381 2382 2383 void 2384 BView::StrokeEllipse(BPoint center, float xRadius, float yRadius, 2385 pattern p) 2386 { 2387 StrokeEllipse(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius, 2388 center.y + yRadius), p); 2389 } 2390 2391 2392 void 2393 BView::StrokeEllipse(BRect rect, ::pattern pattern) 2394 { 2395 if (fOwner == NULL) 2396 return; 2397 2398 check_lock(); 2399 _UpdatePattern(pattern); 2400 2401 fOwner->fLink->StartMessage(AS_STROKE_ELLIPSE); 2402 fOwner->fLink->Attach<BRect>(rect); 2403 } 2404 2405 2406 void 2407 BView::FillEllipse(BPoint center, float xRadius, float yRadius, 2408 ::pattern pattern) 2409 { 2410 FillEllipse(BRect(center.x - xRadius, center.y - yRadius, 2411 center.x + xRadius, center.y + yRadius), pattern); 2412 } 2413 2414 2415 void 2416 BView::FillEllipse(BRect rect, ::pattern pattern) 2417 { 2418 if (fOwner == NULL) 2419 return; 2420 2421 check_lock(); 2422 _UpdatePattern(pattern); 2423 2424 fOwner->fLink->StartMessage(AS_FILL_ELLIPSE); 2425 fOwner->fLink->Attach<BRect>(rect); 2426 } 2427 2428 2429 void 2430 BView::StrokeArc(BPoint center, float xRadius, float yRadius, 2431 float startAngle, float arcAngle, pattern p) 2432 { 2433 StrokeArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius, 2434 center.y + yRadius), startAngle, arcAngle, p); 2435 } 2436 2437 2438 void 2439 BView::StrokeArc(BRect rect, float startAngle, float arcAngle, 2440 ::pattern pattern) 2441 { 2442 if (fOwner == NULL) 2443 return; 2444 2445 check_lock(); 2446 _UpdatePattern(pattern); 2447 2448 fOwner->fLink->StartMessage(AS_STROKE_ARC); 2449 fOwner->fLink->Attach<BRect>(rect); 2450 fOwner->fLink->Attach<float>(startAngle); 2451 fOwner->fLink->Attach<float>(arcAngle); 2452 } 2453 2454 2455 void 2456 BView::FillArc(BPoint center,float xRadius, float yRadius, 2457 float startAngle, float arcAngle, ::pattern pattern) 2458 { 2459 FillArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius, 2460 center.y + yRadius), startAngle, arcAngle, pattern); 2461 } 2462 2463 2464 void 2465 BView::FillArc(BRect rect, float startAngle, float arcAngle, 2466 ::pattern pattern) 2467 { 2468 if (fOwner == NULL) 2469 return; 2470 2471 check_lock(); 2472 _UpdatePattern(pattern); 2473 2474 fOwner->fLink->StartMessage(AS_FILL_ARC); 2475 fOwner->fLink->Attach<BRect>(rect); 2476 fOwner->fLink->Attach<float>(startAngle); 2477 fOwner->fLink->Attach<float>(arcAngle); 2478 } 2479 2480 2481 void 2482 BView::StrokeBezier(BPoint *controlPoints, ::pattern pattern) 2483 { 2484 if (fOwner == NULL) 2485 return; 2486 2487 check_lock(); 2488 _UpdatePattern(pattern); 2489 2490 fOwner->fLink->StartMessage(AS_STROKE_BEZIER); 2491 fOwner->fLink->Attach<BPoint>(controlPoints[0]); 2492 fOwner->fLink->Attach<BPoint>(controlPoints[1]); 2493 fOwner->fLink->Attach<BPoint>(controlPoints[2]); 2494 fOwner->fLink->Attach<BPoint>(controlPoints[3]); 2495 } 2496 2497 2498 void 2499 BView::FillBezier(BPoint *controlPoints, ::pattern pattern) 2500 { 2501 if (fOwner == NULL) 2502 return; 2503 2504 check_lock(); 2505 _UpdatePattern(pattern); 2506 2507 fOwner->fLink->StartMessage(AS_FILL_BEZIER); 2508 fOwner->fLink->Attach<BPoint>(controlPoints[0]); 2509 fOwner->fLink->Attach<BPoint>(controlPoints[1]); 2510 fOwner->fLink->Attach<BPoint>(controlPoints[2]); 2511 fOwner->fLink->Attach<BPoint>(controlPoints[3]); 2512 } 2513 2514 2515 void 2516 BView::StrokePolygon(const BPolygon *polygon, bool closed, pattern p) 2517 { 2518 if (!polygon) 2519 return; 2520 2521 StrokePolygon(polygon->fPts, polygon->fCount, polygon->Frame(), closed, p); 2522 } 2523 2524 2525 void 2526 BView::StrokePolygon(const BPoint *ptArray, int32 numPoints, bool closed, pattern p) 2527 { 2528 BPolygon polygon(ptArray, numPoints); 2529 2530 StrokePolygon(polygon.fPts, polygon.fCount, polygon.Frame(), closed, p); 2531 } 2532 2533 2534 void 2535 BView::StrokePolygon(const BPoint *ptArray, int32 numPoints, BRect bounds, 2536 bool closed, ::pattern pattern) 2537 { 2538 if (!ptArray 2539 || numPoints <= 1 2540 || fOwner == NULL) 2541 return; 2542 2543 check_lock(); 2544 _UpdatePattern(pattern); 2545 2546 BPolygon polygon(ptArray, numPoints); 2547 polygon.MapTo(polygon.Frame(), bounds); 2548 2549 if (fOwner->fLink->StartMessage(AS_STROKE_POLYGON, 2550 polygon.fCount * sizeof(BPoint) + sizeof(BRect) + sizeof(bool) + sizeof(int32)) 2551 == B_OK) { 2552 fOwner->fLink->Attach<BRect>(polygon.Frame()); 2553 fOwner->fLink->Attach<bool>(closed); 2554 fOwner->fLink->Attach<int32>(polygon.fCount); 2555 fOwner->fLink->Attach(polygon.fPts, polygon.fCount * sizeof(BPoint)); 2556 } else { 2557 // TODO: send via an area 2558 fprintf(stderr, "ERROR: polygon to big for BPortLink!\n"); 2559 } 2560 } 2561 2562 2563 void 2564 BView::FillPolygon(const BPolygon *polygon, ::pattern pattern) 2565 { 2566 if (polygon == NULL 2567 || polygon->fCount <= 2 2568 || fOwner == NULL) 2569 return; 2570 2571 check_lock(); 2572 _UpdatePattern(pattern); 2573 2574 if (fOwner->fLink->StartMessage(AS_FILL_POLYGON, 2575 polygon->fCount * sizeof(BPoint) + sizeof(BRect) + sizeof(int32)) == B_OK) { 2576 fOwner->fLink->Attach<BRect>(polygon->Frame()); 2577 fOwner->fLink->Attach<int32>(polygon->fCount); 2578 fOwner->fLink->Attach(polygon->fPts, polygon->fCount * sizeof(BPoint)); 2579 } else { 2580 // TODO: send via an area 2581 fprintf(stderr, "ERROR: polygon to big for BPortLink!\n"); 2582 } 2583 } 2584 2585 2586 void 2587 BView::FillPolygon(const BPoint *ptArray, int32 numPts, ::pattern pattern) 2588 { 2589 if (!ptArray) 2590 return; 2591 2592 BPolygon polygon(ptArray, numPts); 2593 FillPolygon(&polygon, pattern); 2594 } 2595 2596 2597 void 2598 BView::FillPolygon(const BPoint *ptArray, int32 numPts, BRect bounds, 2599 pattern p) 2600 { 2601 if (!ptArray) 2602 return; 2603 2604 BPolygon polygon(ptArray, numPts); 2605 2606 polygon.MapTo(polygon.Frame(), bounds); 2607 FillPolygon(&polygon, p); 2608 } 2609 2610 2611 void 2612 BView::StrokeRect(BRect rect, ::pattern pattern) 2613 { 2614 if (fOwner == NULL) 2615 return; 2616 2617 check_lock(); 2618 _UpdatePattern(pattern); 2619 2620 fOwner->fLink->StartMessage(AS_STROKE_RECT); 2621 fOwner->fLink->Attach<BRect>(rect); 2622 } 2623 2624 2625 void 2626 BView::FillRect(BRect rect, ::pattern pattern) 2627 { 2628 if (fOwner == NULL) 2629 return; 2630 2631 check_lock(); 2632 _UpdatePattern(pattern); 2633 2634 fOwner->fLink->StartMessage(AS_FILL_RECT); 2635 fOwner->fLink->Attach<BRect>(rect); 2636 } 2637 2638 2639 void 2640 BView::StrokeRoundRect(BRect rect, float xRadius, float yRadius, 2641 ::pattern pattern) 2642 { 2643 if (fOwner == NULL) 2644 return; 2645 2646 check_lock(); 2647 _UpdatePattern(pattern); 2648 2649 fOwner->fLink->StartMessage(AS_STROKE_ROUNDRECT); 2650 fOwner->fLink->Attach<BRect>(rect); 2651 fOwner->fLink->Attach<float>(xRadius); 2652 fOwner->fLink->Attach<float>(yRadius); 2653 } 2654 2655 2656 void 2657 BView::FillRoundRect(BRect rect, float xRadius, float yRadius, 2658 ::pattern pattern) 2659 { 2660 if (fOwner == NULL) 2661 return; 2662 2663 check_lock(); 2664 2665 _UpdatePattern(pattern); 2666 2667 fOwner->fLink->StartMessage(AS_FILL_ROUNDRECT); 2668 fOwner->fLink->Attach<BRect>(rect); 2669 fOwner->fLink->Attach<float>(xRadius); 2670 fOwner->fLink->Attach<float>(yRadius); 2671 } 2672 2673 2674 void 2675 BView::FillRegion(BRegion *region, ::pattern pattern) 2676 { 2677 if (region == NULL || fOwner == NULL) 2678 return; 2679 2680 check_lock(); 2681 2682 _UpdatePattern(pattern); 2683 2684 int32 count = region->CountRects(); 2685 2686 if (count * sizeof(BRect) < MAX_ATTACHMENT_SIZE) { 2687 fOwner->fLink->StartMessage(AS_FILL_REGION); 2688 fOwner->fLink->Attach<int32>(count); 2689 2690 for (int32 i = 0; i < count; i++) 2691 fOwner->fLink->Attach<BRect>(region->RectAt(i)); 2692 } else { 2693 // TODO: send via area 2694 } 2695 } 2696 2697 2698 void 2699 BView::StrokeTriangle(BPoint pt1, BPoint pt2, BPoint pt3, 2700 BRect bounds, ::pattern pattern) 2701 { 2702 if (fOwner == NULL) 2703 return; 2704 2705 check_lock(); 2706 2707 _UpdatePattern(pattern); 2708 2709 fOwner->fLink->StartMessage(AS_STROKE_TRIANGLE); 2710 fOwner->fLink->Attach<BPoint>(pt1); 2711 fOwner->fLink->Attach<BPoint>(pt2); 2712 fOwner->fLink->Attach<BPoint>(pt3); 2713 fOwner->fLink->Attach<BRect>(bounds); 2714 } 2715 2716 2717 void 2718 BView::StrokeTriangle(BPoint pt1, BPoint pt2, BPoint pt3, pattern p) 2719 { 2720 if (fOwner) { 2721 // we construct the smallest rectangle that contains the 3 points 2722 // for the 1st point 2723 BRect bounds(pt1, pt1); 2724 2725 // for the 2nd point 2726 if (pt2.x < bounds.left) 2727 bounds.left = pt2.x; 2728 2729 if (pt2.y < bounds.top) 2730 bounds.top = pt2.y; 2731 2732 if (pt2.x > bounds.right) 2733 bounds.right = pt2.x; 2734 2735 if (pt2.y > bounds.bottom) 2736 bounds.bottom = pt2.y; 2737 2738 // for the 3rd point 2739 if (pt3.x < bounds.left) 2740 bounds.left = pt3.x; 2741 2742 if (pt3.y < bounds.top) 2743 bounds.top = pt3.y; 2744 2745 if (pt3.x > bounds.right) 2746 bounds.right = pt3.x; 2747 2748 if (pt3.y > bounds.bottom) 2749 bounds.bottom = pt3.y; 2750 2751 StrokeTriangle(pt1, pt2, pt3, bounds, p); 2752 } 2753 } 2754 2755 2756 void 2757 BView::FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3, pattern p) 2758 { 2759 if (fOwner) { 2760 // we construct the smallest rectangle that contains the 3 points 2761 // for the 1st point 2762 BRect bounds(pt1, pt1); 2763 2764 // for the 2nd point 2765 if (pt2.x < bounds.left) 2766 bounds.left = pt2.x; 2767 2768 if (pt2.y < bounds.top) 2769 bounds.top = pt2.y; 2770 2771 if (pt2.x > bounds.right) 2772 bounds.right = pt2.x; 2773 2774 if (pt2.y > bounds.bottom) 2775 bounds.bottom = pt2.y; 2776 2777 // for the 3rd point 2778 if (pt3.x < bounds.left) 2779 bounds.left = pt3.x; 2780 2781 if (pt3.y < bounds.top) 2782 bounds.top = pt3.y; 2783 2784 if (pt3.x > bounds.right) 2785 bounds.right = pt3.x; 2786 2787 if (pt3.y > bounds.bottom) 2788 bounds.bottom = pt3.y; 2789 2790 FillTriangle(pt1, pt2, pt3, bounds, p); 2791 } 2792 } 2793 2794 2795 void 2796 BView::FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3, 2797 BRect bounds, ::pattern pattern) 2798 { 2799 if (fOwner == NULL) 2800 return; 2801 2802 check_lock(); 2803 _UpdatePattern(pattern); 2804 2805 fOwner->fLink->StartMessage(AS_FILL_TRIANGLE); 2806 fOwner->fLink->Attach<BPoint>(pt1); 2807 fOwner->fLink->Attach<BPoint>(pt2); 2808 fOwner->fLink->Attach<BPoint>(pt3); 2809 fOwner->fLink->Attach<BRect>(bounds); 2810 } 2811 2812 2813 void 2814 BView::StrokeLine(BPoint toPt, pattern p) 2815 { 2816 StrokeLine(PenLocation(), toPt, p); 2817 } 2818 2819 2820 void 2821 BView::StrokeLine(BPoint pt0, BPoint pt1, ::pattern pattern) 2822 { 2823 if (fOwner == NULL) 2824 return; 2825 2826 check_lock(); 2827 _UpdatePattern(pattern); 2828 2829 fOwner->fLink->StartMessage(AS_STROKE_LINE); 2830 fOwner->fLink->Attach<BPoint>(pt0); 2831 fOwner->fLink->Attach<BPoint>(pt1); 2832 2833 // this modifies our pen location, so we invalidate the flag. 2834 fState->valid_flags &= ~B_VIEW_PEN_LOCATION_BIT; 2835 } 2836 2837 2838 void 2839 BView::StrokeShape(BShape *shape, ::pattern pattern) 2840 { 2841 if (shape == NULL || fOwner == NULL) 2842 return; 2843 2844 shape_data *sd = (shape_data *)shape->fPrivateData; 2845 if (sd->opCount == 0 || sd->ptCount == 0) 2846 return; 2847 2848 check_lock(); 2849 _UpdatePattern(pattern); 2850 2851 if ((sd->opCount * sizeof(uint32)) + (sd->ptCount * sizeof(BPoint)) < MAX_ATTACHMENT_SIZE) { 2852 fOwner->fLink->StartMessage(AS_STROKE_SHAPE); 2853 fOwner->fLink->Attach<BRect>(shape->Bounds()); 2854 fOwner->fLink->Attach<int32>(sd->opCount); 2855 fOwner->fLink->Attach<int32>(sd->ptCount); 2856 fOwner->fLink->Attach(sd->opList, sd->opCount * sizeof(uint32)); 2857 fOwner->fLink->Attach(sd->ptList, sd->ptCount * sizeof(BPoint)); 2858 } else { 2859 // TODO: send via an area 2860 } 2861 } 2862 2863 2864 void 2865 BView::FillShape(BShape *shape, ::pattern pattern) 2866 { 2867 if (shape == NULL || fOwner == NULL) 2868 return; 2869 2870 shape_data *sd = (shape_data *)(shape->fPrivateData); 2871 if (sd->opCount == 0 || sd->ptCount == 0) 2872 return; 2873 2874 check_lock(); 2875 _UpdatePattern(pattern); 2876 2877 if ((sd->opCount * sizeof(uint32)) + (sd->ptCount * sizeof(BPoint)) < MAX_ATTACHMENT_SIZE) { 2878 fOwner->fLink->StartMessage(AS_FILL_SHAPE); 2879 fOwner->fLink->Attach<BRect>(shape->Bounds()); 2880 fOwner->fLink->Attach<int32>(sd->opCount); 2881 fOwner->fLink->Attach<int32>(sd->ptCount); 2882 fOwner->fLink->Attach(sd->opList, sd->opCount * sizeof(int32)); 2883 fOwner->fLink->Attach(sd->ptList, sd->ptCount * sizeof(BPoint)); 2884 } else { 2885 // TODO: send via an area 2886 // BTW, in a perfect world, the fLink API would take care of that -- axeld. 2887 } 2888 } 2889 2890 2891 void 2892 BView::BeginLineArray(int32 count) 2893 { 2894 if (fOwner == NULL) 2895 return; 2896 2897 if (count <= 0) 2898 debugger("Calling BeginLineArray with a count <= 0"); 2899 2900 check_lock_no_pick(); 2901 2902 if (comm) { 2903 delete [] comm->array; 2904 delete comm; 2905 } 2906 2907 comm = new _array_data_; 2908 2909 comm->maxCount = count; 2910 comm->count = 0; 2911 comm->array = new _array_hdr_[count]; 2912 } 2913 2914 2915 void 2916 BView::AddLine(BPoint pt0, BPoint pt1, rgb_color col) 2917 { 2918 if (fOwner == NULL) 2919 return; 2920 2921 if (!comm) 2922 debugger("BeginLineArray must be called before using AddLine"); 2923 2924 check_lock_no_pick(); 2925 2926 if (comm->count < comm->maxCount) { 2927 comm->array[comm->count].startX = pt0.x; 2928 comm->array[comm->count].startY = pt0.y; 2929 comm->array[comm->count].endX = pt1.x; 2930 comm->array[comm->count].endY = pt1.y; 2931 2932 set_rgb_color(comm->array[comm->count].color, 2933 col.red, col.green, col.blue, col.alpha); 2934 2935 comm->count++; 2936 } 2937 } 2938 2939 2940 void 2941 BView::EndLineArray() 2942 { 2943 if (fOwner == NULL) 2944 return; 2945 2946 if (!comm) 2947 debugger("Can't call EndLineArray before BeginLineArray"); 2948 2949 check_lock(); 2950 2951 fOwner->fLink->StartMessage(AS_STROKE_LINEARRAY); 2952 fOwner->fLink->Attach<int32>(comm->count); 2953 fOwner->fLink->Attach(comm->array, comm->count * sizeof(_array_hdr_)); 2954 2955 delete [] comm->array; 2956 delete comm; 2957 comm = NULL; 2958 } 2959 2960 2961 void 2962 BView::BeginPicture(BPicture *picture) 2963 { 2964 if (do_owner_check() && picture && picture->usurped == NULL) { 2965 picture->usurp(cpicture); 2966 cpicture = picture; 2967 2968 fOwner->fLink->StartMessage(AS_LAYER_BEGIN_PICTURE); 2969 } 2970 } 2971 2972 2973 void 2974 BView::AppendToPicture(BPicture *picture) 2975 { 2976 check_lock(); 2977 2978 if (picture && picture->usurped == NULL) { 2979 int32 token = picture->token; 2980 2981 if (token == -1) { 2982 BeginPicture(picture); 2983 } else { 2984 picture->usurped = cpicture; 2985 picture->set_token(-1); 2986 fOwner->fLink->StartMessage(AS_LAYER_APPEND_TO_PICTURE); 2987 fOwner->fLink->Attach<int32>(token); 2988 } 2989 } 2990 } 2991 2992 2993 BPicture * 2994 BView::EndPicture() 2995 { 2996 if (do_owner_check() && cpicture) { 2997 int32 token; 2998 2999 fOwner->fLink->StartMessage(AS_LAYER_END_PICTURE); 3000 3001 int32 code; 3002 if (fOwner->fLink->FlushWithReply(code) == B_OK 3003 && code == SERVER_TRUE 3004 && fOwner->fLink->Read<int32>(&token) == B_OK) { 3005 BPicture *picture = cpicture; 3006 cpicture = picture->step_down(); 3007 picture->set_token(token); 3008 3009 return picture; 3010 } 3011 } 3012 3013 return NULL; 3014 } 3015 3016 3017 void 3018 BView::SetViewBitmap(const BBitmap *bitmap, BRect srcRect, BRect dstRect, 3019 uint32 followFlags, uint32 options) 3020 { 3021 _SetViewImage(bitmap, srcRect, dstRect, followFlags, options); 3022 } 3023 3024 3025 void 3026 BView::SetViewBitmap(const BBitmap *bitmap, uint32 followFlags, uint32 options) 3027 { 3028 BRect rect; 3029 if (bitmap) 3030 rect = bitmap->Bounds(); 3031 3032 rect.OffsetTo(0, 0); 3033 3034 _SetViewImage(bitmap, rect, rect, followFlags, options); 3035 } 3036 3037 3038 void 3039 BView::ClearViewBitmap() 3040 { 3041 _SetViewImage(NULL, BRect(), BRect(), 0, 0); 3042 } 3043 3044 3045 status_t 3046 BView::SetViewOverlay(const BBitmap *overlay, BRect srcRect, BRect dstRect, 3047 rgb_color *colorKey, uint32 followFlags, uint32 options) 3048 { 3049 status_t err = _SetViewImage(overlay, srcRect, dstRect, followFlags, 3050 options | 0x4); 3051 3052 // TODO: Incomplete? 3053 3054 // read the color that will be treated as transparent 3055 fOwner->fLink->Read<rgb_color>(colorKey); 3056 3057 return err; 3058 } 3059 3060 3061 status_t 3062 BView::SetViewOverlay(const BBitmap *overlay, rgb_color *colorKey, 3063 uint32 followFlags, uint32 options) 3064 { 3065 BRect rect; 3066 if (overlay) 3067 rect = overlay->Bounds(); 3068 3069 rect.OffsetTo(0, 0); 3070 3071 status_t err = _SetViewImage(overlay, rect, rect, followFlags, 3072 options | 0x4); 3073 3074 // TODO: Incomplete? 3075 3076 // read the color that will be treated as transparent 3077 fOwner->fLink->Read<rgb_color>(colorKey); 3078 3079 return err; 3080 } 3081 3082 3083 void 3084 BView::ClearViewOverlay() 3085 { 3086 _SetViewImage(NULL, BRect(), BRect(), 0, 0); 3087 } 3088 3089 3090 void 3091 BView::CopyBits(BRect src, BRect dst) 3092 { 3093 if (!src.IsValid() || !dst.IsValid()) 3094 return; 3095 3096 if (do_owner_check()) { 3097 fOwner->fLink->StartMessage(AS_LAYER_COPY_BITS); 3098 fOwner->fLink->Attach<BRect>(src); 3099 fOwner->fLink->Attach<BRect>(dst); 3100 } 3101 } 3102 3103 3104 void 3105 BView::DrawPicture(const BPicture *picture) 3106 { 3107 if (picture == NULL) 3108 return; 3109 3110 DrawPictureAsync(picture, PenLocation()); 3111 fOwner->fLink->Attach<int32>(SERVER_TRUE); 3112 3113 // ToDo: why a reply? 3114 int32 code; 3115 if (fOwner->fLink->FlushWithReply(code) == B_OK 3116 && code == SERVER_TRUE) { 3117 status_t err; 3118 fOwner->fLink->Read<int32>(&err); 3119 } 3120 } 3121 3122 3123 void 3124 BView::DrawPicture(const BPicture *picture, BPoint where) 3125 { 3126 if (picture == NULL) 3127 return; 3128 3129 DrawPictureAsync(picture, where); 3130 fOwner->fLink->Attach<int32>(SERVER_TRUE); 3131 3132 // ToDo: why a reply? 3133 int32 code; 3134 if (fOwner->fLink->FlushWithReply(code) == B_OK 3135 && code == SERVER_TRUE) { 3136 status_t err; 3137 fOwner->fLink->Read<int32>(&err); 3138 } 3139 } 3140 3141 3142 void 3143 BView::DrawPicture(const char *filename, long offset, BPoint where) 3144 { 3145 if (!filename) 3146 return; 3147 3148 DrawPictureAsync(filename, offset, where); 3149 fOwner->fLink->Attach<int32>(SERVER_TRUE); 3150 3151 // ToDo: why a reply? 3152 int32 code; 3153 if (fOwner->fLink->FlushWithReply(code) == B_OK 3154 && code == SERVER_TRUE) { 3155 status_t err; 3156 fOwner->fLink->Read<int32>(&err); 3157 } 3158 } 3159 3160 3161 void 3162 BView::DrawPictureAsync(const BPicture *picture) 3163 { 3164 if (picture == NULL) 3165 return; 3166 3167 DrawPictureAsync(picture, PenLocation()); 3168 } 3169 3170 3171 void 3172 BView::DrawPictureAsync(const BPicture *picture, BPoint where) 3173 { 3174 if (picture == NULL) 3175 return; 3176 3177 if (do_owner_check() && picture->token > 0) { 3178 fOwner->fLink->StartMessage(AS_LAYER_DRAW_PICTURE); 3179 fOwner->fLink->Attach<int32>(picture->token); 3180 fOwner->fLink->Attach<BPoint>(where); 3181 } 3182 } 3183 3184 3185 void 3186 BView::DrawPictureAsync(const char *filename, long offset, BPoint where) 3187 { 3188 if (!filename) 3189 return; 3190 3191 // TODO: test and implement 3192 } 3193 3194 3195 void 3196 BView::Invalidate(BRect invalRect) 3197 { 3198 if (!invalRect.IsValid() || fOwner == NULL) 3199 return; 3200 3201 check_lock(); 3202 3203 fOwner->fLink->StartMessage(AS_LAYER_INVAL_RECT); 3204 fOwner->fLink->Attach<BRect>(invalRect); 3205 fOwner->fLink->Flush(); 3206 } 3207 3208 3209 void 3210 BView::Invalidate(const BRegion *invalRegion) 3211 { 3212 if (invalRegion == NULL || fOwner == NULL) 3213 return; 3214 3215 check_lock(); 3216 3217 int32 count = 0; 3218 count = const_cast<BRegion*>(invalRegion)->CountRects(); 3219 3220 fOwner->fLink->StartMessage(AS_LAYER_INVAL_REGION); 3221 fOwner->fLink->Attach<int32>(count); 3222 3223 for (int32 i = 0; i < count; i++) 3224 fOwner->fLink->Attach<BRect>( const_cast<BRegion *>(invalRegion)->RectAt(i)); 3225 3226 fOwner->fLink->Flush(); 3227 } 3228 3229 3230 void 3231 BView::Invalidate() 3232 { 3233 Invalidate(Bounds()); 3234 } 3235 3236 3237 void 3238 BView::InvertRect(BRect rect) 3239 { 3240 if (fOwner) { 3241 check_lock(); 3242 3243 fOwner->fLink->StartMessage(AS_LAYER_INVERT_RECT); 3244 fOwner->fLink->Attach<BRect>(rect); 3245 } 3246 } 3247 3248 3249 // #pragma mark - 3250 // View Hierarchy Functions 3251 3252 3253 void 3254 BView::AddChild(BView *child, BView *before) 3255 { 3256 STRACE(("BView(%s)::AddChild(child='%s' before='%s')\n", 3257 this->Name() ? this->Name(): "NULL", 3258 child && child->Name() ? child->Name(): "NULL", 3259 before && before->Name() ? before->Name(): "NULL")); 3260 3261 if (!child) 3262 return; 3263 3264 if (child->fParent != NULL) 3265 debugger("AddChild failed - the view already has a parent."); 3266 3267 bool lockedOwner = false; 3268 if (fOwner && !fOwner->IsLocked()) { 3269 fOwner->Lock(); 3270 lockedOwner = true; 3271 } 3272 3273 if (!_AddChildToList(child, before)) 3274 debugger("AddChild failed - cannot find 'before' view."); 3275 3276 if (fOwner) { 3277 check_lock(); 3278 3279 STRACE(("BView(%s)::AddChild(child='%s' before='%s')... contacting app_server\n", 3280 Name(), child ? child->Name() : "NULL", before ? before->Name() : "NULL")); 3281 3282 child->_SetOwner(fOwner); 3283 child->_CreateSelf(); 3284 child->_Attach(); 3285 3286 if (lockedOwner) 3287 fOwner->Unlock(); 3288 } 3289 } 3290 3291 3292 bool 3293 BView::RemoveChild(BView *child) 3294 { 3295 STRACE(("BView(%s)::RemoveChild(%s)\n", Name(), child->Name())); 3296 3297 if (!child) 3298 return false; 3299 3300 return child->RemoveSelf(); 3301 } 3302 3303 3304 int32 3305 BView::CountChildren() const 3306 { 3307 check_lock_no_pick(); 3308 3309 uint32 count = 0; 3310 BView *child = fFirstChild; 3311 3312 while (child != NULL) { 3313 count++; 3314 child = child->fNextSibling; 3315 } 3316 3317 return count; 3318 } 3319 3320 3321 BView * 3322 BView::ChildAt(int32 index) const 3323 { 3324 check_lock_no_pick(); 3325 3326 BView *child = fFirstChild; 3327 while (child != NULL && index-- > 0) { 3328 child = child->fNextSibling; 3329 } 3330 3331 return child; 3332 } 3333 3334 3335 BView * 3336 BView::NextSibling() const 3337 { 3338 return fNextSibling; 3339 } 3340 3341 3342 BView * 3343 BView::PreviousSibling() const 3344 { 3345 return fPreviousSibling; 3346 } 3347 3348 3349 bool 3350 BView::RemoveSelf() 3351 { 3352 STRACE(("BView(%s)::RemoveSelf()...\n", Name())); 3353 3354 // Remove this child from its parent 3355 3356 if (fOwner) { 3357 _UpdateStateForRemove(); 3358 _Detach(); 3359 } 3360 3361 if (!fParent || !fParent->_RemoveChildFromList(this)) 3362 return false; 3363 3364 if (fOwner) { 3365 check_lock(); 3366 3367 if (!fState->IsAllValid()) { 3368 // we need to retrieve the latest state from the server 3369 fState->UpdateFrom(*fOwner->fLink); 3370 } 3371 3372 // make sure our owner doesn't need us anymore 3373 3374 if (fOwner->CurrentFocus() == this) 3375 MakeFocus(false); 3376 3377 if (fOwner->fDefaultButton == this) 3378 fOwner->SetDefaultButton(NULL); 3379 3380 if (fOwner->fKeyMenuBar == this) 3381 fOwner->fKeyMenuBar = NULL; 3382 3383 if (fOwner->fLastMouseMovedView == this) 3384 fOwner->fLastMouseMovedView = NULL; 3385 3386 if (fOwner->fLastViewToken == _get_object_token_(this)) 3387 fOwner->fLastViewToken = B_NULL_TOKEN; 3388 3389 BWindow *owner = fOwner; 3390 _SetOwner(NULL); 3391 3392 owner->fLink->StartMessage(AS_LAYER_DELETE); 3393 } 3394 3395 STRACE(("DONE: BView(%s)::removeSelf()\n", Name())); 3396 3397 return true; 3398 } 3399 3400 3401 BView * 3402 BView::Parent() const 3403 { 3404 if (fParent && fParent->fTopLevelView) 3405 return NULL; 3406 3407 return fParent; 3408 } 3409 3410 3411 BView * 3412 BView::FindView(const char *name) const 3413 { 3414 if (name == NULL) 3415 return NULL; 3416 3417 if (Name() != NULL && !strcmp(Name(), name)) 3418 return const_cast<BView *>(this); 3419 3420 BView *child = fFirstChild; 3421 while (child != NULL) { 3422 BView *view = child->FindView(name); 3423 if (view != NULL) 3424 return view; 3425 3426 child = child->fNextSibling; 3427 } 3428 3429 return NULL; 3430 } 3431 3432 3433 void 3434 BView::MoveBy(float deltaX, float deltaY) 3435 { 3436 MoveTo(fParentOffset.x + deltaX, fParentOffset.y + deltaY); 3437 } 3438 3439 3440 void 3441 BView::MoveTo(BPoint where) 3442 { 3443 MoveTo(where.x, where.y); 3444 } 3445 3446 3447 void 3448 BView::MoveTo(float x, float y) 3449 { 3450 if (x == fParentOffset.x && y == fParentOffset.y) 3451 return; 3452 3453 // BeBook says we should do this. And it makes sense. 3454 x = roundf(x); 3455 y = roundf(y); 3456 3457 if (fOwner) { 3458 check_lock(); 3459 fOwner->fLink->StartMessage(AS_LAYER_MOVE_TO); 3460 fOwner->fLink->Attach<float>(x); 3461 fOwner->fLink->Attach<float>(y); 3462 3463 fState->valid_flags |= B_VIEW_FRAME_BIT; 3464 } 3465 3466 fParentOffset.Set(x, y); 3467 } 3468 3469 3470 void 3471 BView::ResizeBy(float deltaWidth, float deltaHeight) 3472 { 3473 ResizeTo(fBounds.right + deltaWidth, fBounds.bottom + deltaHeight); 3474 } 3475 3476 3477 void 3478 BView::ResizeTo(float width, float height) 3479 { 3480 // NOTE: I think this check makes sense, but I didn't 3481 // test what R5 does. 3482 if (width < 0.0) 3483 width = 0.0; 3484 if (height < 0.0) 3485 height = 0.0; 3486 3487 if (width == fBounds.Width() && height == fBounds.Height()) 3488 return; 3489 3490 // BeBook says we should do this. And it makes sense. 3491 width = floorf(width + 0.5); 3492 height = floorf(height + 0.5); 3493 3494 if (fOwner) { 3495 check_lock(); 3496 fOwner->fLink->StartMessage(AS_LAYER_RESIZE_TO); 3497 fOwner->fLink->Attach<float>(width); 3498 fOwner->fLink->Attach<float>(height); 3499 3500 fState->valid_flags |= B_VIEW_FRAME_BIT; 3501 } 3502 3503 fBounds.right = fBounds.left + width; 3504 fBounds.bottom = fBounds.top + height; 3505 } 3506 3507 3508 // #pragma mark - 3509 // Inherited Methods (from BHandler) 3510 3511 3512 status_t 3513 BView::GetSupportedSuites(BMessage *data) 3514 { 3515 if (data == NULL) 3516 return B_BAD_VALUE; 3517 3518 status_t status = data->AddString("Suites", "suite/vnd.Be-view"); 3519 if (status == B_OK) { 3520 BPropertyInfo propertyInfo(sViewPropInfo); 3521 3522 status = data->AddFlat("message", &propertyInfo); 3523 if (status == B_OK) 3524 status = BHandler::GetSupportedSuites(data); 3525 } 3526 return status; 3527 } 3528 3529 3530 BHandler * 3531 BView::ResolveSpecifier(BMessage *msg, int32 index, BMessage *specifier, 3532 int32 what, const char *property) 3533 { 3534 if (msg->what == B_WINDOW_MOVE_BY 3535 || msg->what == B_WINDOW_MOVE_TO) 3536 return this; 3537 3538 BPropertyInfo propertyInfo(sViewPropInfo); 3539 3540 switch (propertyInfo.FindMatch(msg, index, specifier, what, property)) { 3541 case B_ERROR: 3542 break; 3543 3544 case 0: 3545 case 1: 3546 case 2: 3547 case 3: 3548 case 5: 3549 return this; 3550 3551 case 4: 3552 if (fShelf) { 3553 msg->PopSpecifier(); 3554 return fShelf; 3555 } else { 3556 BMessage replyMsg(B_MESSAGE_NOT_UNDERSTOOD); 3557 3558 replyMsg.AddInt32("error", B_NAME_NOT_FOUND); 3559 replyMsg.AddString("message", "This window doesn't have a self"); 3560 msg->SendReply(&replyMsg); 3561 return NULL; 3562 } 3563 break; 3564 3565 case 6: 3566 case 7: 3567 case 8: 3568 { 3569 if (fFirstChild) { 3570 BView *child; 3571 switch (msg->what) { 3572 case B_INDEX_SPECIFIER: 3573 { 3574 int32 index; 3575 msg->FindInt32("data", &index); 3576 child = ChildAt(index); 3577 break; 3578 } 3579 case B_REVERSE_INDEX_SPECIFIER: 3580 { 3581 int32 rindex; 3582 msg->FindInt32("data", &rindex); 3583 child = ChildAt(CountChildren() - rindex); 3584 break; 3585 } 3586 case B_NAME_SPECIFIER: 3587 { 3588 const char *name; 3589 msg->FindString("data", &name); 3590 child = FindView(name); 3591 break; 3592 } 3593 3594 default: 3595 child = NULL; 3596 break; 3597 } 3598 3599 if (child != NULL) { 3600 msg->PopSpecifier(); 3601 return child; 3602 } else { 3603 BMessage replyMsg(B_MESSAGE_NOT_UNDERSTOOD); 3604 replyMsg.AddInt32("error", B_BAD_INDEX); 3605 replyMsg.AddString("message", "Cannot find view at/with specified index/name."); 3606 msg->SendReply(&replyMsg); 3607 return NULL; 3608 } 3609 } else { 3610 BMessage replyMsg(B_MESSAGE_NOT_UNDERSTOOD); 3611 replyMsg.AddInt32("error", B_NAME_NOT_FOUND); 3612 replyMsg.AddString("message", "This window doesn't have children."); 3613 msg->SendReply(&replyMsg); 3614 return NULL; 3615 } 3616 break; 3617 } 3618 3619 default: 3620 break; 3621 } 3622 3623 return BHandler::ResolveSpecifier(msg, index, specifier, what, property); 3624 } 3625 3626 3627 void 3628 BView::MessageReceived(BMessage *msg) 3629 { 3630 BMessage specifier; 3631 int32 what; 3632 const char *prop; 3633 int32 index; 3634 status_t err; 3635 3636 if (!msg->HasSpecifiers()) { 3637 BHandler::MessageReceived(msg); 3638 return; 3639 } 3640 3641 err = msg->GetCurrentSpecifier(&index, &specifier, &what, &prop); 3642 if (err == B_OK) { 3643 BMessage replyMsg; 3644 3645 switch (msg->what) { 3646 case B_GET_PROPERTY: 3647 { 3648 replyMsg.what = B_NO_ERROR; 3649 replyMsg.AddInt32("error", B_OK); 3650 3651 if (strcmp(prop, "Frame") == 0) 3652 replyMsg.AddRect("result", Frame()); 3653 else if (strcmp(prop, "Hidden") == 0) 3654 replyMsg.AddBool( "result", IsHidden()); 3655 break; 3656 } 3657 3658 case B_SET_PROPERTY: 3659 { 3660 if (strcmp(prop, "Frame") == 0) { 3661 BRect newFrame; 3662 if (msg->FindRect("data", &newFrame) == B_OK) { 3663 MoveTo(newFrame.LeftTop()); 3664 ResizeTo(newFrame.right, newFrame.bottom); 3665 3666 replyMsg.what = B_NO_ERROR; 3667 replyMsg.AddInt32("error", B_OK); 3668 } else { 3669 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 3670 replyMsg.AddInt32("error", B_BAD_SCRIPT_SYNTAX); 3671 replyMsg.AddString("message", "Didn't understand the specifier(s)"); 3672 } 3673 } else if (strcmp(prop, "Hidden") == 0) { 3674 bool newHiddenState; 3675 if (msg->FindBool("data", &newHiddenState) == B_OK) { 3676 if (!IsHidden() && newHiddenState == true) { 3677 Hide(); 3678 3679 replyMsg.what = B_NO_ERROR; 3680 replyMsg.AddInt32( "error", B_OK); 3681 } 3682 else if (IsHidden() && newHiddenState == false) { 3683 Show(); 3684 3685 replyMsg.what = B_NO_ERROR; 3686 replyMsg.AddInt32("error", B_OK); 3687 } else { 3688 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 3689 replyMsg.AddInt32("error", B_BAD_SCRIPT_SYNTAX); 3690 replyMsg.AddString("message", "Didn't understand the specifier(s)"); 3691 } 3692 } else { 3693 replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD; 3694 replyMsg.AddInt32("error", B_BAD_SCRIPT_SYNTAX); 3695 replyMsg.AddString("message", "Didn't understand the specifier(s)"); 3696 } 3697 } 3698 break; 3699 } 3700 3701 case B_COUNT_PROPERTIES: 3702 if (strcmp(prop, "View") == 0) { 3703 replyMsg.what = B_NO_ERROR; 3704 replyMsg.AddInt32("error", B_OK); 3705 replyMsg.AddInt32("result", CountChildren()); 3706 } 3707 break; 3708 } 3709 3710 msg->SendReply(&replyMsg); 3711 } else { 3712 BMessage replyMsg(B_MESSAGE_NOT_UNDERSTOOD); 3713 replyMsg.AddInt32("error" , B_BAD_SCRIPT_SYNTAX); 3714 replyMsg.AddString("message", "Didn't understand the specifier(s)"); 3715 3716 msg->SendReply(&replyMsg); 3717 } 3718 } 3719 3720 3721 status_t 3722 BView::Perform(perform_code d, void* arg) 3723 { 3724 return B_BAD_VALUE; 3725 } 3726 3727 3728 // #pragma mark - 3729 // Private Functions 3730 3731 3732 void 3733 BView::_InitData(BRect frame, const char *name, uint32 resizingMode, uint32 flags) 3734 { 3735 // Info: The name of the view is set by BHandler constructor 3736 3737 STRACE(("BView::InitData: enter\n")); 3738 3739 // initialize members 3740 fFlags = (resizingMode & _RESIZE_MASK_) | (flags & ~_RESIZE_MASK_); 3741 3742 // handle rounding 3743 frame.left = roundf(frame.left); 3744 frame.top = roundf(frame.top); 3745 frame.right = roundf(frame.right); 3746 frame.bottom = roundf(frame.bottom); 3747 3748 fParentOffset.Set(frame.left, frame.top); 3749 3750 fOwner = NULL; 3751 fParent = NULL; 3752 fNextSibling = NULL; 3753 fPreviousSibling = NULL; 3754 fFirstChild = NULL; 3755 3756 fShowLevel = 0; 3757 fTopLevelView = false; 3758 3759 cpicture = NULL; 3760 comm = NULL; 3761 3762 fVerScroller = NULL; 3763 fHorScroller = NULL; 3764 3765 f_is_printing = false; 3766 3767 fState = new BPrivate::ViewState; 3768 3769 fBounds = frame.OffsetToCopy(B_ORIGIN); 3770 fShelf = NULL; 3771 3772 fEventMask = 0; 3773 fEventOptions = 0; 3774 } 3775 3776 3777 void 3778 BView::removeCommArray() 3779 { 3780 if (comm) { 3781 delete [] comm->array; 3782 delete comm; 3783 comm = NULL; 3784 } 3785 } 3786 3787 3788 void 3789 BView::_SetOwner(BWindow *newOwner) 3790 { 3791 if (!newOwner) 3792 removeCommArray(); 3793 3794 if (fOwner != newOwner && fOwner) { 3795 if (fOwner->fFocus == this) 3796 MakeFocus(false); 3797 3798 if (fOwner->fLastMouseMovedView == this) 3799 fOwner->fLastMouseMovedView = NULL; 3800 3801 fOwner->RemoveHandler(this); 3802 if (fShelf) 3803 fOwner->RemoveHandler(fShelf); 3804 } 3805 3806 if (newOwner && newOwner != fOwner) { 3807 newOwner->AddHandler(this); 3808 if (fShelf) 3809 newOwner->AddHandler(fShelf); 3810 3811 if (fTopLevelView) 3812 SetNextHandler(newOwner); 3813 else 3814 SetNextHandler(fParent); 3815 } 3816 3817 fOwner = newOwner; 3818 3819 for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling) 3820 child->_SetOwner(newOwner); 3821 } 3822 3823 3824 void 3825 BView::DoPictureClip(BPicture *picture, BPoint where, 3826 bool invert, bool sync) 3827 { 3828 if (!picture) 3829 return; 3830 3831 if (do_owner_check()) { 3832 fOwner->fLink->StartMessage(AS_LAYER_CLIP_TO_PICTURE); 3833 fOwner->fLink->Attach<int32>(picture->token); 3834 fOwner->fLink->Attach<BPoint>(where); 3835 fOwner->fLink->Attach<bool>(invert); 3836 3837 // TODO: I think that "sync" means another thing here: 3838 // the bebook, at least, says so. 3839 if (sync) 3840 fOwner->fLink->Flush(); 3841 3842 fState->valid_flags &= ~B_VIEW_CLIP_REGION_BIT; 3843 } 3844 3845 fState->archiving_flags |= B_VIEW_CLIP_REGION_BIT; 3846 } 3847 3848 3849 bool 3850 BView::_RemoveChildFromList(BView* child) 3851 { 3852 if (child->fParent != this) 3853 return false; 3854 3855 if (fFirstChild == child) { 3856 // it's the first view in the list 3857 fFirstChild = child->fNextSibling; 3858 } else { 3859 // there must be a previous sibling 3860 child->fPreviousSibling->fNextSibling = child->fNextSibling; 3861 } 3862 3863 if (child->fNextSibling) 3864 child->fNextSibling->fPreviousSibling = child->fPreviousSibling; 3865 3866 child->fParent = NULL; 3867 child->fNextSibling = NULL; 3868 child->fPreviousSibling = NULL; 3869 3870 return true; 3871 } 3872 3873 3874 bool 3875 BView::_AddChildToList(BView* view, BView* before) 3876 { 3877 if (!view) 3878 return false; 3879 3880 BView *current = fFirstChild; 3881 BView *last = current; 3882 3883 while (current && current != before) { 3884 last = current; 3885 current = current->fNextSibling; 3886 } 3887 3888 if (!current && before) 3889 return false; 3890 3891 // we're at begining of the list, OR between two elements 3892 if (current) { 3893 if (current == fFirstChild) { 3894 view->fNextSibling = current; 3895 current->fPreviousSibling = view; 3896 fFirstChild = view; 3897 } else { 3898 view->fNextSibling = current; 3899 view->fPreviousSibling = current->fPreviousSibling; 3900 current->fPreviousSibling->fNextSibling = view; 3901 current->fPreviousSibling = view; 3902 } 3903 } else { 3904 // we have reached the end of the list 3905 3906 // if last!=NULL then we add to the end. Otherwise, view is the 3907 // first chiild in the list 3908 if (last) { 3909 last->fNextSibling = view; 3910 view->fPreviousSibling = last; 3911 } else 3912 fFirstChild = view; 3913 } 3914 3915 view->fParent = this; 3916 return true; 3917 } 3918 3919 3920 /*! \brief Creates the server counterpart of this view. 3921 This is only done for views that are part of the view hierarchy, ie. when 3922 they are attached to a window. 3923 RemoveSelf() deletes the server object again. 3924 */ 3925 bool 3926 BView::_CreateSelf() 3927 { 3928 // AS_LAYER_CREATE & AS_LAYER_CREATE_ROOT do not use the 3929 // current view mechanism via check_lock() - the token 3930 // of the view and its parent are both send to the server. 3931 3932 if (fTopLevelView) 3933 fOwner->fLink->StartMessage(AS_LAYER_CREATE_ROOT); 3934 else 3935 fOwner->fLink->StartMessage(AS_LAYER_CREATE); 3936 3937 fOwner->fLink->Attach<int32>(_get_object_token_(this)); 3938 fOwner->fLink->AttachString(Name()); 3939 fOwner->fLink->Attach<BRect>(Frame()); 3940 fOwner->fLink->Attach<uint32>(ResizingMode()); 3941 fOwner->fLink->Attach<uint32>(fEventMask); 3942 fOwner->fLink->Attach<uint32>(fEventOptions); 3943 fOwner->fLink->Attach<uint32>(Flags()); 3944 fOwner->fLink->Attach<bool>(IsHidden(this)); 3945 fOwner->fLink->Attach<rgb_color>(fState->view_color); 3946 if (fTopLevelView) 3947 fOwner->fLink->Attach<int32>(B_NULL_TOKEN); 3948 else 3949 fOwner->fLink->Attach<int32>(_get_object_token_(fParent)); 3950 fOwner->fLink->Flush(); 3951 3952 do_owner_check(); 3953 fState->UpdateServerState(*fOwner->fLink); 3954 3955 // we create all its children, too 3956 3957 for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling) { 3958 child->_CreateSelf(); 3959 } 3960 3961 fOwner->fLink->Flush(); 3962 return true; 3963 } 3964 3965 3966 void 3967 BView::_Activate(bool active) 3968 { 3969 WindowActivated(active); 3970 3971 for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling) { 3972 child->_Activate(active); 3973 } 3974 } 3975 3976 3977 void 3978 BView::_Attach() 3979 { 3980 AttachedToWindow(); 3981 3982 for (BView* child = fFirstChild; child != NULL; child = child->fNextSibling) { 3983 child->_Attach(); 3984 } 3985 3986 AllAttached(); 3987 } 3988 3989 3990 void 3991 BView::_Detach() 3992 { 3993 DetachedFromWindow(); 3994 3995 for (BView* child = fFirstChild; child != NULL; child = child->fNextSibling) { 3996 child->_Detach(); 3997 } 3998 3999 AllDetached(); 4000 } 4001 4002 4003 void 4004 BView::_Draw(BRect updateRect) 4005 { 4006 if (IsHidden(this)) 4007 return; 4008 4009 check_lock(); 4010 4011 if (Flags() & B_WILL_DRAW) { 4012 // TODO: make states robust 4013 PushState(); 4014 Draw(updateRect); 4015 PopState(); 4016 } else { 4017 // The code below is certainly not correct, because 4018 // it redoes what the app_server already did 4019 // Find out what happens on R5 if a view has ViewColor() = 4020 // B_TRANSPARENT_COLOR but not B_WILL_DRAW 4021 /* rgb_color c = aView->HighColor(); 4022 aView->SetHighColor(aView->ViewColor()); 4023 aView->FillRect(aView->Bounds(), B_SOLID_HIGH); 4024 aView->SetHighColor(c);*/ 4025 } 4026 4027 for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling) { 4028 BRect rect = child->Frame(); 4029 if (!updateRect.Intersects(rect)) 4030 continue; 4031 4032 // get new update rect in child coordinates 4033 rect = updateRect & rect; 4034 child->ConvertFromParent(&rect); 4035 4036 child->_Draw(rect); 4037 } 4038 4039 if (Flags() & B_WILL_DRAW) { 4040 PushState(); 4041 DrawAfterChildren(updateRect); 4042 PopState(); 4043 } 4044 } 4045 4046 4047 void 4048 BView::_Pulse() 4049 { 4050 if (Flags() & B_PULSE_NEEDED) 4051 Pulse(); 4052 4053 for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling) { 4054 child->_Pulse(); 4055 } 4056 } 4057 4058 4059 void 4060 BView::_UpdateStateForRemove() 4061 { 4062 if (!do_owner_check()) 4063 return; 4064 4065 fState->UpdateFrom(*fOwner->fLink); 4066 fBounds = Bounds(); 4067 fParentOffset = LeftTop(); 4068 4069 // update children as well 4070 4071 for (BView *child = fFirstChild; child != NULL; child = child->fNextSibling) { 4072 child->_UpdateStateForRemove(); 4073 } 4074 } 4075 4076 4077 inline void 4078 BView::_UpdatePattern(::pattern pattern) 4079 { 4080 if (fState->IsValid(B_VIEW_PATTERN_BIT) && pattern == fState->pattern) 4081 return; 4082 4083 if (fOwner) { 4084 check_lock(); 4085 4086 fOwner->fLink->StartMessage(AS_LAYER_SET_PATTERN); 4087 fOwner->fLink->Attach< ::pattern>(pattern); 4088 4089 fState->valid_flags |= B_VIEW_PATTERN_BIT; 4090 } 4091 4092 fState->pattern = pattern; 4093 } 4094 4095 4096 BShelf * 4097 BView::shelf() const 4098 { 4099 return fShelf; 4100 } 4101 4102 4103 void 4104 BView::set_shelf(BShelf *shelf) 4105 { 4106 // TODO: is this all that needs done? 4107 fShelf = shelf; 4108 } 4109 4110 4111 status_t 4112 BView::_SetViewImage(const BBitmap* bitmap, BRect srcRect, 4113 BRect dstRect, uint32 followFlags, uint32 options) 4114 { 4115 if (!do_owner_check()) 4116 return B_ERROR; 4117 4118 int32 serverToken = bitmap ? bitmap->get_server_token() : -1; 4119 4120 fOwner->fLink->StartMessage(AS_LAYER_SET_VIEW_IMAGE); 4121 fOwner->fLink->Attach<int32>(serverToken); 4122 fOwner->fLink->Attach<BRect>(srcRect); 4123 fOwner->fLink->Attach<BRect>(dstRect); 4124 fOwner->fLink->Attach<int32>(followFlags); 4125 fOwner->fLink->Attach<int32>(options); 4126 4127 // TODO: this needs fixed between here and the server. 4128 // The server should return whatever error code is needed, whether it 4129 // is B_OK or whatever, not SERVER_TRUE. 4130 4131 status_t status = B_ERROR; 4132 int32 code; 4133 if (fOwner->fLink->FlushWithReply(code) == B_OK 4134 && code == SERVER_TRUE) 4135 fOwner->fLink->Read<status_t>(&status); 4136 4137 return status; 4138 } 4139 4140 4141 bool 4142 BView::do_owner_check() const 4143 { 4144 STRACE(("BView(%s)::do_owner_check()...", Name())); 4145 4146 int32 serverToken = _get_object_token_(this); 4147 4148 if (fOwner == NULL) { 4149 debugger("View method requires owner and doesn't have one."); 4150 return false; 4151 } 4152 4153 fOwner->check_lock(); 4154 4155 if (fOwner->fLastViewToken != serverToken) { 4156 STRACE(("contacting app_server... sending token: %ld\n", serverToken)); 4157 fOwner->fLink->StartMessage(AS_SET_CURRENT_LAYER); 4158 fOwner->fLink->Attach<int32>(serverToken); 4159 4160 fOwner->fLastViewToken = serverToken; 4161 } else 4162 STRACE(("this is the lastViewToken\n")); 4163 4164 return true; 4165 } 4166 4167 4168 void 4169 BView::check_lock() const 4170 { 4171 STRACE(("BView(%s)::check_lock()...", Name() ? Name(): "NULL")); 4172 4173 if (!fOwner) 4174 return; 4175 4176 fOwner->check_lock(); 4177 4178 int32 serverToken = _get_object_token_(this); 4179 4180 if (fOwner->fLastViewToken != serverToken) { 4181 STRACE(("contacting app_server... sending token: %ld\n", serverToken)); 4182 fOwner->fLink->StartMessage(AS_SET_CURRENT_LAYER); 4183 fOwner->fLink->Attach<int32>(serverToken); 4184 4185 fOwner->fLastViewToken = serverToken; 4186 } else { 4187 STRACE(("quiet2\n")); 4188 } 4189 } 4190 4191 4192 void 4193 BView::check_lock_no_pick() const 4194 { 4195 if (fOwner) 4196 fOwner->check_lock(); 4197 } 4198 4199 4200 bool 4201 BView::do_owner_check_no_pick() const 4202 { 4203 if (fOwner) { 4204 fOwner->check_lock(); 4205 return true; 4206 } else { 4207 debugger("View method requires owner and doesn't have one."); 4208 return false; 4209 } 4210 } 4211 4212 4213 void BView::_ReservedView2(){} 4214 void BView::_ReservedView3(){} 4215 void BView::_ReservedView4(){} 4216 void BView::_ReservedView5(){} 4217 void BView::_ReservedView6(){} 4218 void BView::_ReservedView7(){} 4219 void BView::_ReservedView8(){} 4220 4221 #if !_PR3_COMPATIBLE_ 4222 void BView::_ReservedView9(){} 4223 void BView::_ReservedView10(){} 4224 void BView::_ReservedView11(){} 4225 void BView::_ReservedView12(){} 4226 void BView::_ReservedView13(){} 4227 void BView::_ReservedView14(){} 4228 void BView::_ReservedView15(){} 4229 void BView::_ReservedView16(){} 4230 #endif 4231 4232 4233 BView::BView(const BView &other) 4234 : BHandler() 4235 { 4236 // this is private and not functional, but exported 4237 } 4238 4239 4240 BView & 4241 BView::operator=(const BView &other) 4242 { 4243 // this is private and not functional, but exported 4244 return *this; 4245 } 4246 4247 4248 void 4249 BView::PrintToStream() 4250 { 4251 printf("BView::PrintToStream()\n"); 4252 printf("\tName: %s\ 4253 \tParent: %s\ 4254 \tFirstChild: %s\ 4255 \tNextSibling: %s\ 4256 \tPrevSibling: %s\ 4257 \tOwner(Window): %s\ 4258 \tToken: %ld\ 4259 \tFlags: %ld\ 4260 \tView origin: (%f,%f)\ 4261 \tView Bounds rectangle: (%f,%f,%f,%f)\ 4262 \tShow level: %d\ 4263 \tTopView?: %s\ 4264 \tBPicture: %s\ 4265 \tVertical Scrollbar %s\ 4266 \tHorizontal Scrollbar %s\ 4267 \tIs Printing?: %s\ 4268 \tShelf?: %s\ 4269 \tEventMask: %ld\ 4270 \tEventOptions: %ld\n", 4271 Name(), 4272 fParent ? fParent->Name() : "NULL", 4273 fFirstChild ? fFirstChild->Name() : "NULL", 4274 fNextSibling ? fNextSibling->Name() : "NULL", 4275 fPreviousSibling ? fPreviousSibling->Name() : "NULL", 4276 fOwner ? fOwner->Name() : "NULL", 4277 _get_object_token_(this), 4278 fFlags, 4279 fParentOffset.x, fParentOffset.y, 4280 fBounds.left, fBounds.top, fBounds.right, fBounds.bottom, 4281 fShowLevel, 4282 fTopLevelView ? "YES" : "NO", 4283 cpicture? "YES" : "NULL", 4284 fVerScroller? "YES" : "NULL", 4285 fHorScroller? "YES" : "NULL", 4286 f_is_printing? "YES" : "NO", 4287 fShelf? "YES" : "NO", 4288 fEventMask, 4289 fEventOptions); 4290 4291 printf("\tState status:\ 4292 \t\tLocalCoordianteSystem: (%f,%f)\ 4293 \t\tPenLocation: (%f,%f)\ 4294 \t\tPenSize: %f\ 4295 \t\tHighColor: [%d,%d,%d,%d]\ 4296 \t\tLowColor: [%d,%d,%d,%d]\ 4297 \t\tViewColor: [%d,%d,%d,%d]\ 4298 \t\tPattern: %llx\ 4299 \t\tDrawingMode: %d\ 4300 \t\tLineJoinMode: %d\ 4301 \t\tLineCapMode: %d\ 4302 \t\tMiterLimit: %f\ 4303 \t\tAlphaSource: %d\ 4304 \t\tAlphaFuntion: %d\ 4305 \t\tScale: %f\ 4306 \t\t(Print)FontAliasing: %s\ 4307 \t\tFont Info:\n", 4308 fState->origin.x, fState->origin.y, 4309 fState->pen_location.x, fState->pen_location.y, 4310 fState->pen_size, 4311 fState->high_color.red, fState->high_color.blue, fState->high_color.green, fState->high_color.alpha, 4312 fState->low_color.red, fState->low_color.blue, fState->low_color.green, fState->low_color.alpha, 4313 fState->view_color.red, fState->view_color.blue, fState->view_color.green, fState->view_color.alpha, 4314 *((uint64*)&(fState->pattern)), 4315 fState->drawing_mode, 4316 fState->line_join, 4317 fState->line_cap, 4318 fState->miter_limit, 4319 fState->alpha_source_mode, 4320 fState->alpha_function_mode, 4321 fState->scale, 4322 fState->font_aliasing? "YES" : "NO"); 4323 4324 fState->font.PrintToStream(); 4325 4326 // TODO: also print the line array. 4327 } 4328 4329 4330 void 4331 BView::PrintTree() 4332 { 4333 int32 spaces = 2; 4334 BView *c = fFirstChild; //c = short for: current 4335 printf( "'%s'\n", Name() ); 4336 if (c != NULL) { 4337 while(true) { 4338 // action block 4339 { 4340 for (int i = 0; i < spaces; i++) 4341 printf(" "); 4342 4343 printf( "'%s'\n", c->Name() ); 4344 } 4345 4346 // go deep 4347 if (c->fFirstChild) { 4348 c = c->fFirstChild; 4349 spaces += 2; 4350 } else { 4351 // go right 4352 if (c->fNextSibling) { 4353 c = c->fNextSibling; 4354 } else { 4355 // go up 4356 while (!c->fParent->fNextSibling && c->fParent != this) { 4357 c = c->fParent; 4358 spaces -= 2; 4359 } 4360 4361 // that enough! We've reached this view. 4362 if (c->fParent == this) 4363 break; 4364 4365 c = c->fParent->fNextSibling; 4366 spaces -= 2; 4367 } 4368 } 4369 } 4370 } 4371 } 4372 4373 4374 /* TODO: 4375 -implement SetDiskMode(). What's with this method? What does it do? test! 4376 does it has something to do with DrawPictureAsync( filename* .. )? 4377 -implement DrawAfterChildren() 4378 */ 4379