1 /* 2 * Copyright 2001-2008, Haiku Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Frans van Nispen (xlr8@tref.nl) 7 * Stephan Aßmus <superstippi@gmx.de> 8 * Ingo Weinhold <bonefish@cs.tu-berlin.de> 9 */ 10 11 /*! BTextControl displays text that can act like a control. */ 12 13 14 #include <stdio.h> 15 16 #include <AbstractLayoutItem.h> 17 #include <LayoutUtils.h> 18 #include <Message.h> 19 #include <Region.h> 20 #include <TextControl.h> 21 #include <Window.h> 22 23 #include "TextInput.h" 24 25 26 class BTextControl::LabelLayoutItem : public BAbstractLayoutItem { 27 public: 28 LabelLayoutItem(BTextControl* parent); 29 30 virtual bool IsVisible(); 31 virtual void SetVisible(bool visible); 32 33 virtual BRect Frame(); 34 virtual void SetFrame(BRect frame); 35 36 virtual BView* View(); 37 38 virtual BSize BaseMinSize(); 39 virtual BSize BaseMaxSize(); 40 virtual BSize BasePreferredSize(); 41 virtual BAlignment BaseAlignment(); 42 43 private: 44 BTextControl* fParent; 45 BRect fFrame; 46 }; 47 48 49 class BTextControl::TextViewLayoutItem : public BAbstractLayoutItem { 50 public: 51 TextViewLayoutItem(BTextControl* parent); 52 53 virtual bool IsVisible(); 54 virtual void SetVisible(bool visible); 55 56 virtual BRect Frame(); 57 virtual void SetFrame(BRect frame); 58 59 virtual BView* View(); 60 61 virtual BSize BaseMinSize(); 62 virtual BSize BaseMaxSize(); 63 virtual BSize BasePreferredSize(); 64 virtual BAlignment BaseAlignment(); 65 66 private: 67 BTextControl* fParent; 68 BRect fFrame; 69 }; 70 71 72 // #pragma mark - 73 74 75 BTextControl::BTextControl(BRect frame, const char* name, const char* label, 76 const char* text, BMessage* message, uint32 mask, uint32 flags) 77 : BControl(frame, name, label, message, mask, flags | B_FRAME_EVENTS) 78 { 79 _InitData(label, text); 80 _ValidateLayout(); 81 } 82 83 84 BTextControl::BTextControl(const char* name, const char* label, 85 const char* text, BMessage* message, uint32 flags) 86 : BControl(BRect(0, 0, -1, -1), name, label, message, B_FOLLOW_NONE, 87 flags | B_FRAME_EVENTS | B_SUPPORTS_LAYOUT) 88 { 89 _InitData(label, text); 90 _ValidateLayout(); 91 } 92 93 94 BTextControl::BTextControl(const char* label, const char* text, 95 BMessage* message) 96 : BControl(BRect(0, 0, -1, -1), NULL, label, message, B_FOLLOW_NONE, 97 B_WILL_DRAW | B_NAVIGABLE | B_FRAME_EVENTS | B_SUPPORTS_LAYOUT) 98 { 99 _InitData(label, text); 100 _ValidateLayout(); 101 } 102 103 104 BTextControl::~BTextControl() 105 { 106 SetModificationMessage(NULL); 107 } 108 109 110 BTextControl::BTextControl(BMessage* archive) 111 : BControl(archive) 112 { 113 _InitData(Label(), NULL, archive); 114 115 int32 labelAlignment = B_ALIGN_LEFT; 116 int32 textAlignment = B_ALIGN_LEFT; 117 118 if (archive->HasInt32("_a_label")) 119 archive->FindInt32("_a_label", &labelAlignment); 120 121 if (archive->HasInt32("_a_text")) 122 archive->FindInt32("_a_text", &textAlignment); 123 124 SetAlignment((alignment)labelAlignment, (alignment)textAlignment); 125 126 if (archive->HasFloat("_divide")) 127 archive->FindFloat("_divide", &fDivider); 128 129 if (archive->HasMessage("_mod_msg")) { 130 BMessage* message = new BMessage; 131 archive->FindMessage("_mod_msg", message); 132 SetModificationMessage(message); 133 } 134 } 135 136 137 BArchivable* 138 BTextControl::Instantiate(BMessage* archive) 139 { 140 if (validate_instantiation(archive, "BTextControl")) 141 return new BTextControl(archive); 142 143 return NULL; 144 } 145 146 147 status_t 148 BTextControl::Archive(BMessage *data, bool deep) const 149 { 150 status_t ret = BControl::Archive(data, deep); 151 alignment labelAlignment, textAlignment; 152 153 GetAlignment(&labelAlignment, &textAlignment); 154 155 if (ret == B_OK) 156 ret = data->AddInt32("_a_label", labelAlignment); 157 if (ret == B_OK) 158 ret = data->AddInt32("_a_text", textAlignment); 159 if (ret == B_OK) 160 ret = data->AddFloat("_divide", Divider()); 161 162 if (ModificationMessage() && (ret == B_OK)) 163 ret = data->AddMessage("_mod_msg", ModificationMessage()); 164 165 return ret; 166 } 167 168 169 void 170 BTextControl::SetText(const char *text) 171 { 172 if (InvokeKind() != B_CONTROL_INVOKED) 173 return; 174 175 fText->SetText(text); 176 177 if (IsFocus()) 178 fText->SetInitialText(); 179 180 fText->Invalidate(); 181 } 182 183 184 const char * 185 BTextControl::Text() const 186 { 187 return fText->Text(); 188 } 189 190 191 void 192 BTextControl::SetValue(int32 value) 193 { 194 BControl::SetValue(value); 195 } 196 197 198 status_t 199 BTextControl::Invoke(BMessage *message) 200 { 201 return BControl::Invoke(message); 202 } 203 204 205 BTextView * 206 BTextControl::TextView() const 207 { 208 return fText; 209 } 210 211 212 void 213 BTextControl::SetModificationMessage(BMessage *message) 214 { 215 delete fModificationMessage; 216 fModificationMessage = message; 217 } 218 219 220 BMessage * 221 BTextControl::ModificationMessage() const 222 { 223 return fModificationMessage; 224 } 225 226 227 void 228 BTextControl::SetAlignment(alignment labelAlignment, alignment textAlignment) 229 { 230 fText->SetAlignment(textAlignment); 231 fText->AlignTextRect(); 232 233 if (fLabelAlign != labelAlignment) { 234 fLabelAlign = labelAlignment; 235 Invalidate(); 236 } 237 } 238 239 240 void 241 BTextControl::GetAlignment(alignment* _label, alignment* _text) const 242 { 243 if (_label) 244 *_label = fLabelAlign; 245 if (_text) 246 *_text = fText->Alignment(); 247 } 248 249 250 void 251 BTextControl::SetDivider(float dividingLine) 252 { 253 fDivider = floorf(dividingLine + 0.5); 254 255 _LayoutTextView(); 256 257 if (Window()) { 258 fText->Invalidate(); 259 Invalidate(); 260 } 261 } 262 263 264 float 265 BTextControl::Divider() const 266 { 267 return fDivider; 268 } 269 270 271 void 272 BTextControl::Draw(BRect updateRect) 273 { 274 rgb_color noTint = ui_color(B_PANEL_BACKGROUND_COLOR); 275 rgb_color lighten1 = tint_color(noTint, B_LIGHTEN_1_TINT); 276 rgb_color lighten2 = tint_color(noTint, B_LIGHTEN_2_TINT); 277 rgb_color lightenMax = tint_color(noTint, B_LIGHTEN_MAX_TINT); 278 rgb_color darken1 = tint_color(noTint, B_DARKEN_1_TINT); 279 rgb_color darken2 = tint_color(noTint, B_DARKEN_2_TINT); 280 rgb_color darken4 = tint_color(noTint, B_DARKEN_4_TINT); 281 rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); 282 283 bool enabled = IsEnabled(); 284 bool active = false; 285 286 if (fText->IsFocus() && Window()->IsActive()) 287 active = true; 288 289 // outer bevel 290 291 BRect rect = fText->Frame(); 292 rect.InsetBy(-2, -2); 293 294 if (enabled) 295 SetHighColor(darken1); 296 else 297 SetHighColor(noTint); 298 299 StrokeLine(rect.LeftBottom(), rect.LeftTop()); 300 StrokeLine(rect.RightTop()); 301 302 if (enabled) 303 SetHighColor(lighten2); 304 else 305 SetHighColor(lighten1); 306 307 StrokeLine(BPoint(rect.left + 1.0f, rect.bottom), rect.RightBottom()); 308 StrokeLine(BPoint(rect.right, rect.top + 1.0f), rect.RightBottom()); 309 310 // inner bevel 311 312 rect.InsetBy(1.0f, 1.0f); 313 314 if (active) { 315 SetHighColor(navigationColor); 316 StrokeRect(rect); 317 } else { 318 if (enabled) 319 SetHighColor(darken4); 320 else 321 SetHighColor(darken2); 322 323 StrokeLine(rect.LeftTop(), rect.LeftBottom()); 324 StrokeLine(rect.LeftTop(), rect.RightTop()); 325 326 SetHighColor(noTint); 327 StrokeLine(BPoint(rect.left + 1.0f, rect.bottom), rect.RightBottom()); 328 StrokeLine(BPoint(rect.right, rect.top + 1.0f)); 329 } 330 331 // label 332 333 if (Label()) { 334 font_height fontHeight; 335 GetFontHeight(&fontHeight); 336 337 float y = Bounds().top + (Bounds().Height() + 1 - fontHeight.ascent 338 - fontHeight.descent) / 2 + fontHeight.ascent; 339 float x; 340 341 float labelWidth = StringWidth(Label()); 342 switch (fLabelAlign) { 343 case B_ALIGN_RIGHT: 344 x = fDivider - labelWidth - 3.0; 345 break; 346 347 case B_ALIGN_CENTER: 348 x = fDivider - labelWidth / 2.0; 349 break; 350 351 default: 352 x = 0.0; 353 break; 354 } 355 356 BRect labelArea(x, Bounds().top, x + labelWidth, Bounds().bottom); 357 if (x < fDivider && updateRect.Intersects(labelArea)) { 358 labelArea.right = fText->Frame().left - 3; 359 360 BRegion clipRegion(labelArea); 361 ConstrainClippingRegion(&clipRegion); 362 SetHighColor(IsEnabled() ? ui_color(B_CONTROL_TEXT_COLOR) 363 : tint_color(noTint, B_DISABLED_LABEL_TINT)); 364 DrawString(Label(), BPoint(x, y)); 365 } 366 } 367 } 368 369 370 void 371 BTextControl::MouseDown(BPoint where) 372 { 373 if (!fText->IsFocus()) { 374 fText->MakeFocus(true); 375 } 376 } 377 378 379 void 380 BTextControl::AttachedToWindow() 381 { 382 BControl::AttachedToWindow(); 383 384 _UpdateTextViewColors(IsEnabled()); 385 fText->MakeEditable(IsEnabled()); 386 } 387 388 389 void 390 BTextControl::MakeFocus(bool state) 391 { 392 if (state != fText->IsFocus()) { 393 fText->MakeFocus(state); 394 395 if (state) 396 fText->SelectAll(); 397 } 398 } 399 400 401 void 402 BTextControl::SetEnabled(bool enabled) 403 { 404 if (IsEnabled() == enabled) 405 return; 406 407 if (Window()) { 408 fText->MakeEditable(enabled); 409 410 _UpdateTextViewColors(enabled); 411 412 fText->Invalidate(); 413 Window()->UpdateIfNeeded(); 414 } 415 416 BControl::SetEnabled(enabled); 417 } 418 419 420 void 421 BTextControl::GetPreferredSize(float *_width, float *_height) 422 { 423 if (_height) { 424 // we need enough space for the label and the child text view 425 font_height fontHeight; 426 GetFontHeight(&fontHeight); 427 float labelHeight = ceil(fontHeight.ascent + fontHeight.descent 428 + fontHeight.leading); 429 float textHeight = ceilf(fText->LineHeight(0) + 1.0) + 4.0; 430 431 *_height = max_c(labelHeight, textHeight); 432 } 433 434 if (_width) { 435 *_width = Bounds().Width(); 436 const char* label = Label(); 437 if (label) { 438 float width = ceilf(StringWidth(label)); 439 *_width = (width * 1.3) + width + 4.0; 440 } 441 } 442 } 443 444 445 void 446 BTextControl::ResizeToPreferred() 447 { 448 BView::ResizeToPreferred(); 449 450 fDivider = 0.0; 451 const char* label = Label(); 452 if (label) 453 fDivider = ceil(StringWidth(label)) + 2.0; 454 455 _LayoutTextView(); 456 } 457 458 459 void 460 BTextControl::SetFlags(uint32 flags) 461 { 462 if (!fSkipSetFlags) { 463 // If the textview is navigable, set it to not navigable if needed 464 // Else if it is not navigable, set it to navigable if needed 465 if (fText->Flags() & B_NAVIGABLE) { 466 if (!(flags & B_NAVIGABLE)) 467 fText->SetFlags(fText->Flags() & ~B_NAVIGABLE); 468 469 } else { 470 if (flags & B_NAVIGABLE) 471 fText->SetFlags(fText->Flags() | B_NAVIGABLE); 472 } 473 474 // Don't make this one navigable 475 flags &= ~B_NAVIGABLE; 476 } 477 478 BView::SetFlags(flags); 479 } 480 481 482 void 483 BTextControl::MessageReceived(BMessage *msg) 484 { 485 switch(msg->what) { 486 case B_SET_PROPERTY: 487 case B_GET_PROPERTY: 488 // TODO 489 break; 490 default: 491 BControl::MessageReceived(msg); 492 break; 493 } 494 } 495 496 497 BHandler * 498 BTextControl::ResolveSpecifier(BMessage *msg, int32 index, 499 BMessage *specifier, int32 form, 500 const char *property) 501 { 502 /* 503 BPropertyInfo propInfo(prop_list); 504 BHandler *target = NULL; 505 506 if (propInfo.FindMatch(message, 0, specifier, what, property) < B_OK) 507 return BControl::ResolveSpecifier(message, index, specifier, what, 508 property); 509 else 510 return this; 511 */ 512 return BControl::ResolveSpecifier(msg, index, specifier, form, property); 513 } 514 515 516 status_t 517 BTextControl::GetSupportedSuites(BMessage *data) 518 { 519 return BControl::GetSupportedSuites(data); 520 } 521 522 523 void 524 BTextControl::MouseUp(BPoint pt) 525 { 526 BControl::MouseUp(pt); 527 } 528 529 530 void 531 BTextControl::MouseMoved(BPoint pt, uint32 code, const BMessage *msg) 532 { 533 BControl::MouseMoved(pt, code, msg); 534 } 535 536 537 void 538 BTextControl::DetachedFromWindow() 539 { 540 BControl::DetachedFromWindow(); 541 } 542 543 544 void 545 BTextControl::AllAttached() 546 { 547 BControl::AllAttached(); 548 } 549 550 551 void 552 BTextControl::AllDetached() 553 { 554 BControl::AllDetached(); 555 } 556 557 558 void 559 BTextControl::FrameMoved(BPoint newPosition) 560 { 561 BControl::FrameMoved(newPosition); 562 } 563 564 565 void 566 BTextControl::FrameResized(float width, float height) 567 { 568 BControl::FrameResized(width, height); 569 570 // changes in width 571 572 BRect bounds = Bounds(); 573 const float border = 2.0f; 574 575 if (bounds.Width() > fPreviousWidth) { 576 // invalidate the region between the old and the new right border 577 BRect rect = bounds; 578 rect.left += fPreviousWidth - border; 579 rect.right--; 580 Invalidate(rect); 581 } else if (bounds.Width() < fPreviousWidth) { 582 // invalidate the region of the new right border 583 BRect rect = bounds; 584 rect.left = rect.right - border; 585 Invalidate(rect); 586 } 587 588 // changes in height 589 590 if (bounds.Height() > fPreviousHeight) { 591 // invalidate the region between the old and the new bottom border 592 BRect rect = bounds; 593 rect.top += fPreviousHeight - border; 594 rect.bottom--; 595 Invalidate(rect); 596 } else if (bounds.Height() < fPreviousHeight) { 597 // invalidate the region of the new bottom border 598 BRect rect = bounds; 599 rect.top = rect.bottom - border; 600 Invalidate(rect); 601 } 602 603 fPreviousWidth = uint16(bounds.Width()); 604 fPreviousHeight = uint16(bounds.Height()); 605 } 606 607 608 void 609 BTextControl::WindowActivated(bool active) 610 { 611 if (fText->IsFocus()) { 612 // invalidate to remove/show focus indication 613 BRect rect = fText->Frame(); 614 rect.InsetBy(-1, -1); 615 Invalidate(rect); 616 617 // help out embedded text view which doesn't 618 // get notified of this 619 fText->Invalidate(); 620 } 621 } 622 623 624 status_t 625 BTextControl::Perform(perform_code d, void *arg) 626 { 627 return BControl::Perform(d, arg); 628 } 629 630 631 BLayoutItem* 632 BTextControl::CreateLabelLayoutItem() 633 { 634 if (!fLabelLayoutItem) 635 fLabelLayoutItem = new LabelLayoutItem(this); 636 return fLabelLayoutItem; 637 } 638 639 640 BLayoutItem* 641 BTextControl::CreateTextViewLayoutItem() 642 { 643 if (!fTextViewLayoutItem) 644 fTextViewLayoutItem = new TextViewLayoutItem(this); 645 return fTextViewLayoutItem; 646 } 647 648 649 void BTextControl::_ReservedTextControl1() {} 650 void BTextControl::_ReservedTextControl2() {} 651 void BTextControl::_ReservedTextControl3() {} 652 void BTextControl::_ReservedTextControl4() {} 653 654 655 BTextControl & 656 BTextControl::operator=(const BTextControl&) 657 { 658 return *this; 659 } 660 661 662 void 663 BTextControl::_UpdateTextViewColors(bool enabled) 664 { 665 rgb_color textColor; 666 rgb_color color; 667 BFont font; 668 669 fText->GetFontAndColor(0, &font); 670 671 if (enabled) 672 textColor = ui_color(B_DOCUMENT_TEXT_COLOR); 673 else { 674 textColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 675 B_DISABLED_LABEL_TINT); 676 } 677 678 fText->SetFontAndColor(&font, B_FONT_ALL, &textColor); 679 680 if (enabled) { 681 color = ui_color(B_DOCUMENT_BACKGROUND_COLOR); 682 } else { 683 color = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 684 B_LIGHTEN_2_TINT); 685 } 686 687 fText->SetViewColor(color); 688 fText->SetLowColor(color); 689 } 690 691 692 void 693 BTextControl::_CommitValue() 694 { 695 } 696 697 698 void 699 BTextControl::_InitData(const char* label, const char* initialText, 700 BMessage* archive) 701 { 702 BRect bounds(Bounds()); 703 704 fText = NULL; 705 fModificationMessage = NULL; 706 fLabelAlign = B_ALIGN_LEFT; 707 fDivider = 0.0f; 708 fPreviousWidth = bounds.Width(); 709 fPreviousHeight = bounds.Height(); 710 fLabelLayoutItem = NULL; 711 fTextViewLayoutItem = NULL; 712 fSkipSetFlags = false; 713 714 int32 flags = 0; 715 716 BFont font(be_plain_font); 717 718 if (!archive || !archive->HasString("_fname")) 719 flags |= B_FONT_FAMILY_AND_STYLE; 720 721 if (!archive || !archive->HasFloat("_fflt")) 722 flags |= B_FONT_SIZE; 723 724 if (flags != 0) 725 SetFont(&font, flags); 726 727 if (label) 728 fDivider = floorf(bounds.Width() / 2.0f); 729 730 uint32 navigableFlags = Flags() & B_NAVIGABLE; 731 if (navigableFlags != 0) { 732 fSkipSetFlags = true; 733 SetFlags(Flags() & ~B_NAVIGABLE); 734 fSkipSetFlags = false; 735 } 736 737 if (archive) 738 fText = static_cast<BPrivate::_BTextInput_*>(FindView("_input_")); 739 740 if (fText == NULL) { 741 BRect frame(fDivider, bounds.top, bounds.right, bounds.bottom); 742 // we are stroking the frame around the text view, which 743 // is 2 pixels wide 744 frame.InsetBy(2.0, 3.0); 745 BRect textRect(frame.OffsetToCopy(B_ORIGIN)); 746 747 fText = new BPrivate::_BTextInput_(frame, textRect, 748 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, 749 B_WILL_DRAW | B_FRAME_EVENTS | navigableFlags); 750 AddChild(fText); 751 752 SetText(initialText); 753 fText->SetAlignment(B_ALIGN_LEFT); 754 fText->AlignTextRect(); 755 } 756 } 757 758 759 void 760 BTextControl::_ValidateLayout() 761 { 762 float height; 763 BTextControl::GetPreferredSize(NULL, &height); 764 765 ResizeTo(Bounds().Width(), height); 766 767 _LayoutTextView(); 768 769 fPreviousHeight = Bounds().Height(); 770 } 771 772 773 void 774 BTextControl::_LayoutTextView() 775 { 776 BRect frame = Bounds(); 777 frame.left = fDivider; 778 // we are stroking the frame around the text view, which 779 // is 2 pixels wide 780 frame.InsetBy(2.0, 2.0); 781 fText->MoveTo(frame.left, frame.top); 782 fText->ResizeTo(frame.Width(), frame.Height()); 783 fText->AlignTextRect(); 784 } 785 786 787 void 788 BTextControl::_UpdateFrame() 789 { 790 if (fLabelLayoutItem && fTextViewLayoutItem) { 791 BRect labelFrame = fLabelLayoutItem->Frame(); 792 BRect textFrame = fTextViewLayoutItem->Frame(); 793 MoveTo(labelFrame.left, labelFrame.top); 794 ResizeTo(textFrame.left + textFrame.Width() - labelFrame.left, 795 textFrame.top + textFrame.Height() - labelFrame.top); 796 SetDivider(textFrame.left - labelFrame.left); 797 } 798 } 799 800 801 // #pragma mark - 802 803 804 BTextControl::LabelLayoutItem::LabelLayoutItem(BTextControl* parent) 805 : fParent(parent), 806 fFrame() 807 { 808 } 809 810 811 bool 812 BTextControl::LabelLayoutItem::IsVisible() 813 { 814 return !fParent->IsHidden(fParent); 815 } 816 817 818 void 819 BTextControl::LabelLayoutItem::SetVisible(bool visible) 820 { 821 // not allowed 822 } 823 824 825 BRect 826 BTextControl::LabelLayoutItem::Frame() 827 { 828 return fFrame; 829 } 830 831 832 void 833 BTextControl::LabelLayoutItem::SetFrame(BRect frame) 834 { 835 fFrame = frame; 836 fParent->_UpdateFrame(); 837 } 838 839 840 BView* 841 BTextControl::LabelLayoutItem::View() 842 { 843 return fParent; 844 } 845 846 847 BSize 848 BTextControl::LabelLayoutItem::BaseMinSize() 849 { 850 // TODO: Cache the info. Might be too expensive for this call. 851 const char* label = fParent->Label(); 852 if (!label) 853 return BSize(-1, -1); 854 855 BSize size; 856 fParent->GetPreferredSize(NULL, &size.height); 857 858 size.width = fParent->StringWidth(label) + 2 * 3 - 1; 859 860 return size; 861 } 862 863 864 BSize 865 BTextControl::LabelLayoutItem::BaseMaxSize() 866 { 867 return BaseMinSize(); 868 } 869 870 871 BSize 872 BTextControl::LabelLayoutItem::BasePreferredSize() 873 { 874 return BaseMinSize(); 875 } 876 877 878 BAlignment 879 BTextControl::LabelLayoutItem::BaseAlignment() 880 { 881 return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); 882 } 883 884 885 // #pragma mark - 886 887 888 BTextControl::TextViewLayoutItem::TextViewLayoutItem(BTextControl* parent) 889 : fParent(parent), 890 fFrame() 891 { 892 } 893 894 895 bool 896 BTextControl::TextViewLayoutItem::IsVisible() 897 { 898 return !fParent->IsHidden(fParent); 899 } 900 901 902 void 903 BTextControl::TextViewLayoutItem::SetVisible(bool visible) 904 { 905 // not allowed 906 } 907 908 909 BRect 910 BTextControl::TextViewLayoutItem::Frame() 911 { 912 return fFrame; 913 } 914 915 916 void 917 BTextControl::TextViewLayoutItem::SetFrame(BRect frame) 918 { 919 fFrame = frame; 920 fParent->_UpdateFrame(); 921 } 922 923 924 BView* 925 BTextControl::TextViewLayoutItem::View() 926 { 927 return fParent; 928 } 929 930 931 BSize 932 BTextControl::TextViewLayoutItem::BaseMinSize() 933 { 934 // TODO: Cache the info. Might be too expensive for this call. 935 BSize size; 936 fParent->GetPreferredSize(NULL, &size.height); 937 938 // mmh, some arbitrary minimal width 939 size.width = 30; 940 941 return size; 942 } 943 944 945 BSize 946 BTextControl::TextViewLayoutItem::BaseMaxSize() 947 { 948 BSize size(BaseMinSize()); 949 size.width = B_SIZE_UNLIMITED; 950 return size; 951 } 952 953 954 BSize 955 BTextControl::TextViewLayoutItem::BasePreferredSize() 956 { 957 BSize size(BaseMinSize()); 958 // puh, no idea... 959 size.width = 100; 960 return size; 961 } 962 963 964 BAlignment 965 BTextControl::TextViewLayoutItem::BaseAlignment() 966 { 967 return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); 968 } 969 970