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