1105644bfSAxel Dörfler /* 2991c062fSAxel Dörfler * Copyright 2001-2008, Haiku Inc. 3105644bfSAxel Dörfler * Distributed under the terms of the MIT License. 4105644bfSAxel Dörfler * 5105644bfSAxel Dörfler * Authors: 6105644bfSAxel Dörfler * Frans van Nispen (xlr8@tref.nl) 7105644bfSAxel Dörfler * Stephan Aßmus <superstippi@gmx.de> 89ecf9d1cSIngo Weinhold * Ingo Weinhold <bonefish@cs.tu-berlin.de> 9105644bfSAxel Dörfler */ 10105644bfSAxel Dörfler 11991c062fSAxel Dörfler /*! BTextControl displays text that can act like a control. */ 12105644bfSAxel Dörfler 13105644bfSAxel Dörfler 1452a38012Sejakowatz #include <stdio.h> 1552a38012Sejakowatz 169ecf9d1cSIngo Weinhold #include <AbstractLayoutItem.h> 179ecf9d1cSIngo Weinhold #include <LayoutUtils.h> 18058691d4SStefano Ceccherini #include <Message.h> 19455d1c46SAxel Dörfler #include <Region.h> 2052a38012Sejakowatz #include <TextControl.h> 2152a38012Sejakowatz #include <Window.h> 2252a38012Sejakowatz 2352a38012Sejakowatz #include "TextInput.h" 2452a38012Sejakowatz 2552a38012Sejakowatz 2693ba577cSStephan Aßmus //#define TRACE_TEXT_CONTROL 2793ba577cSStephan Aßmus #ifdef TRACE_TEXT_CONTROL 2893ba577cSStephan Aßmus # include <FunctionTracer.h> 2993ba577cSStephan Aßmus static int32 sFunctionDepth = -1; 30349c911eSStephan Aßmus # define CALLED(x...) FunctionTracer _ft("BTextControl", __FUNCTION__, \ 3193ba577cSStephan Aßmus sFunctionDepth) 3293ba577cSStephan Aßmus # define TRACE(x...) { BString _to; \ 3393ba577cSStephan Aßmus _to.Append(' ', (sFunctionDepth + 1) * 2); \ 3493ba577cSStephan Aßmus printf("%s", _to.String()); printf(x); } 3593ba577cSStephan Aßmus #else 3693ba577cSStephan Aßmus # define CALLED(x...) 3793ba577cSStephan Aßmus # define TRACE(x...) 3893ba577cSStephan Aßmus #endif 3993ba577cSStephan Aßmus 4093ba577cSStephan Aßmus 419ecf9d1cSIngo Weinhold class BTextControl::LabelLayoutItem : public BAbstractLayoutItem { 429ecf9d1cSIngo Weinhold public: 439ecf9d1cSIngo Weinhold LabelLayoutItem(BTextControl* parent); 449ecf9d1cSIngo Weinhold 459ecf9d1cSIngo Weinhold virtual bool IsVisible(); 469ecf9d1cSIngo Weinhold virtual void SetVisible(bool visible); 479ecf9d1cSIngo Weinhold 489ecf9d1cSIngo Weinhold virtual BRect Frame(); 499ecf9d1cSIngo Weinhold virtual void SetFrame(BRect frame); 509ecf9d1cSIngo Weinhold 519ecf9d1cSIngo Weinhold virtual BView* View(); 529ecf9d1cSIngo Weinhold 539ecf9d1cSIngo Weinhold virtual BSize BaseMinSize(); 549ecf9d1cSIngo Weinhold virtual BSize BaseMaxSize(); 559ecf9d1cSIngo Weinhold virtual BSize BasePreferredSize(); 569ecf9d1cSIngo Weinhold virtual BAlignment BaseAlignment(); 579ecf9d1cSIngo Weinhold 589ecf9d1cSIngo Weinhold private: 599ecf9d1cSIngo Weinhold BTextControl* fParent; 609ecf9d1cSIngo Weinhold BRect fFrame; 619ecf9d1cSIngo Weinhold }; 629ecf9d1cSIngo Weinhold 639ecf9d1cSIngo Weinhold 649ecf9d1cSIngo Weinhold class BTextControl::TextViewLayoutItem : public BAbstractLayoutItem { 659ecf9d1cSIngo Weinhold public: 669ecf9d1cSIngo Weinhold TextViewLayoutItem(BTextControl* parent); 679ecf9d1cSIngo Weinhold 689ecf9d1cSIngo Weinhold virtual bool IsVisible(); 699ecf9d1cSIngo Weinhold virtual void SetVisible(bool visible); 709ecf9d1cSIngo Weinhold 719ecf9d1cSIngo Weinhold virtual BRect Frame(); 729ecf9d1cSIngo Weinhold virtual void SetFrame(BRect frame); 739ecf9d1cSIngo Weinhold 749ecf9d1cSIngo Weinhold virtual BView* View(); 759ecf9d1cSIngo Weinhold 769ecf9d1cSIngo Weinhold virtual BSize BaseMinSize(); 779ecf9d1cSIngo Weinhold virtual BSize BaseMaxSize(); 789ecf9d1cSIngo Weinhold virtual BSize BasePreferredSize(); 799ecf9d1cSIngo Weinhold virtual BAlignment BaseAlignment(); 809ecf9d1cSIngo Weinhold 819ecf9d1cSIngo Weinhold private: 829ecf9d1cSIngo Weinhold BTextControl* fParent; 839ecf9d1cSIngo Weinhold BRect fFrame; 849ecf9d1cSIngo Weinhold }; 859ecf9d1cSIngo Weinhold 869ecf9d1cSIngo Weinhold 87349c911eSStephan Aßmus struct BTextControl::LayoutData { 88349c911eSStephan Aßmus LayoutData(float width, float height) 89349c911eSStephan Aßmus : label_layout_item(NULL), 90349c911eSStephan Aßmus text_view_layout_item(NULL), 91349c911eSStephan Aßmus previous_width(width), 92349c911eSStephan Aßmus previous_height(height), 93349c911eSStephan Aßmus valid(false) 94349c911eSStephan Aßmus { 95349c911eSStephan Aßmus } 96349c911eSStephan Aßmus 97349c911eSStephan Aßmus LabelLayoutItem* label_layout_item; 98349c911eSStephan Aßmus TextViewLayoutItem* text_view_layout_item; 99349c911eSStephan Aßmus float previous_width; // used in FrameResized() for 100349c911eSStephan Aßmus float previous_height; // invalidation 101349c911eSStephan Aßmus font_height font_info; 102349c911eSStephan Aßmus float label_width; 103349c911eSStephan Aßmus float label_height; 104349c911eSStephan Aßmus BSize min; 105349c911eSStephan Aßmus BSize text_view_min; 106349c911eSStephan Aßmus bool valid; 107349c911eSStephan Aßmus }; 108349c911eSStephan Aßmus 109349c911eSStephan Aßmus 1109ecf9d1cSIngo Weinhold // #pragma mark - 1119ecf9d1cSIngo Weinhold 1129ecf9d1cSIngo Weinhold 113349c911eSStephan Aßmus static const int32 kFrameMargin = 2; 114349c911eSStephan Aßmus static const int32 kLabelInputSpacing = 3; 115349c911eSStephan Aßmus 116349c911eSStephan Aßmus 11752a38012Sejakowatz BTextControl::BTextControl(BRect frame, const char* name, const char* label, 118991c062fSAxel Dörfler const char* text, BMessage* message, uint32 mask, uint32 flags) 1199cb2dbe2SMarc Flerackers : BControl(frame, name, label, message, mask, flags | B_FRAME_EVENTS) 12052a38012Sejakowatz { 121ffe72abdSAxel Dörfler _InitData(label, text); 1229ecf9d1cSIngo Weinhold _ValidateLayout(); 1239ecf9d1cSIngo Weinhold } 12452a38012Sejakowatz 125105644bfSAxel Dörfler 1269ecf9d1cSIngo Weinhold BTextControl::BTextControl(const char* name, const char* label, 127991c062fSAxel Dörfler const char* text, BMessage* message, uint32 flags) 12893ba577cSStephan Aßmus : BControl(name, label, message, flags | B_FRAME_EVENTS) 1299ecf9d1cSIngo Weinhold { 1309ecf9d1cSIngo Weinhold _InitData(label, text); 1319ecf9d1cSIngo Weinhold _ValidateLayout(); 1329ecf9d1cSIngo Weinhold } 133105644bfSAxel Dörfler 134ffe72abdSAxel Dörfler 135991c062fSAxel Dörfler BTextControl::BTextControl(const char* label, const char* text, 136991c062fSAxel Dörfler BMessage* message) 13793ba577cSStephan Aßmus : BControl(NULL, label, message, 13893ba577cSStephan Aßmus B_WILL_DRAW | B_NAVIGABLE | B_FRAME_EVENTS) 1399ecf9d1cSIngo Weinhold { 1409ecf9d1cSIngo Weinhold _InitData(label, text); 1419ecf9d1cSIngo Weinhold _ValidateLayout(); 14252a38012Sejakowatz } 143058691d4SStefano Ceccherini 144058691d4SStefano Ceccherini 14552a38012Sejakowatz BTextControl::~BTextControl() 14652a38012Sejakowatz { 1479cb2dbe2SMarc Flerackers SetModificationMessage(NULL); 14852a38012Sejakowatz } 149058691d4SStefano Ceccherini 150058691d4SStefano Ceccherini 151ffe72abdSAxel Dörfler BTextControl::BTextControl(BMessage* archive) 152ffe72abdSAxel Dörfler : BControl(archive) 15352a38012Sejakowatz { 154ffe72abdSAxel Dörfler _InitData(Label(), NULL, archive); 15552a38012Sejakowatz 156ffe72abdSAxel Dörfler int32 labelAlignment = B_ALIGN_LEFT; 157ffe72abdSAxel Dörfler int32 textAlignment = B_ALIGN_LEFT; 15852a38012Sejakowatz 159ffe72abdSAxel Dörfler if (archive->HasInt32("_a_label")) 160ffe72abdSAxel Dörfler archive->FindInt32("_a_label", &labelAlignment); 16152a38012Sejakowatz 162ffe72abdSAxel Dörfler if (archive->HasInt32("_a_text")) 163ffe72abdSAxel Dörfler archive->FindInt32("_a_text", &textAlignment); 16452a38012Sejakowatz 165ffe72abdSAxel Dörfler SetAlignment((alignment)labelAlignment, (alignment)textAlignment); 1669cb2dbe2SMarc Flerackers 167ffe72abdSAxel Dörfler if (archive->HasFloat("_divide")) 168ed1c257aSKarsten Heimrich archive->FindFloat("_divide", &fDivider); 1699cb2dbe2SMarc Flerackers 170ffe72abdSAxel Dörfler if (archive->HasMessage("_mod_msg")) { 171ffe72abdSAxel Dörfler BMessage* message = new BMessage; 172ffe72abdSAxel Dörfler archive->FindMessage("_mod_msg", message); 173ffe72abdSAxel Dörfler SetModificationMessage(message); 1749cb2dbe2SMarc Flerackers } 17552a38012Sejakowatz } 176058691d4SStefano Ceccherini 177058691d4SStefano Ceccherini 178058691d4SStefano Ceccherini BArchivable* 179058691d4SStefano Ceccherini BTextControl::Instantiate(BMessage* archive) 18052a38012Sejakowatz { 1819cb2dbe2SMarc Flerackers if (validate_instantiation(archive, "BTextControl")) 1829cb2dbe2SMarc Flerackers return new BTextControl(archive); 183991c062fSAxel Dörfler 18452a38012Sejakowatz return NULL; 18552a38012Sejakowatz } 186058691d4SStefano Ceccherini 187058691d4SStefano Ceccherini 188058691d4SStefano Ceccherini status_t 189058691d4SStefano Ceccherini BTextControl::Archive(BMessage *data, bool deep) const 19052a38012Sejakowatz { 1913a543720SJérôme Duval status_t ret = BControl::Archive(data, deep); 192058691d4SStefano Ceccherini alignment labelAlignment, textAlignment; 19352a38012Sejakowatz 194058691d4SStefano Ceccherini GetAlignment(&labelAlignment, &textAlignment); 1959cb2dbe2SMarc Flerackers 19611d7ecebSJérôme Duval if (ret == B_OK) 19711d7ecebSJérôme Duval ret = data->AddInt32("_a_label", labelAlignment); 19811d7ecebSJérôme Duval if (ret == B_OK) 19911d7ecebSJérôme Duval ret = data->AddInt32("_a_text", textAlignment); 20011d7ecebSJérôme Duval if (ret == B_OK) 20111d7ecebSJérôme Duval ret = data->AddFloat("_divide", Divider()); 2029cb2dbe2SMarc Flerackers 20311d7ecebSJérôme Duval if (ModificationMessage() && (ret == B_OK)) 20411d7ecebSJérôme Duval ret = data->AddMessage("_mod_msg", ModificationMessage()); 2059cb2dbe2SMarc Flerackers 20611d7ecebSJérôme Duval return ret; 20752a38012Sejakowatz } 208058691d4SStefano Ceccherini 209058691d4SStefano Ceccherini 210058691d4SStefano Ceccherini void 211058691d4SStefano Ceccherini BTextControl::SetText(const char *text) 21252a38012Sejakowatz { 2139cb2dbe2SMarc Flerackers if (InvokeKind() != B_CONTROL_INVOKED) 2149cb2dbe2SMarc Flerackers return; 2159cb2dbe2SMarc Flerackers 21693ba577cSStephan Aßmus CALLED(); 21793ba577cSStephan Aßmus 21852a38012Sejakowatz fText->SetText(text); 2199cb2dbe2SMarc Flerackers 2209cb2dbe2SMarc Flerackers if (IsFocus()) 2219cb2dbe2SMarc Flerackers fText->SetInitialText(); 2229cb2dbe2SMarc Flerackers 2239cb2dbe2SMarc Flerackers fText->Invalidate(); 22452a38012Sejakowatz } 225058691d4SStefano Ceccherini 226058691d4SStefano Ceccherini 227058691d4SStefano Ceccherini const char * 228058691d4SStefano Ceccherini BTextControl::Text() const 22952a38012Sejakowatz { 23052a38012Sejakowatz return fText->Text(); 23152a38012Sejakowatz } 232058691d4SStefano Ceccherini 233058691d4SStefano Ceccherini 234058691d4SStefano Ceccherini void 235058691d4SStefano Ceccherini BTextControl::SetValue(int32 value) 23652a38012Sejakowatz { 2379cb2dbe2SMarc Flerackers BControl::SetValue(value); 23852a38012Sejakowatz } 239058691d4SStefano Ceccherini 240058691d4SStefano Ceccherini 241058691d4SStefano Ceccherini status_t 242058691d4SStefano Ceccherini BTextControl::Invoke(BMessage *message) 24352a38012Sejakowatz { 244058691d4SStefano Ceccherini return BControl::Invoke(message); 24552a38012Sejakowatz } 246058691d4SStefano Ceccherini 247058691d4SStefano Ceccherini 248058691d4SStefano Ceccherini BTextView * 249058691d4SStefano Ceccherini BTextControl::TextView() const 25052a38012Sejakowatz { 2519cb2dbe2SMarc Flerackers return fText; 25252a38012Sejakowatz } 253058691d4SStefano Ceccherini 254058691d4SStefano Ceccherini 255058691d4SStefano Ceccherini void 256058691d4SStefano Ceccherini BTextControl::SetModificationMessage(BMessage *message) 25752a38012Sejakowatz { 2589cb2dbe2SMarc Flerackers delete fModificationMessage; 25952a38012Sejakowatz fModificationMessage = message; 26052a38012Sejakowatz } 261058691d4SStefano Ceccherini 262058691d4SStefano Ceccherini 263058691d4SStefano Ceccherini BMessage * 264058691d4SStefano Ceccherini BTextControl::ModificationMessage() const 26552a38012Sejakowatz { 26652a38012Sejakowatz return fModificationMessage; 26752a38012Sejakowatz } 268058691d4SStefano Ceccherini 269058691d4SStefano Ceccherini 270058691d4SStefano Ceccherini void 271058691d4SStefano Ceccherini BTextControl::SetAlignment(alignment labelAlignment, alignment textAlignment) 27252a38012Sejakowatz { 273058691d4SStefano Ceccherini fText->SetAlignment(textAlignment); 2749cb2dbe2SMarc Flerackers fText->AlignTextRect(); 2759cb2dbe2SMarc Flerackers 276058691d4SStefano Ceccherini if (fLabelAlign != labelAlignment) { 277058691d4SStefano Ceccherini fLabelAlign = labelAlignment; 2789cb2dbe2SMarc Flerackers Invalidate(); 2799cb2dbe2SMarc Flerackers } 28052a38012Sejakowatz } 281058691d4SStefano Ceccherini 282058691d4SStefano Ceccherini 283058691d4SStefano Ceccherini void 284c432fbbbSAxel Dörfler BTextControl::GetAlignment(alignment* _label, alignment* _text) const 28552a38012Sejakowatz { 286c432fbbbSAxel Dörfler if (_label) 287c432fbbbSAxel Dörfler *_label = fLabelAlign; 288c432fbbbSAxel Dörfler if (_text) 289c432fbbbSAxel Dörfler *_text = fText->Alignment(); 29052a38012Sejakowatz } 2919cb2dbe2SMarc Flerackers 292058691d4SStefano Ceccherini 293058691d4SStefano Ceccherini void 294058691d4SStefano Ceccherini BTextControl::SetDivider(float dividingLine) 295058691d4SStefano Ceccherini { 296a431f44bSStephan Aßmus fDivider = floorf(dividingLine + 0.5); 2972e6a5805SStephan Aßmus 298a431f44bSStephan Aßmus _LayoutTextView(); 29952a38012Sejakowatz 300058691d4SStefano Ceccherini if (Window()) { 30152a38012Sejakowatz fText->Invalidate(); 30252a38012Sejakowatz Invalidate(); 30352a38012Sejakowatz } 3049cb2dbe2SMarc Flerackers } 305058691d4SStefano Ceccherini 306058691d4SStefano Ceccherini 307058691d4SStefano Ceccherini float 308058691d4SStefano Ceccherini BTextControl::Divider() const 30952a38012Sejakowatz { 31052a38012Sejakowatz return fDivider; 31152a38012Sejakowatz } 312058691d4SStefano Ceccherini 313058691d4SStefano Ceccherini 314058691d4SStefano Ceccherini void 315058691d4SStefano Ceccherini BTextControl::Draw(BRect updateRect) 31652a38012Sejakowatz { 317c432fbbbSAxel Dörfler rgb_color noTint = ui_color(B_PANEL_BACKGROUND_COLOR); 318c432fbbbSAxel Dörfler rgb_color lighten1 = tint_color(noTint, B_LIGHTEN_1_TINT); 319c432fbbbSAxel Dörfler rgb_color lighten2 = tint_color(noTint, B_LIGHTEN_2_TINT); 320c432fbbbSAxel Dörfler rgb_color lightenMax = tint_color(noTint, B_LIGHTEN_MAX_TINT); 321c432fbbbSAxel Dörfler rgb_color darken1 = tint_color(noTint, B_DARKEN_1_TINT); 322c432fbbbSAxel Dörfler rgb_color darken2 = tint_color(noTint, B_DARKEN_2_TINT); 323c432fbbbSAxel Dörfler rgb_color darken4 = tint_color(noTint, B_DARKEN_4_TINT); 324c432fbbbSAxel Dörfler rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); 3259cb2dbe2SMarc Flerackers 3269cb2dbe2SMarc Flerackers bool enabled = IsEnabled(); 3279cb2dbe2SMarc Flerackers bool active = false; 3289cb2dbe2SMarc Flerackers 3299cb2dbe2SMarc Flerackers if (fText->IsFocus() && Window()->IsActive()) 3309cb2dbe2SMarc Flerackers active = true; 3319cb2dbe2SMarc Flerackers 332455d1c46SAxel Dörfler // outer bevel 333455d1c46SAxel Dörfler 334a431f44bSStephan Aßmus BRect rect = fText->Frame(); 335a431f44bSStephan Aßmus rect.InsetBy(-2, -2); 336455d1c46SAxel Dörfler 337455d1c46SAxel Dörfler if (enabled) 338455d1c46SAxel Dörfler SetHighColor(darken1); 339455d1c46SAxel Dörfler else 340455d1c46SAxel Dörfler SetHighColor(noTint); 341455d1c46SAxel Dörfler 342455d1c46SAxel Dörfler StrokeLine(rect.LeftBottom(), rect.LeftTop()); 343455d1c46SAxel Dörfler StrokeLine(rect.RightTop()); 344455d1c46SAxel Dörfler 345455d1c46SAxel Dörfler if (enabled) 346455d1c46SAxel Dörfler SetHighColor(lighten2); 347455d1c46SAxel Dörfler else 348455d1c46SAxel Dörfler SetHighColor(lighten1); 349455d1c46SAxel Dörfler 350455d1c46SAxel Dörfler StrokeLine(BPoint(rect.left + 1.0f, rect.bottom), rect.RightBottom()); 351455d1c46SAxel Dörfler StrokeLine(BPoint(rect.right, rect.top + 1.0f), rect.RightBottom()); 352455d1c46SAxel Dörfler 353455d1c46SAxel Dörfler // inner bevel 354455d1c46SAxel Dörfler 355455d1c46SAxel Dörfler rect.InsetBy(1.0f, 1.0f); 3569cb2dbe2SMarc Flerackers 357058691d4SStefano Ceccherini if (active) { 358105644bfSAxel Dörfler SetHighColor(navigationColor); 3599cb2dbe2SMarc Flerackers StrokeRect(rect); 360058691d4SStefano Ceccherini } else { 3619cb2dbe2SMarc Flerackers if (enabled) 3629cb2dbe2SMarc Flerackers SetHighColor(darken4); 3639cb2dbe2SMarc Flerackers else 3649cb2dbe2SMarc Flerackers SetHighColor(darken2); 3659cb2dbe2SMarc Flerackers 3669cb2dbe2SMarc Flerackers StrokeLine(rect.LeftTop(), rect.LeftBottom()); 3679cb2dbe2SMarc Flerackers StrokeLine(rect.LeftTop(), rect.RightTop()); 3689cb2dbe2SMarc Flerackers 369105644bfSAxel Dörfler SetHighColor(noTint); 3709cb2dbe2SMarc Flerackers StrokeLine(BPoint(rect.left + 1.0f, rect.bottom), rect.RightBottom()); 3719cb2dbe2SMarc Flerackers StrokeLine(BPoint(rect.right, rect.top + 1.0f)); 3729cb2dbe2SMarc Flerackers } 3739cb2dbe2SMarc Flerackers 3747a25fcafSStefano Ceccherini // label 3757a25fcafSStefano Ceccherini 376058691d4SStefano Ceccherini if (Label()) { 377349c911eSStephan Aßmus _ValidateLayoutData(); 378349c911eSStephan Aßmus font_height& fontHeight = fLayoutData->font_info; 3799cb2dbe2SMarc Flerackers 380a68292ddSStephan Aßmus float y = Bounds().top + (Bounds().Height() + 1 - fontHeight.ascent 381a68292ddSStephan Aßmus - fontHeight.descent) / 2 + fontHeight.ascent; 38252a38012Sejakowatz float x; 3839cb2dbe2SMarc Flerackers 3847a25fcafSStefano Ceccherini float labelWidth = StringWidth(Label()); 385058691d4SStefano Ceccherini switch (fLabelAlign) { 38652a38012Sejakowatz case B_ALIGN_RIGHT: 387349c911eSStephan Aßmus x = fDivider - labelWidth - kLabelInputSpacing; 38852a38012Sejakowatz break; 38952a38012Sejakowatz 39052a38012Sejakowatz case B_ALIGN_CENTER: 391b8872c02SStephan Aßmus x = fDivider - labelWidth / 2.0; 39252a38012Sejakowatz break; 39352a38012Sejakowatz 39452a38012Sejakowatz default: 395b8872c02SStephan Aßmus x = 0.0; 39652a38012Sejakowatz break; 39752a38012Sejakowatz } 39852a38012Sejakowatz 3992c5a8894SStephan Aßmus BRect labelArea(x, Bounds().top, x + labelWidth, Bounds().bottom); 4007a25fcafSStefano Ceccherini if (x < fDivider && updateRect.Intersects(labelArea)) { 401349c911eSStephan Aßmus labelArea.right = fText->Frame().left - kLabelInputSpacing; 4027a25fcafSStefano Ceccherini 4037a25fcafSStefano Ceccherini BRegion clipRegion(labelArea); 4047a25fcafSStefano Ceccherini ConstrainClippingRegion(&clipRegion); 405c432fbbbSAxel Dörfler SetHighColor(IsEnabled() ? ui_color(B_CONTROL_TEXT_COLOR) 406fa815db3SAxel Dörfler : tint_color(noTint, B_DISABLED_LABEL_TINT)); 40752a38012Sejakowatz DrawString(Label(), BPoint(x, y)); 40852a38012Sejakowatz } 40952a38012Sejakowatz } 4107a25fcafSStefano Ceccherini } 411058691d4SStefano Ceccherini 412058691d4SStefano Ceccherini 413058691d4SStefano Ceccherini void 414058691d4SStefano Ceccherini BTextControl::MouseDown(BPoint where) 41552a38012Sejakowatz { 416058691d4SStefano Ceccherini if (!fText->IsFocus()) { 4179cb2dbe2SMarc Flerackers fText->MakeFocus(true); 41852a38012Sejakowatz } 41952a38012Sejakowatz } 420058691d4SStefano Ceccherini 421058691d4SStefano Ceccherini 422058691d4SStefano Ceccherini void 423058691d4SStefano Ceccherini BTextControl::AttachedToWindow() 42452a38012Sejakowatz { 42552a38012Sejakowatz BControl::AttachedToWindow(); 42652a38012Sejakowatz 42779c35b39SAxel Dörfler _UpdateTextViewColors(IsEnabled()); 4283a3f6c1eSAxel Dörfler fText->MakeEditable(IsEnabled()); 42952a38012Sejakowatz } 430058691d4SStefano Ceccherini 431058691d4SStefano Ceccherini 432058691d4SStefano Ceccherini void 433058691d4SStefano Ceccherini BTextControl::MakeFocus(bool state) 43452a38012Sejakowatz { 4356d8d6cadSStephan Aßmus if (state != fText->IsFocus()) { 43652a38012Sejakowatz fText->MakeFocus(state); 4379cb2dbe2SMarc Flerackers 4389cb2dbe2SMarc Flerackers if (state) 4399cb2dbe2SMarc Flerackers fText->SelectAll(); 44052a38012Sejakowatz } 4416d8d6cadSStephan Aßmus } 442058691d4SStefano Ceccherini 443058691d4SStefano Ceccherini 444058691d4SStefano Ceccherini void 44579c35b39SAxel Dörfler BTextControl::SetEnabled(bool enabled) 44652a38012Sejakowatz { 44779c35b39SAxel Dörfler if (IsEnabled() == enabled) 4489cb2dbe2SMarc Flerackers return; 4499cb2dbe2SMarc Flerackers 450058691d4SStefano Ceccherini if (Window()) { 45179c35b39SAxel Dörfler fText->MakeEditable(enabled); 4529cb2dbe2SMarc Flerackers 45379c35b39SAxel Dörfler _UpdateTextViewColors(enabled); 4549cb2dbe2SMarc Flerackers 4559cb2dbe2SMarc Flerackers fText->Invalidate(); 4569cb2dbe2SMarc Flerackers Window()->UpdateIfNeeded(); 4579cb2dbe2SMarc Flerackers } 4589cb2dbe2SMarc Flerackers 45979c35b39SAxel Dörfler BControl::SetEnabled(enabled); 46052a38012Sejakowatz } 461058691d4SStefano Ceccherini 462058691d4SStefano Ceccherini 463058691d4SStefano Ceccherini void 464105644bfSAxel Dörfler BTextControl::GetPreferredSize(float *_width, float *_height) 46552a38012Sejakowatz { 466349c911eSStephan Aßmus CALLED(); 46752a38012Sejakowatz 468349c911eSStephan Aßmus _ValidateLayoutData(); 469105644bfSAxel Dörfler 470*1aaf53ecSStephan Aßmus if (_width) { 471*1aaf53ecSStephan Aßmus float minWidth = fLayoutData->min.width; 472*1aaf53ecSStephan Aßmus if (Label() == NULL && !(Flags() & B_SUPPORTS_LAYOUT)) { 473*1aaf53ecSStephan Aßmus // Indeed, only if there is no label! BeOS backwards compatible 474*1aaf53ecSStephan Aßmus // behavior: 475*1aaf53ecSStephan Aßmus minWidth = max_c(minWidth, Bounds().Width()); 476*1aaf53ecSStephan Aßmus } 477*1aaf53ecSStephan Aßmus *_width = minWidth; 478*1aaf53ecSStephan Aßmus } 479349c911eSStephan Aßmus 480349c911eSStephan Aßmus if (_height) 481349c911eSStephan Aßmus *_height = fLayoutData->min.height; 48252a38012Sejakowatz } 483058691d4SStefano Ceccherini 484058691d4SStefano Ceccherini 485058691d4SStefano Ceccherini void 486058691d4SStefano Ceccherini BTextControl::ResizeToPreferred() 48752a38012Sejakowatz { 488105644bfSAxel Dörfler BView::ResizeToPreferred(); 4891bdc2a52SKarsten Heimrich 4901bdc2a52SKarsten Heimrich fDivider = 0.0; 4911bdc2a52SKarsten Heimrich const char* label = Label(); 4921bdc2a52SKarsten Heimrich if (label) 4931bdc2a52SKarsten Heimrich fDivider = ceil(StringWidth(label)) + 2.0; 4941bdc2a52SKarsten Heimrich 4951bdc2a52SKarsten Heimrich _LayoutTextView(); 49652a38012Sejakowatz } 497058691d4SStefano Ceccherini 498058691d4SStefano Ceccherini 499058691d4SStefano Ceccherini void 500058691d4SStefano Ceccherini BTextControl::SetFlags(uint32 flags) 50152a38012Sejakowatz { 5029cb2dbe2SMarc Flerackers // If the textview is navigable, set it to not navigable if needed 5039cb2dbe2SMarc Flerackers // Else if it is not navigable, set it to navigable if needed 504058691d4SStefano Ceccherini if (fText->Flags() & B_NAVIGABLE) { 5059cb2dbe2SMarc Flerackers if (!(flags & B_NAVIGABLE)) 5069cb2dbe2SMarc Flerackers fText->SetFlags(fText->Flags() & ~B_NAVIGABLE); 507058691d4SStefano Ceccherini 508058691d4SStefano Ceccherini } else { 5099cb2dbe2SMarc Flerackers if (flags & B_NAVIGABLE) 5109cb2dbe2SMarc Flerackers fText->SetFlags(fText->Flags() | B_NAVIGABLE); 5119cb2dbe2SMarc Flerackers } 5129cb2dbe2SMarc Flerackers 5139cb2dbe2SMarc Flerackers // Don't make this one navigable 5149cb2dbe2SMarc Flerackers flags &= ~B_NAVIGABLE; 5159cb2dbe2SMarc Flerackers 51652a38012Sejakowatz BView::SetFlags(flags); 51752a38012Sejakowatz } 518058691d4SStefano Ceccherini 519058691d4SStefano Ceccherini 520058691d4SStefano Ceccherini void 521058691d4SStefano Ceccherini BTextControl::MessageReceived(BMessage *msg) 52252a38012Sejakowatz { 523058691d4SStefano Ceccherini switch(msg->what) { 5249cb2dbe2SMarc Flerackers case B_SET_PROPERTY: 5259cb2dbe2SMarc Flerackers case B_GET_PROPERTY: 5269cb2dbe2SMarc Flerackers // TODO 52752a38012Sejakowatz break; 52852a38012Sejakowatz default: 52952a38012Sejakowatz BControl::MessageReceived(msg); 53052a38012Sejakowatz break; 53152a38012Sejakowatz } 53252a38012Sejakowatz } 533058691d4SStefano Ceccherini 534058691d4SStefano Ceccherini 535058691d4SStefano Ceccherini BHandler * 536058691d4SStefano Ceccherini BTextControl::ResolveSpecifier(BMessage *msg, int32 index, 53752a38012Sejakowatz BMessage *specifier, int32 form, 53852a38012Sejakowatz const char *property) 53952a38012Sejakowatz { 5409cb2dbe2SMarc Flerackers /* 5419cb2dbe2SMarc Flerackers BPropertyInfo propInfo(prop_list); 5429cb2dbe2SMarc Flerackers BHandler *target = NULL; 5439cb2dbe2SMarc Flerackers 5449cb2dbe2SMarc Flerackers if (propInfo.FindMatch(message, 0, specifier, what, property) < B_OK) 5459cb2dbe2SMarc Flerackers return BControl::ResolveSpecifier(message, index, specifier, what, 5469cb2dbe2SMarc Flerackers property); 5479cb2dbe2SMarc Flerackers else 5489cb2dbe2SMarc Flerackers return this; 5499cb2dbe2SMarc Flerackers */ 5509cb2dbe2SMarc Flerackers return BControl::ResolveSpecifier(msg, index, specifier, form, property); 55152a38012Sejakowatz } 552058691d4SStefano Ceccherini 553058691d4SStefano Ceccherini 554058691d4SStefano Ceccherini status_t 555058691d4SStefano Ceccherini BTextControl::GetSupportedSuites(BMessage *data) 55652a38012Sejakowatz { 5579cb2dbe2SMarc Flerackers return BControl::GetSupportedSuites(data); 55852a38012Sejakowatz } 559058691d4SStefano Ceccherini 560058691d4SStefano Ceccherini 561058691d4SStefano Ceccherini void 562058691d4SStefano Ceccherini BTextControl::MouseUp(BPoint pt) 56352a38012Sejakowatz { 56452a38012Sejakowatz BControl::MouseUp(pt); 56552a38012Sejakowatz } 566058691d4SStefano Ceccherini 567058691d4SStefano Ceccherini 568058691d4SStefano Ceccherini void 569058691d4SStefano Ceccherini BTextControl::MouseMoved(BPoint pt, uint32 code, const BMessage *msg) 57052a38012Sejakowatz { 57152a38012Sejakowatz BControl::MouseMoved(pt, code, msg); 57252a38012Sejakowatz } 573058691d4SStefano Ceccherini 574058691d4SStefano Ceccherini 575058691d4SStefano Ceccherini void 576058691d4SStefano Ceccherini BTextControl::DetachedFromWindow() 57752a38012Sejakowatz { 57852a38012Sejakowatz BControl::DetachedFromWindow(); 57952a38012Sejakowatz } 580058691d4SStefano Ceccherini 581058691d4SStefano Ceccherini 582058691d4SStefano Ceccherini void 583058691d4SStefano Ceccherini BTextControl::AllAttached() 58452a38012Sejakowatz { 58552a38012Sejakowatz BControl::AllAttached(); 58652a38012Sejakowatz } 587058691d4SStefano Ceccherini 588058691d4SStefano Ceccherini 589058691d4SStefano Ceccherini void 590058691d4SStefano Ceccherini BTextControl::AllDetached() 59152a38012Sejakowatz { 59252a38012Sejakowatz BControl::AllDetached(); 59352a38012Sejakowatz } 594058691d4SStefano Ceccherini 595058691d4SStefano Ceccherini 596058691d4SStefano Ceccherini void 597058691d4SStefano Ceccherini BTextControl::FrameMoved(BPoint newPosition) 59852a38012Sejakowatz { 59952a38012Sejakowatz BControl::FrameMoved(newPosition); 60052a38012Sejakowatz } 601058691d4SStefano Ceccherini 602058691d4SStefano Ceccherini 603058691d4SStefano Ceccherini void 604ffe72abdSAxel Dörfler BTextControl::FrameResized(float width, float height) 60552a38012Sejakowatz { 60693ba577cSStephan Aßmus CALLED(); 60793ba577cSStephan Aßmus 608ffe72abdSAxel Dörfler BControl::FrameResized(width, height); 609ffe72abdSAxel Dörfler 610349c911eSStephan Aßmus // TODO: this causes flickering still... 611349c911eSStephan Aßmus 612ffe72abdSAxel Dörfler // changes in width 613ffe72abdSAxel Dörfler 614ffe72abdSAxel Dörfler BRect bounds = Bounds(); 615ffe72abdSAxel Dörfler 616349c911eSStephan Aßmus if (bounds.Width() > fLayoutData->previous_width) { 617ffe72abdSAxel Dörfler // invalidate the region between the old and the new right border 618ffe72abdSAxel Dörfler BRect rect = bounds; 619349c911eSStephan Aßmus rect.left += fLayoutData->previous_width - kFrameMargin; 620ffe72abdSAxel Dörfler rect.right--; 621ffe72abdSAxel Dörfler Invalidate(rect); 622349c911eSStephan Aßmus } else if (bounds.Width() < fLayoutData->previous_width) { 623ffe72abdSAxel Dörfler // invalidate the region of the new right border 624ffe72abdSAxel Dörfler BRect rect = bounds; 625349c911eSStephan Aßmus rect.left = rect.right - kFrameMargin; 626ffe72abdSAxel Dörfler Invalidate(rect); 627ffe72abdSAxel Dörfler } 628ffe72abdSAxel Dörfler 629ffe72abdSAxel Dörfler // changes in height 630ffe72abdSAxel Dörfler 631349c911eSStephan Aßmus if (bounds.Height() > fLayoutData->previous_height) { 632ffe72abdSAxel Dörfler // invalidate the region between the old and the new bottom border 633ffe72abdSAxel Dörfler BRect rect = bounds; 634349c911eSStephan Aßmus rect.top += fLayoutData->previous_height - kFrameMargin; 635ffe72abdSAxel Dörfler rect.bottom--; 636ffe72abdSAxel Dörfler Invalidate(rect); 637349c911eSStephan Aßmus // invalidate label area 638349c911eSStephan Aßmus rect = bounds; 639349c911eSStephan Aßmus rect.right = fDivider; 640349c911eSStephan Aßmus Invalidate(rect); 641349c911eSStephan Aßmus } else if (bounds.Height() < fLayoutData->previous_height) { 642ffe72abdSAxel Dörfler // invalidate the region of the new bottom border 643ffe72abdSAxel Dörfler BRect rect = bounds; 644349c911eSStephan Aßmus rect.top = rect.bottom - kFrameMargin; 645349c911eSStephan Aßmus Invalidate(rect); 646349c911eSStephan Aßmus // invalidate label area 647349c911eSStephan Aßmus rect = bounds; 648349c911eSStephan Aßmus rect.right = fDivider; 649ffe72abdSAxel Dörfler Invalidate(rect); 650ffe72abdSAxel Dörfler } 651ffe72abdSAxel Dörfler 652349c911eSStephan Aßmus fLayoutData->previous_width = bounds.Width(); 653349c911eSStephan Aßmus fLayoutData->previous_height = bounds.Height(); 65493ba577cSStephan Aßmus 65593ba577cSStephan Aßmus TRACE("width: %.2f, height: %.2f\n", bounds.Width(), bounds.Height()); 65652a38012Sejakowatz } 657058691d4SStefano Ceccherini 658058691d4SStefano Ceccherini 659058691d4SStefano Ceccherini void 660058691d4SStefano Ceccherini BTextControl::WindowActivated(bool active) 66152a38012Sejakowatz { 6626d8d6cadSStephan Aßmus if (fText->IsFocus()) { 663dde10e45SStephan Aßmus // invalidate to remove/show focus indication 6642c5a8894SStephan Aßmus BRect rect = fText->Frame(); 6652c5a8894SStephan Aßmus rect.InsetBy(-1, -1); 6666d8d6cadSStephan Aßmus Invalidate(rect); 667dde10e45SStephan Aßmus 668dde10e45SStephan Aßmus // help out embedded text view which doesn't 669dde10e45SStephan Aßmus // get notified of this 670dde10e45SStephan Aßmus fText->Invalidate(); 6716d8d6cadSStephan Aßmus } 67252a38012Sejakowatz } 673058691d4SStefano Ceccherini 674058691d4SStefano Ceccherini 675349c911eSStephan Aßmus BSize 676349c911eSStephan Aßmus BTextControl::MinSize() 67752a38012Sejakowatz { 678349c911eSStephan Aßmus CALLED(); 679349c911eSStephan Aßmus 680349c911eSStephan Aßmus _ValidateLayoutData(); 681349c911eSStephan Aßmus return BLayoutUtils::ComposeSize(ExplicitMinSize(), fLayoutData->min); 682349c911eSStephan Aßmus } 683349c911eSStephan Aßmus 684349c911eSStephan Aßmus 685349c911eSStephan Aßmus BSize 686349c911eSStephan Aßmus BTextControl::MaxSize() 687349c911eSStephan Aßmus { 688349c911eSStephan Aßmus CALLED(); 689349c911eSStephan Aßmus 690349c911eSStephan Aßmus _ValidateLayoutData(); 691349c911eSStephan Aßmus 692349c911eSStephan Aßmus BSize max = fLayoutData->min; 693349c911eSStephan Aßmus max.width = B_SIZE_UNLIMITED; 694349c911eSStephan Aßmus 695349c911eSStephan Aßmus return BLayoutUtils::ComposeSize(ExplicitMaxSize(), max); 696349c911eSStephan Aßmus } 697349c911eSStephan Aßmus 698349c911eSStephan Aßmus 699349c911eSStephan Aßmus BSize 700349c911eSStephan Aßmus BTextControl::PreferredSize() 701349c911eSStephan Aßmus { 702349c911eSStephan Aßmus CALLED(); 703349c911eSStephan Aßmus 704349c911eSStephan Aßmus _ValidateLayoutData(); 705349c911eSStephan Aßmus return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), fLayoutData->min); 706349c911eSStephan Aßmus } 707349c911eSStephan Aßmus 708349c911eSStephan Aßmus 709349c911eSStephan Aßmus void 710349c911eSStephan Aßmus BTextControl::InvalidateLayout(bool descendants) 711349c911eSStephan Aßmus { 712349c911eSStephan Aßmus CALLED(); 713349c911eSStephan Aßmus 714349c911eSStephan Aßmus fLayoutData->valid = false; 715349c911eSStephan Aßmus 716349c911eSStephan Aßmus BView::InvalidateLayout(descendants); 71752a38012Sejakowatz } 718058691d4SStefano Ceccherini 719058691d4SStefano Ceccherini 7209ecf9d1cSIngo Weinhold BLayoutItem* 7219ecf9d1cSIngo Weinhold BTextControl::CreateLabelLayoutItem() 7229ecf9d1cSIngo Weinhold { 723349c911eSStephan Aßmus if (!fLayoutData->label_layout_item) 724349c911eSStephan Aßmus fLayoutData->label_layout_item = new LabelLayoutItem(this); 725349c911eSStephan Aßmus return fLayoutData->label_layout_item; 7269ecf9d1cSIngo Weinhold } 7279ecf9d1cSIngo Weinhold 7289ecf9d1cSIngo Weinhold 7299ecf9d1cSIngo Weinhold BLayoutItem* 7309ecf9d1cSIngo Weinhold BTextControl::CreateTextViewLayoutItem() 7319ecf9d1cSIngo Weinhold { 732349c911eSStephan Aßmus if (!fLayoutData->text_view_layout_item) 733349c911eSStephan Aßmus fLayoutData->text_view_layout_item = new TextViewLayoutItem(this); 734349c911eSStephan Aßmus return fLayoutData->text_view_layout_item; 735349c911eSStephan Aßmus } 736349c911eSStephan Aßmus 737349c911eSStephan Aßmus 738349c911eSStephan Aßmus void 739349c911eSStephan Aßmus BTextControl::DoLayout() 740349c911eSStephan Aßmus { 741349c911eSStephan Aßmus // Bail out, if we shan't do layout. 742349c911eSStephan Aßmus if (!(Flags() & B_SUPPORTS_LAYOUT)) 743349c911eSStephan Aßmus return; 744349c911eSStephan Aßmus 745349c911eSStephan Aßmus CALLED(); 746349c911eSStephan Aßmus 747349c911eSStephan Aßmus // If the user set a layout, we let the base class version call its 748349c911eSStephan Aßmus // hook. 749349c911eSStephan Aßmus if (GetLayout()) { 750349c911eSStephan Aßmus BView::DoLayout(); 751349c911eSStephan Aßmus return; 752349c911eSStephan Aßmus } 753349c911eSStephan Aßmus 754349c911eSStephan Aßmus _ValidateLayoutData(); 755349c911eSStephan Aßmus 756349c911eSStephan Aßmus // validate current size 757349c911eSStephan Aßmus BSize size(Bounds().Size()); 758349c911eSStephan Aßmus if (size.width < fLayoutData->min.width) 759349c911eSStephan Aßmus size.width = fLayoutData->min.width; 760349c911eSStephan Aßmus if (size.height < fLayoutData->min.height) 761349c911eSStephan Aßmus size.height = fLayoutData->min.height; 762349c911eSStephan Aßmus 763349c911eSStephan Aßmus // divider 764349c911eSStephan Aßmus float divider = 0; 765349c911eSStephan Aßmus if (fLayoutData->label_layout_item && fLayoutData->text_view_layout_item) { 766349c911eSStephan Aßmus // We have layout items. They define the divider location. 767349c911eSStephan Aßmus divider = fLayoutData->text_view_layout_item->Frame().left 768349c911eSStephan Aßmus - fLayoutData->label_layout_item->Frame().left; 769349c911eSStephan Aßmus } else { 770349c911eSStephan Aßmus if (fLayoutData->label_width > 0) 771349c911eSStephan Aßmus divider = fLayoutData->label_width + 5; 772349c911eSStephan Aßmus } 773349c911eSStephan Aßmus 774349c911eSStephan Aßmus // text view 775349c911eSStephan Aßmus BRect dirty(fText->Frame()); 776349c911eSStephan Aßmus BRect textFrame(divider + 1, kFrameMargin, size.width - 2, 777349c911eSStephan Aßmus size.height - kFrameMargin); 778349c911eSStephan Aßmus 779349c911eSStephan Aßmus // place the text view and set the divider 780349c911eSStephan Aßmus BLayoutUtils::AlignInFrame(fText, textFrame); 781349c911eSStephan Aßmus 782349c911eSStephan Aßmus fDivider = divider; 783349c911eSStephan Aßmus 784349c911eSStephan Aßmus // invalidate dirty region 785349c911eSStephan Aßmus dirty = dirty | fText->Frame(); 786349c911eSStephan Aßmus dirty.InsetBy(-kFrameMargin, -kFrameMargin); 787349c911eSStephan Aßmus 788349c911eSStephan Aßmus Invalidate(dirty); 789349c911eSStephan Aßmus } 790349c911eSStephan Aßmus 791349c911eSStephan Aßmus 792349c911eSStephan Aßmus // #pragma mark - 793349c911eSStephan Aßmus 794349c911eSStephan Aßmus 795349c911eSStephan Aßmus status_t 796349c911eSStephan Aßmus BTextControl::Perform(perform_code d, void *arg) 797349c911eSStephan Aßmus { 798349c911eSStephan Aßmus return BControl::Perform(d, arg); 7999ecf9d1cSIngo Weinhold } 8009ecf9d1cSIngo Weinhold 8019ecf9d1cSIngo Weinhold 8029cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl1() {} 8039cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl2() {} 8049cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl3() {} 8059cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl4() {} 806058691d4SStefano Ceccherini 807058691d4SStefano Ceccherini 808058691d4SStefano Ceccherini BTextControl & 809058691d4SStefano Ceccherini BTextControl::operator=(const BTextControl&) 81052a38012Sejakowatz { 81152a38012Sejakowatz return *this; 81252a38012Sejakowatz } 813058691d4SStefano Ceccherini 814058691d4SStefano Ceccherini 815058691d4SStefano Ceccherini void 81679c35b39SAxel Dörfler BTextControl::_UpdateTextViewColors(bool enabled) 8173a3f6c1eSAxel Dörfler { 8183a3f6c1eSAxel Dörfler rgb_color textColor; 819aae7000dSAxel Dörfler rgb_color color; 8203a3f6c1eSAxel Dörfler BFont font; 8213a3f6c1eSAxel Dörfler 822aae7000dSAxel Dörfler fText->GetFontAndColor(0, &font); 8233a3f6c1eSAxel Dörfler 8243a3f6c1eSAxel Dörfler if (enabled) 825aae7000dSAxel Dörfler textColor = ui_color(B_DOCUMENT_TEXT_COLOR); 82612aefeb4SAxel Dörfler else { 82712aefeb4SAxel Dörfler textColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 82812aefeb4SAxel Dörfler B_DISABLED_LABEL_TINT); 82912aefeb4SAxel Dörfler } 8303a3f6c1eSAxel Dörfler 8313a3f6c1eSAxel Dörfler fText->SetFontAndColor(&font, B_FONT_ALL, &textColor); 8323a3f6c1eSAxel Dörfler 8333a3f6c1eSAxel Dörfler if (enabled) { 834aae7000dSAxel Dörfler color = ui_color(B_DOCUMENT_BACKGROUND_COLOR); 8353a3f6c1eSAxel Dörfler } else { 8363a3f6c1eSAxel Dörfler color = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 8373a3f6c1eSAxel Dörfler B_LIGHTEN_2_TINT); 8383a3f6c1eSAxel Dörfler } 8393a3f6c1eSAxel Dörfler 8403a3f6c1eSAxel Dörfler fText->SetViewColor(color); 8413a3f6c1eSAxel Dörfler fText->SetLowColor(color); 8423a3f6c1eSAxel Dörfler } 8433a3f6c1eSAxel Dörfler 8443a3f6c1eSAxel Dörfler 8453a3f6c1eSAxel Dörfler void 846ffe72abdSAxel Dörfler BTextControl::_CommitValue() 8479cb2dbe2SMarc Flerackers { 8489cb2dbe2SMarc Flerackers } 849058691d4SStefano Ceccherini 850058691d4SStefano Ceccherini 851058691d4SStefano Ceccherini void 852ffe72abdSAxel Dörfler BTextControl::_InitData(const char* label, const char* initialText, 853ffe72abdSAxel Dörfler BMessage* archive) 8549cb2dbe2SMarc Flerackers { 8559cb2dbe2SMarc Flerackers BRect bounds(Bounds()); 8569cb2dbe2SMarc Flerackers 8579cb2dbe2SMarc Flerackers fText = NULL; 8589cb2dbe2SMarc Flerackers fModificationMessage = NULL; 8599cb2dbe2SMarc Flerackers fLabelAlign = B_ALIGN_LEFT; 8609cb2dbe2SMarc Flerackers fDivider = 0.0f; 861349c911eSStephan Aßmus fLayoutData = new LayoutData(bounds.Width(), bounds.Height()); 8629cb2dbe2SMarc Flerackers 8639cb2dbe2SMarc Flerackers int32 flags = 0; 8649cb2dbe2SMarc Flerackers 865918a22d9SDarkWyrm BFont font(be_plain_font); 8669cb2dbe2SMarc Flerackers 867ffe72abdSAxel Dörfler if (!archive || !archive->HasString("_fname")) 868058691d4SStefano Ceccherini flags |= B_FONT_FAMILY_AND_STYLE; 8699cb2dbe2SMarc Flerackers 870ffe72abdSAxel Dörfler if (!archive || !archive->HasFloat("_fflt")) 871058691d4SStefano Ceccherini flags |= B_FONT_SIZE; 8729cb2dbe2SMarc Flerackers 8739cb2dbe2SMarc Flerackers if (flags != 0) 8749cb2dbe2SMarc Flerackers SetFont(&font, flags); 8759cb2dbe2SMarc Flerackers 8769cb2dbe2SMarc Flerackers if (label) 8772e6a5805SStephan Aßmus fDivider = floorf(bounds.Width() / 2.0f); 8789cb2dbe2SMarc Flerackers 879105644bfSAxel Dörfler uint32 navigableFlags = Flags() & B_NAVIGABLE; 88093ba577cSStephan Aßmus if (navigableFlags != 0) 88193ba577cSStephan Aßmus BView::SetFlags(Flags() & ~B_NAVIGABLE); 8829cb2dbe2SMarc Flerackers 883ffe72abdSAxel Dörfler if (archive) 884b8872c02SStephan Aßmus fText = static_cast<BPrivate::_BTextInput_*>(FindView("_input_")); 885991c062fSAxel Dörfler 886991c062fSAxel Dörfler if (fText == NULL) { 887ee2a3473SStephan Aßmus BRect frame(fDivider, bounds.top, bounds.right, bounds.bottom); 888105644bfSAxel Dörfler // we are stroking the frame around the text view, which 8892e6a5805SStephan Aßmus // is 2 pixels wide 890349c911eSStephan Aßmus frame.InsetBy(kFrameMargin, kFrameMargin); 891111b4fbcSStefano Ceccherini BRect textRect(frame.OffsetToCopy(B_ORIGIN)); 8929cb2dbe2SMarc Flerackers 893b8872c02SStephan Aßmus fText = new BPrivate::_BTextInput_(frame, textRect, 89493ba577cSStephan Aßmus B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS | navigableFlags); 8959cb2dbe2SMarc Flerackers AddChild(fText); 8969cb2dbe2SMarc Flerackers 897455d1c46SAxel Dörfler SetText(initialText); 8989cb2dbe2SMarc Flerackers fText->SetAlignment(B_ALIGN_LEFT); 8999cb2dbe2SMarc Flerackers fText->AlignTextRect(); 9009cb2dbe2SMarc Flerackers } 9019cb2dbe2SMarc Flerackers } 9029ecf9d1cSIngo Weinhold 9039ecf9d1cSIngo Weinhold 9049ecf9d1cSIngo Weinhold void 9059ecf9d1cSIngo Weinhold BTextControl::_ValidateLayout() 9069ecf9d1cSIngo Weinhold { 90793ba577cSStephan Aßmus CALLED(); 90893ba577cSStephan Aßmus 909349c911eSStephan Aßmus _ValidateLayoutData(); 9109ecf9d1cSIngo Weinhold 911349c911eSStephan Aßmus ResizeTo(Bounds().Width(), fLayoutData->min.height); 9129ecf9d1cSIngo Weinhold 913a431f44bSStephan Aßmus _LayoutTextView(); 9149ecf9d1cSIngo Weinhold } 9159ecf9d1cSIngo Weinhold 9169ecf9d1cSIngo Weinhold 9179ecf9d1cSIngo Weinhold void 918a431f44bSStephan Aßmus BTextControl::_LayoutTextView() 919a431f44bSStephan Aßmus { 92093ba577cSStephan Aßmus CALLED(); 92193ba577cSStephan Aßmus 922a431f44bSStephan Aßmus BRect frame = Bounds(); 923a431f44bSStephan Aßmus frame.left = fDivider; 924a431f44bSStephan Aßmus // we are stroking the frame around the text view, which 925a431f44bSStephan Aßmus // is 2 pixels wide 926a431f44bSStephan Aßmus frame.InsetBy(2.0, 2.0); 927a431f44bSStephan Aßmus fText->MoveTo(frame.left, frame.top); 928a431f44bSStephan Aßmus fText->ResizeTo(frame.Width(), frame.Height()); 929b8872c02SStephan Aßmus fText->AlignTextRect(); 93093ba577cSStephan Aßmus 93193ba577cSStephan Aßmus TRACE("width: %.2f, height: %.2f\n", Frame().Width(), Frame().Height()); 93293ba577cSStephan Aßmus TRACE("fDivider: %.2f\n", fDivider); 93393ba577cSStephan Aßmus TRACE("fText frame: (%.2f, %.2f, %.2f, %.2f)\n", 93493ba577cSStephan Aßmus frame.left, frame.top, frame.right, frame.bottom); 935a431f44bSStephan Aßmus } 936a431f44bSStephan Aßmus 937a431f44bSStephan Aßmus 938a431f44bSStephan Aßmus void 9399ecf9d1cSIngo Weinhold BTextControl::_UpdateFrame() 9409ecf9d1cSIngo Weinhold { 941349c911eSStephan Aßmus CALLED(); 942349c911eSStephan Aßmus 943349c911eSStephan Aßmus if (fLayoutData->label_layout_item && fLayoutData->text_view_layout_item) { 944349c911eSStephan Aßmus BRect labelFrame = fLayoutData->label_layout_item->Frame(); 945349c911eSStephan Aßmus BRect textFrame = fLayoutData->text_view_layout_item->Frame(); 946349c911eSStephan Aßmus 947349c911eSStephan Aßmus // update divider 948349c911eSStephan Aßmus fDivider = textFrame.left - labelFrame.left; 949349c911eSStephan Aßmus 9509ecf9d1cSIngo Weinhold MoveTo(labelFrame.left, labelFrame.top); 951349c911eSStephan Aßmus BSize oldSize = Bounds().Size(); 9529ecf9d1cSIngo Weinhold ResizeTo(textFrame.left + textFrame.Width() - labelFrame.left, 9539ecf9d1cSIngo Weinhold textFrame.top + textFrame.Height() - labelFrame.top); 954349c911eSStephan Aßmus BSize newSize = Bounds().Size(); 955349c911eSStephan Aßmus 956349c911eSStephan Aßmus // If the size changes, ResizeTo() will trigger a relayout, otherwise 957349c911eSStephan Aßmus // we need to do that explicitly. 958349c911eSStephan Aßmus if (newSize != oldSize) 959349c911eSStephan Aßmus Relayout(); 9609ecf9d1cSIngo Weinhold } 9619ecf9d1cSIngo Weinhold } 9629ecf9d1cSIngo Weinhold 9639ecf9d1cSIngo Weinhold 964349c911eSStephan Aßmus void 965349c911eSStephan Aßmus BTextControl::_ValidateLayoutData() 966349c911eSStephan Aßmus { 967349c911eSStephan Aßmus CALLED(); 968349c911eSStephan Aßmus 969349c911eSStephan Aßmus if (fLayoutData->valid) 970349c911eSStephan Aßmus return; 971349c911eSStephan Aßmus 972349c911eSStephan Aßmus // cache font height 973349c911eSStephan Aßmus font_height& fh = fLayoutData->font_info; 974349c911eSStephan Aßmus GetFontHeight(&fh); 975349c911eSStephan Aßmus 976349c911eSStephan Aßmus if (Label() != NULL) { 977349c911eSStephan Aßmus fLayoutData->label_width = ceilf(StringWidth(Label())); 978349c911eSStephan Aßmus fLayoutData->label_height = ceilf(fh.ascent) + ceilf(fh.descent); 979349c911eSStephan Aßmus } else { 980349c911eSStephan Aßmus fLayoutData->label_width = 0; 981349c911eSStephan Aßmus fLayoutData->label_height = 0; 982349c911eSStephan Aßmus } 983349c911eSStephan Aßmus 984349c911eSStephan Aßmus // compute the minimal divider 985349c911eSStephan Aßmus float divider = 0; 986349c911eSStephan Aßmus if (fLayoutData->label_width > 0) 987349c911eSStephan Aßmus divider = fLayoutData->label_width + 5; 988349c911eSStephan Aßmus 989349c911eSStephan Aßmus // If we shan't do real layout, we let the current divider take influence. 990349c911eSStephan Aßmus if (!(Flags() & B_SUPPORTS_LAYOUT)) 991349c911eSStephan Aßmus divider = max_c(divider, fDivider); 992349c911eSStephan Aßmus 993349c911eSStephan Aßmus // get the minimal (== preferred) text view size 994349c911eSStephan Aßmus fLayoutData->text_view_min = fText->MinSize(); 995349c911eSStephan Aßmus 996349c911eSStephan Aßmus TRACE("text view min width: %.2f\n", fLayoutData->text_view_min.width); 997349c911eSStephan Aßmus 998349c911eSStephan Aßmus // compute our minimal (== preferred) size 999349c911eSStephan Aßmus BSize min(fLayoutData->text_view_min); 1000349c911eSStephan Aßmus min.width += 2 * kFrameMargin; 1001349c911eSStephan Aßmus min.height += 2 * kFrameMargin; 1002349c911eSStephan Aßmus 1003349c911eSStephan Aßmus if (divider > 0) 1004349c911eSStephan Aßmus min.width += divider; 1005349c911eSStephan Aßmus if (fLayoutData->label_height > min.height) 1006349c911eSStephan Aßmus min.height = fLayoutData->label_height; 1007349c911eSStephan Aßmus 1008349c911eSStephan Aßmus fLayoutData->min = min; 1009349c911eSStephan Aßmus 1010349c911eSStephan Aßmus fLayoutData->valid = true; 1011349c911eSStephan Aßmus 1012349c911eSStephan Aßmus TRACE("width: %.2f, height: %.2f\n", min.width, min.height); 1013349c911eSStephan Aßmus } 1014349c911eSStephan Aßmus 1015349c911eSStephan Aßmus 10169ecf9d1cSIngo Weinhold // #pragma mark - 10179ecf9d1cSIngo Weinhold 10189ecf9d1cSIngo Weinhold 10199ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::LabelLayoutItem(BTextControl* parent) 10209ecf9d1cSIngo Weinhold : fParent(parent), 10219ecf9d1cSIngo Weinhold fFrame() 10229ecf9d1cSIngo Weinhold { 10239ecf9d1cSIngo Weinhold } 10249ecf9d1cSIngo Weinhold 10259ecf9d1cSIngo Weinhold 10269ecf9d1cSIngo Weinhold bool 10279ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::IsVisible() 10289ecf9d1cSIngo Weinhold { 10299ecf9d1cSIngo Weinhold return !fParent->IsHidden(fParent); 10309ecf9d1cSIngo Weinhold } 10319ecf9d1cSIngo Weinhold 10329ecf9d1cSIngo Weinhold 10339ecf9d1cSIngo Weinhold void 10349ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::SetVisible(bool visible) 10359ecf9d1cSIngo Weinhold { 10369ecf9d1cSIngo Weinhold // not allowed 10379ecf9d1cSIngo Weinhold } 10389ecf9d1cSIngo Weinhold 10399ecf9d1cSIngo Weinhold 10409ecf9d1cSIngo Weinhold BRect 10419ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::Frame() 10429ecf9d1cSIngo Weinhold { 10439ecf9d1cSIngo Weinhold return fFrame; 10449ecf9d1cSIngo Weinhold } 10459ecf9d1cSIngo Weinhold 10469ecf9d1cSIngo Weinhold 10479ecf9d1cSIngo Weinhold void 10489ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::SetFrame(BRect frame) 10499ecf9d1cSIngo Weinhold { 10509ecf9d1cSIngo Weinhold fFrame = frame; 10519ecf9d1cSIngo Weinhold fParent->_UpdateFrame(); 10529ecf9d1cSIngo Weinhold } 10539ecf9d1cSIngo Weinhold 10549ecf9d1cSIngo Weinhold 10559ecf9d1cSIngo Weinhold BView* 10569ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::View() 10579ecf9d1cSIngo Weinhold { 10589ecf9d1cSIngo Weinhold return fParent; 10599ecf9d1cSIngo Weinhold } 10609ecf9d1cSIngo Weinhold 10619ecf9d1cSIngo Weinhold 10629ecf9d1cSIngo Weinhold BSize 10639ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BaseMinSize() 10649ecf9d1cSIngo Weinhold { 1065349c911eSStephan Aßmus fParent->_ValidateLayoutData(); 1066349c911eSStephan Aßmus 1067349c911eSStephan Aßmus if (!fParent->Label()) 10689ecf9d1cSIngo Weinhold return BSize(-1, -1); 10699ecf9d1cSIngo Weinhold 1070349c911eSStephan Aßmus return BSize(fParent->fLayoutData->label_width + 5, 1071349c911eSStephan Aßmus fParent->fLayoutData->label_height); 10729ecf9d1cSIngo Weinhold } 10739ecf9d1cSIngo Weinhold 10749ecf9d1cSIngo Weinhold 10759ecf9d1cSIngo Weinhold BSize 10769ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BaseMaxSize() 10779ecf9d1cSIngo Weinhold { 10789ecf9d1cSIngo Weinhold return BaseMinSize(); 10799ecf9d1cSIngo Weinhold } 10809ecf9d1cSIngo Weinhold 10819ecf9d1cSIngo Weinhold 10829ecf9d1cSIngo Weinhold BSize 10839ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BasePreferredSize() 10849ecf9d1cSIngo Weinhold { 10859ecf9d1cSIngo Weinhold return BaseMinSize(); 10869ecf9d1cSIngo Weinhold } 10879ecf9d1cSIngo Weinhold 10889ecf9d1cSIngo Weinhold 10899ecf9d1cSIngo Weinhold BAlignment 10909ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BaseAlignment() 10919ecf9d1cSIngo Weinhold { 10929ecf9d1cSIngo Weinhold return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); 10939ecf9d1cSIngo Weinhold } 10949ecf9d1cSIngo Weinhold 10959ecf9d1cSIngo Weinhold 10969ecf9d1cSIngo Weinhold // #pragma mark - 10979ecf9d1cSIngo Weinhold 10989ecf9d1cSIngo Weinhold 10999ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::TextViewLayoutItem(BTextControl* parent) 11009ecf9d1cSIngo Weinhold : fParent(parent), 11019ecf9d1cSIngo Weinhold fFrame() 11029ecf9d1cSIngo Weinhold { 1103349c911eSStephan Aßmus // by default the part right of the divider shall have an unlimited maximum 1104349c911eSStephan Aßmus // width 1105349c911eSStephan Aßmus SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 11069ecf9d1cSIngo Weinhold } 11079ecf9d1cSIngo Weinhold 11089ecf9d1cSIngo Weinhold 11099ecf9d1cSIngo Weinhold bool 11109ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::IsVisible() 11119ecf9d1cSIngo Weinhold { 11129ecf9d1cSIngo Weinhold return !fParent->IsHidden(fParent); 11139ecf9d1cSIngo Weinhold } 11149ecf9d1cSIngo Weinhold 11159ecf9d1cSIngo Weinhold 11169ecf9d1cSIngo Weinhold void 11179ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::SetVisible(bool visible) 11189ecf9d1cSIngo Weinhold { 11199ecf9d1cSIngo Weinhold // not allowed 11209ecf9d1cSIngo Weinhold } 11219ecf9d1cSIngo Weinhold 11229ecf9d1cSIngo Weinhold 11239ecf9d1cSIngo Weinhold BRect 11249ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::Frame() 11259ecf9d1cSIngo Weinhold { 11269ecf9d1cSIngo Weinhold return fFrame; 11279ecf9d1cSIngo Weinhold } 11289ecf9d1cSIngo Weinhold 11299ecf9d1cSIngo Weinhold 11309ecf9d1cSIngo Weinhold void 11319ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::SetFrame(BRect frame) 11329ecf9d1cSIngo Weinhold { 11339ecf9d1cSIngo Weinhold fFrame = frame; 11349ecf9d1cSIngo Weinhold fParent->_UpdateFrame(); 11359ecf9d1cSIngo Weinhold } 11369ecf9d1cSIngo Weinhold 11379ecf9d1cSIngo Weinhold 11389ecf9d1cSIngo Weinhold BView* 11399ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::View() 11409ecf9d1cSIngo Weinhold { 11419ecf9d1cSIngo Weinhold return fParent; 11429ecf9d1cSIngo Weinhold } 11439ecf9d1cSIngo Weinhold 11449ecf9d1cSIngo Weinhold 11459ecf9d1cSIngo Weinhold BSize 11469ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BaseMinSize() 11479ecf9d1cSIngo Weinhold { 1148349c911eSStephan Aßmus fParent->_ValidateLayoutData(); 11499ecf9d1cSIngo Weinhold 1150349c911eSStephan Aßmus BSize size = fParent->fLayoutData->text_view_min; 1151349c911eSStephan Aßmus size.width += 2 * kFrameMargin; 1152349c911eSStephan Aßmus size.height += 2 * kFrameMargin; 11539ecf9d1cSIngo Weinhold 11549ecf9d1cSIngo Weinhold return size; 11559ecf9d1cSIngo Weinhold } 11569ecf9d1cSIngo Weinhold 11579ecf9d1cSIngo Weinhold 11589ecf9d1cSIngo Weinhold BSize 11599ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BaseMaxSize() 11609ecf9d1cSIngo Weinhold { 11619ecf9d1cSIngo Weinhold BSize size(BaseMinSize()); 11629ecf9d1cSIngo Weinhold size.width = B_SIZE_UNLIMITED; 11639ecf9d1cSIngo Weinhold return size; 11649ecf9d1cSIngo Weinhold } 11659ecf9d1cSIngo Weinhold 11669ecf9d1cSIngo Weinhold 11679ecf9d1cSIngo Weinhold BSize 11689ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BasePreferredSize() 11699ecf9d1cSIngo Weinhold { 11709ecf9d1cSIngo Weinhold BSize size(BaseMinSize()); 11719ecf9d1cSIngo Weinhold // puh, no idea... 11729ecf9d1cSIngo Weinhold size.width = 100; 11739ecf9d1cSIngo Weinhold return size; 11749ecf9d1cSIngo Weinhold } 11759ecf9d1cSIngo Weinhold 11769ecf9d1cSIngo Weinhold 11779ecf9d1cSIngo Weinhold BAlignment 11789ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BaseAlignment() 11799ecf9d1cSIngo Weinhold { 11809ecf9d1cSIngo Weinhold return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); 11819ecf9d1cSIngo Weinhold } 11829ecf9d1cSIngo Weinhold 1183