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 13c121b41fSRene Gollent #include <string.h> 14c121b41fSRene Gollent 152f86ba45SStephan Aßmus #include <TextControl.h> 16105644bfSAxel Dörfler 179ecf9d1cSIngo Weinhold #include <AbstractLayoutItem.h> 182f86ba45SStephan Aßmus #include <ControlLook.h> 199ecf9d1cSIngo Weinhold #include <LayoutUtils.h> 20058691d4SStefano Ceccherini #include <Message.h> 212a30a9e9SRene Gollent #include <PropertyInfo.h> 22455d1c46SAxel Dörfler #include <Region.h> 2352a38012Sejakowatz #include <Window.h> 2452a38012Sejakowatz 2539fbf550SOliver Tappe #include <binary_compatibility/Interface.h> 265c47e35eSAlex Wilson #include <binary_compatibility/Support.h> 2739fbf550SOliver Tappe 2852a38012Sejakowatz #include "TextInput.h" 2952a38012Sejakowatz 3052a38012Sejakowatz 3193ba577cSStephan Aßmus //#define TRACE_TEXT_CONTROL 3293ba577cSStephan Aßmus #ifdef TRACE_TEXT_CONTROL 3373161598SJérôme Duval # include <stdio.h> 3493ba577cSStephan Aßmus # include <FunctionTracer.h> 3593ba577cSStephan Aßmus static int32 sFunctionDepth = -1; 36349c911eSStephan Aßmus # define CALLED(x...) FunctionTracer _ft("BTextControl", __FUNCTION__, \ 3793ba577cSStephan Aßmus sFunctionDepth) 3893ba577cSStephan Aßmus # define TRACE(x...) { BString _to; \ 3993ba577cSStephan Aßmus _to.Append(' ', (sFunctionDepth + 1) * 2); \ 4093ba577cSStephan Aßmus printf("%s", _to.String()); printf(x); } 4193ba577cSStephan Aßmus #else 4293ba577cSStephan Aßmus # define CALLED(x...) 4393ba577cSStephan Aßmus # define TRACE(x...) 4493ba577cSStephan Aßmus #endif 4593ba577cSStephan Aßmus 4693ba577cSStephan Aßmus 475c47e35eSAlex Wilson namespace { 485c47e35eSAlex Wilson const char* const kFrameField = "BTextControl:layoutitem:frame"; 495c47e35eSAlex Wilson const char* const kTextViewItemField = "BTextControl:textViewItem"; 505c47e35eSAlex Wilson const char* const kLabelItemField = "BMenuField:labelItem"; 515c47e35eSAlex Wilson } 525c47e35eSAlex Wilson 535c47e35eSAlex Wilson 542a30a9e9SRene Gollent static property_info sPropertyList[] = { 552a30a9e9SRene Gollent { 562a30a9e9SRene Gollent "Value", 572a30a9e9SRene Gollent { B_GET_PROPERTY, B_SET_PROPERTY }, 582a30a9e9SRene Gollent { B_DIRECT_SPECIFIER }, 592a30a9e9SRene Gollent NULL, 0, 602a30a9e9SRene Gollent { B_STRING_TYPE } 612a30a9e9SRene Gollent }, 622a30a9e9SRene Gollent {} 632a30a9e9SRene Gollent }; 642a30a9e9SRene Gollent 652a30a9e9SRene Gollent 669ecf9d1cSIngo Weinhold class BTextControl::LabelLayoutItem : public BAbstractLayoutItem { 679ecf9d1cSIngo Weinhold public: 689ecf9d1cSIngo Weinhold LabelLayoutItem(BTextControl* parent); 695c47e35eSAlex Wilson LabelLayoutItem(BMessage* from); 709ecf9d1cSIngo Weinhold 719ecf9d1cSIngo Weinhold virtual bool IsVisible(); 729ecf9d1cSIngo Weinhold virtual void SetVisible(bool visible); 739ecf9d1cSIngo Weinhold 749ecf9d1cSIngo Weinhold virtual BRect Frame(); 759ecf9d1cSIngo Weinhold virtual void SetFrame(BRect frame); 769ecf9d1cSIngo Weinhold 775c47e35eSAlex Wilson void SetParent(BTextControl* parent); 789ecf9d1cSIngo Weinhold virtual BView* View(); 799ecf9d1cSIngo Weinhold 809ecf9d1cSIngo Weinhold virtual BSize BaseMinSize(); 819ecf9d1cSIngo Weinhold virtual BSize BaseMaxSize(); 829ecf9d1cSIngo Weinhold virtual BSize BasePreferredSize(); 839ecf9d1cSIngo Weinhold virtual BAlignment BaseAlignment(); 849ecf9d1cSIngo Weinhold 855c47e35eSAlex Wilson virtual status_t Archive(BMessage* into, bool deep = true) const; 865c47e35eSAlex Wilson static BArchivable* Instantiate(BMessage* from); 879ecf9d1cSIngo Weinhold private: 889ecf9d1cSIngo Weinhold BTextControl* fParent; 899ecf9d1cSIngo Weinhold BRect fFrame; 909ecf9d1cSIngo Weinhold }; 919ecf9d1cSIngo Weinhold 929ecf9d1cSIngo Weinhold 939ecf9d1cSIngo Weinhold class BTextControl::TextViewLayoutItem : public BAbstractLayoutItem { 949ecf9d1cSIngo Weinhold public: 959ecf9d1cSIngo Weinhold TextViewLayoutItem(BTextControl* parent); 965c47e35eSAlex Wilson TextViewLayoutItem(BMessage* from); 979ecf9d1cSIngo Weinhold 989ecf9d1cSIngo Weinhold virtual bool IsVisible(); 999ecf9d1cSIngo Weinhold virtual void SetVisible(bool visible); 1009ecf9d1cSIngo Weinhold 1019ecf9d1cSIngo Weinhold virtual BRect Frame(); 1029ecf9d1cSIngo Weinhold virtual void SetFrame(BRect frame); 1039ecf9d1cSIngo Weinhold 1045c47e35eSAlex Wilson void SetParent(BTextControl* parent); 1059ecf9d1cSIngo Weinhold virtual BView* View(); 1069ecf9d1cSIngo Weinhold 1079ecf9d1cSIngo Weinhold virtual BSize BaseMinSize(); 1089ecf9d1cSIngo Weinhold virtual BSize BaseMaxSize(); 1099ecf9d1cSIngo Weinhold virtual BSize BasePreferredSize(); 1109ecf9d1cSIngo Weinhold virtual BAlignment BaseAlignment(); 1119ecf9d1cSIngo Weinhold 1125c47e35eSAlex Wilson virtual status_t Archive(BMessage* into, bool deep = true) const; 1135c47e35eSAlex Wilson static BArchivable* Instantiate(BMessage* from); 1149ecf9d1cSIngo Weinhold private: 1159ecf9d1cSIngo Weinhold BTextControl* fParent; 1169ecf9d1cSIngo Weinhold BRect fFrame; 1179ecf9d1cSIngo Weinhold }; 1189ecf9d1cSIngo Weinhold 1199ecf9d1cSIngo Weinhold 120349c911eSStephan Aßmus struct BTextControl::LayoutData { 121349c911eSStephan Aßmus LayoutData(float width, float height) 1225c47e35eSAlex Wilson : 1235c47e35eSAlex Wilson label_layout_item(NULL), 124349c911eSStephan Aßmus text_view_layout_item(NULL), 125349c911eSStephan Aßmus previous_width(width), 126349c911eSStephan Aßmus previous_height(height), 127349c911eSStephan Aßmus valid(false) 128349c911eSStephan Aßmus { 129349c911eSStephan Aßmus } 130349c911eSStephan Aßmus 131349c911eSStephan Aßmus LabelLayoutItem* label_layout_item; 132349c911eSStephan Aßmus TextViewLayoutItem* text_view_layout_item; 133349c911eSStephan Aßmus float previous_width; // used in FrameResized() for 134349c911eSStephan Aßmus float previous_height; // invalidation 135349c911eSStephan Aßmus font_height font_info; 136349c911eSStephan Aßmus float label_width; 137349c911eSStephan Aßmus float label_height; 138349c911eSStephan Aßmus BSize min; 139349c911eSStephan Aßmus BSize text_view_min; 140349c911eSStephan Aßmus bool valid; 141349c911eSStephan Aßmus }; 142349c911eSStephan Aßmus 143349c911eSStephan Aßmus 1449ecf9d1cSIngo Weinhold // #pragma mark - 1459ecf9d1cSIngo Weinhold 1469ecf9d1cSIngo Weinhold 147349c911eSStephan Aßmus static const int32 kFrameMargin = 2; 148349c911eSStephan Aßmus static const int32 kLabelInputSpacing = 3; 149349c911eSStephan Aßmus 150349c911eSStephan Aßmus 15152a38012Sejakowatz BTextControl::BTextControl(BRect frame, const char* name, const char* label, 152991c062fSAxel Dörfler const char* text, BMessage* message, uint32 mask, uint32 flags) 1535c47e35eSAlex Wilson : 1545c47e35eSAlex Wilson BControl(frame, name, label, message, mask, flags | B_FRAME_EVENTS) 15552a38012Sejakowatz { 1565c47e35eSAlex Wilson _InitData(label); 1575c47e35eSAlex Wilson _InitText(text); 1589ecf9d1cSIngo Weinhold _ValidateLayout(); 1599ecf9d1cSIngo Weinhold } 16052a38012Sejakowatz 161105644bfSAxel Dörfler 1629ecf9d1cSIngo Weinhold BTextControl::BTextControl(const char* name, const char* label, 163991c062fSAxel Dörfler const char* text, BMessage* message, uint32 flags) 1645c47e35eSAlex Wilson : 1655c47e35eSAlex Wilson BControl(name, label, message, flags | B_FRAME_EVENTS) 1669ecf9d1cSIngo Weinhold { 1675c47e35eSAlex Wilson _InitData(label); 1685c47e35eSAlex Wilson _InitText(text); 1699ecf9d1cSIngo Weinhold _ValidateLayout(); 1709ecf9d1cSIngo Weinhold } 171105644bfSAxel Dörfler 172ffe72abdSAxel Dörfler 173991c062fSAxel Dörfler BTextControl::BTextControl(const char* label, const char* text, 174991c062fSAxel Dörfler BMessage* message) 1755c47e35eSAlex Wilson : 1765c47e35eSAlex Wilson BControl(NULL, label, message, 17793ba577cSStephan Aßmus B_WILL_DRAW | B_NAVIGABLE | B_FRAME_EVENTS) 1789ecf9d1cSIngo Weinhold { 1795c47e35eSAlex Wilson _InitData(label); 1805c47e35eSAlex Wilson _InitText(text); 1819ecf9d1cSIngo Weinhold _ValidateLayout(); 18252a38012Sejakowatz } 183058691d4SStefano Ceccherini 184058691d4SStefano Ceccherini 18552a38012Sejakowatz BTextControl::~BTextControl() 18652a38012Sejakowatz { 1879cb2dbe2SMarc Flerackers SetModificationMessage(NULL); 18853aaed9fSStephan Aßmus delete fLayoutData; 18952a38012Sejakowatz } 190058691d4SStefano Ceccherini 191058691d4SStefano Ceccherini 192ffe72abdSAxel Dörfler BTextControl::BTextControl(BMessage* archive) 1935c47e35eSAlex Wilson : 1945c47e35eSAlex Wilson BControl(BUnarchiver::PrepareArchive(archive)) 19552a38012Sejakowatz { 1965c47e35eSAlex Wilson BUnarchiver unarchiver(archive); 19752a38012Sejakowatz 1985c47e35eSAlex Wilson _InitData(Label(), archive); 19952a38012Sejakowatz 2005c47e35eSAlex Wilson if (!BUnarchiver::IsArchiveManaged(archive)) 2015c47e35eSAlex Wilson _InitText(NULL, archive); 20252a38012Sejakowatz 2035c47e35eSAlex Wilson status_t err = B_OK; 204ffe72abdSAxel Dörfler if (archive->HasFloat("_divide")) 2055c47e35eSAlex Wilson err = archive->FindFloat("_divide", &fDivider); 2069cb2dbe2SMarc Flerackers 2075c47e35eSAlex Wilson if (err == B_OK && archive->HasMessage("_mod_msg")) { 208ffe72abdSAxel Dörfler BMessage* message = new BMessage; 2095c47e35eSAlex Wilson err = archive->FindMessage("_mod_msg", message); 210ffe72abdSAxel Dörfler SetModificationMessage(message); 2119cb2dbe2SMarc Flerackers } 2125c47e35eSAlex Wilson 2135c47e35eSAlex Wilson unarchiver.Finish(err); 21452a38012Sejakowatz } 215058691d4SStefano Ceccherini 216058691d4SStefano Ceccherini 217058691d4SStefano Ceccherini BArchivable* 218058691d4SStefano Ceccherini BTextControl::Instantiate(BMessage* archive) 21952a38012Sejakowatz { 2209cb2dbe2SMarc Flerackers if (validate_instantiation(archive, "BTextControl")) 2219cb2dbe2SMarc Flerackers return new BTextControl(archive); 222991c062fSAxel Dörfler 22352a38012Sejakowatz return NULL; 22452a38012Sejakowatz } 225058691d4SStefano Ceccherini 226058691d4SStefano Ceccherini 227058691d4SStefano Ceccherini status_t 228058691d4SStefano Ceccherini BTextControl::Archive(BMessage *data, bool deep) const 22952a38012Sejakowatz { 2305c47e35eSAlex Wilson BArchiver archiver(data); 2313a543720SJérôme Duval status_t ret = BControl::Archive(data, deep); 232058691d4SStefano Ceccherini alignment labelAlignment, textAlignment; 23352a38012Sejakowatz 234058691d4SStefano Ceccherini GetAlignment(&labelAlignment, &textAlignment); 2359cb2dbe2SMarc Flerackers 23611d7ecebSJérôme Duval if (ret == B_OK) 23711d7ecebSJérôme Duval ret = data->AddInt32("_a_label", labelAlignment); 23811d7ecebSJérôme Duval if (ret == B_OK) 23911d7ecebSJérôme Duval ret = data->AddInt32("_a_text", textAlignment); 24011d7ecebSJérôme Duval if (ret == B_OK) 24111d7ecebSJérôme Duval ret = data->AddFloat("_divide", Divider()); 2429cb2dbe2SMarc Flerackers 24311d7ecebSJérôme Duval if (ModificationMessage() && (ret == B_OK)) 24411d7ecebSJérôme Duval ret = data->AddMessage("_mod_msg", ModificationMessage()); 2459cb2dbe2SMarc Flerackers 2465c47e35eSAlex Wilson return archiver.Finish(ret); 2475c47e35eSAlex Wilson } 2485c47e35eSAlex Wilson 2495c47e35eSAlex Wilson 2505c47e35eSAlex Wilson status_t 2515c47e35eSAlex Wilson BTextControl::AllArchived(BMessage* into) const 2525c47e35eSAlex Wilson { 2535c47e35eSAlex Wilson BArchiver archiver(into); 2545c47e35eSAlex Wilson status_t err = B_OK; 2555c47e35eSAlex Wilson 2565c47e35eSAlex Wilson if (archiver.IsArchived(fLayoutData->text_view_layout_item)) { 2575c47e35eSAlex Wilson err = archiver.AddArchivable(kTextViewItemField, 2585c47e35eSAlex Wilson fLayoutData->text_view_layout_item); 2595c47e35eSAlex Wilson } 2605c47e35eSAlex Wilson 2615c47e35eSAlex Wilson if (err == B_OK && archiver.IsArchived(fLayoutData->label_layout_item)) { 2625c47e35eSAlex Wilson err = archiver.AddArchivable(kLabelItemField, 2635c47e35eSAlex Wilson fLayoutData->label_layout_item); 2645c47e35eSAlex Wilson } 2655c47e35eSAlex Wilson 2665c47e35eSAlex Wilson return err; 2675c47e35eSAlex Wilson } 2685c47e35eSAlex Wilson 2695c47e35eSAlex Wilson 2705c47e35eSAlex Wilson status_t 2715c47e35eSAlex Wilson BTextControl::AllUnarchived(const BMessage* from) 2725c47e35eSAlex Wilson { 2735c47e35eSAlex Wilson status_t err; 2745c47e35eSAlex Wilson if ((err = BControl::AllUnarchived(from)) != B_OK) 2755c47e35eSAlex Wilson return err; 2765c47e35eSAlex Wilson 2775c47e35eSAlex Wilson _InitText(NULL, from); 2785c47e35eSAlex Wilson 2795c47e35eSAlex Wilson BUnarchiver unarchiver(from); 2805c47e35eSAlex Wilson if (unarchiver.IsInstantiated(kTextViewItemField)) { 2815c47e35eSAlex Wilson err = unarchiver.FindObject(kTextViewItemField, 2825c47e35eSAlex Wilson BUnarchiver::B_DONT_ASSUME_OWNERSHIP, 2835c47e35eSAlex Wilson fLayoutData->text_view_layout_item); 2845c47e35eSAlex Wilson 2855c47e35eSAlex Wilson if (err == B_OK) 2865c47e35eSAlex Wilson fLayoutData->text_view_layout_item->SetParent(this); 2875c47e35eSAlex Wilson else 2885c47e35eSAlex Wilson return err; 2895c47e35eSAlex Wilson } 2905c47e35eSAlex Wilson 2915c47e35eSAlex Wilson if (unarchiver.IsInstantiated(kLabelItemField)) { 2925c47e35eSAlex Wilson err = unarchiver.FindObject(kLabelItemField, 2935c47e35eSAlex Wilson BUnarchiver::B_DONT_ASSUME_OWNERSHIP, 2945c47e35eSAlex Wilson fLayoutData->label_layout_item); 2955c47e35eSAlex Wilson 2965c47e35eSAlex Wilson if (err == B_OK) 2975c47e35eSAlex Wilson fLayoutData->label_layout_item->SetParent(this); 2985c47e35eSAlex Wilson } 2995c47e35eSAlex Wilson return err; 30052a38012Sejakowatz } 301058691d4SStefano Ceccherini 302058691d4SStefano Ceccherini 303058691d4SStefano Ceccherini void 304058691d4SStefano Ceccherini BTextControl::SetText(const char *text) 30552a38012Sejakowatz { 3069cb2dbe2SMarc Flerackers if (InvokeKind() != B_CONTROL_INVOKED) 3079cb2dbe2SMarc Flerackers return; 3089cb2dbe2SMarc Flerackers 30993ba577cSStephan Aßmus CALLED(); 31093ba577cSStephan Aßmus 31152a38012Sejakowatz fText->SetText(text); 3129cb2dbe2SMarc Flerackers 3135b349aa2SJérôme Duval if (fText->IsFocus()) { 3149cb2dbe2SMarc Flerackers fText->SetInitialText(); 3155b349aa2SJérôme Duval fText->SelectAll(); 3165b349aa2SJérôme Duval } 3179cb2dbe2SMarc Flerackers 3189cb2dbe2SMarc Flerackers fText->Invalidate(); 31952a38012Sejakowatz } 320058691d4SStefano Ceccherini 321058691d4SStefano Ceccherini 322058691d4SStefano Ceccherini const char * 323058691d4SStefano Ceccherini BTextControl::Text() const 32452a38012Sejakowatz { 32552a38012Sejakowatz return fText->Text(); 32652a38012Sejakowatz } 327058691d4SStefano Ceccherini 328058691d4SStefano Ceccherini 329058691d4SStefano Ceccherini void 330058691d4SStefano Ceccherini BTextControl::SetValue(int32 value) 33152a38012Sejakowatz { 3329cb2dbe2SMarc Flerackers BControl::SetValue(value); 33352a38012Sejakowatz } 334058691d4SStefano Ceccherini 335058691d4SStefano Ceccherini 336058691d4SStefano Ceccherini status_t 337058691d4SStefano Ceccherini BTextControl::Invoke(BMessage *message) 33852a38012Sejakowatz { 339058691d4SStefano Ceccherini return BControl::Invoke(message); 34052a38012Sejakowatz } 341058691d4SStefano Ceccherini 342058691d4SStefano Ceccherini 343058691d4SStefano Ceccherini BTextView * 344058691d4SStefano Ceccherini BTextControl::TextView() const 34552a38012Sejakowatz { 3469cb2dbe2SMarc Flerackers return fText; 34752a38012Sejakowatz } 348058691d4SStefano Ceccherini 349058691d4SStefano Ceccherini 350058691d4SStefano Ceccherini void 351058691d4SStefano Ceccherini BTextControl::SetModificationMessage(BMessage *message) 35252a38012Sejakowatz { 3539cb2dbe2SMarc Flerackers delete fModificationMessage; 35452a38012Sejakowatz fModificationMessage = message; 35552a38012Sejakowatz } 356058691d4SStefano Ceccherini 357058691d4SStefano Ceccherini 358058691d4SStefano Ceccherini BMessage * 359058691d4SStefano Ceccherini BTextControl::ModificationMessage() const 36052a38012Sejakowatz { 36152a38012Sejakowatz return fModificationMessage; 36252a38012Sejakowatz } 363058691d4SStefano Ceccherini 364058691d4SStefano Ceccherini 365058691d4SStefano Ceccherini void 366058691d4SStefano Ceccherini BTextControl::SetAlignment(alignment labelAlignment, alignment textAlignment) 36752a38012Sejakowatz { 368058691d4SStefano Ceccherini fText->SetAlignment(textAlignment); 3699cb2dbe2SMarc Flerackers fText->AlignTextRect(); 3709cb2dbe2SMarc Flerackers 371058691d4SStefano Ceccherini if (fLabelAlign != labelAlignment) { 372058691d4SStefano Ceccherini fLabelAlign = labelAlignment; 3739cb2dbe2SMarc Flerackers Invalidate(); 3749cb2dbe2SMarc Flerackers } 37552a38012Sejakowatz } 376058691d4SStefano Ceccherini 377058691d4SStefano Ceccherini 378058691d4SStefano Ceccherini void 379c432fbbbSAxel Dörfler BTextControl::GetAlignment(alignment* _label, alignment* _text) const 38052a38012Sejakowatz { 381c432fbbbSAxel Dörfler if (_label) 382c432fbbbSAxel Dörfler *_label = fLabelAlign; 383c432fbbbSAxel Dörfler if (_text) 384c432fbbbSAxel Dörfler *_text = fText->Alignment(); 38552a38012Sejakowatz } 3869cb2dbe2SMarc Flerackers 387058691d4SStefano Ceccherini 388058691d4SStefano Ceccherini void 389058691d4SStefano Ceccherini BTextControl::SetDivider(float dividingLine) 390058691d4SStefano Ceccherini { 391a431f44bSStephan Aßmus fDivider = floorf(dividingLine + 0.5); 3922e6a5805SStephan Aßmus 393a431f44bSStephan Aßmus _LayoutTextView(); 39452a38012Sejakowatz 395058691d4SStefano Ceccherini if (Window()) { 39652a38012Sejakowatz fText->Invalidate(); 39752a38012Sejakowatz Invalidate(); 39852a38012Sejakowatz } 3999cb2dbe2SMarc Flerackers } 400058691d4SStefano Ceccherini 401058691d4SStefano Ceccherini 402058691d4SStefano Ceccherini float 403058691d4SStefano Ceccherini BTextControl::Divider() const 40452a38012Sejakowatz { 40552a38012Sejakowatz return fDivider; 40652a38012Sejakowatz } 407058691d4SStefano Ceccherini 408058691d4SStefano Ceccherini 409058691d4SStefano Ceccherini void 410058691d4SStefano Ceccherini BTextControl::Draw(BRect updateRect) 41152a38012Sejakowatz { 4122f86ba45SStephan Aßmus bool enabled = IsEnabled(); 4132f86ba45SStephan Aßmus bool active = fText->IsFocus() && Window()->IsActive(); 4142f86ba45SStephan Aßmus 4152f86ba45SStephan Aßmus BRect rect = fText->Frame(); 4162f86ba45SStephan Aßmus rect.InsetBy(-2, -2); 4172f86ba45SStephan Aßmus 4182f86ba45SStephan Aßmus if (be_control_look != NULL) { 4192f86ba45SStephan Aßmus rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); 4202f86ba45SStephan Aßmus uint32 flags = 0; 4212f86ba45SStephan Aßmus if (!enabled) 4222f86ba45SStephan Aßmus flags |= BControlLook::B_DISABLED; 4232f86ba45SStephan Aßmus if (active) 4242f86ba45SStephan Aßmus flags |= BControlLook::B_FOCUSED; 4252f86ba45SStephan Aßmus be_control_look->DrawTextControlBorder(this, rect, updateRect, base, 4262f86ba45SStephan Aßmus flags); 4272f86ba45SStephan Aßmus 4282f86ba45SStephan Aßmus rect = Bounds(); 4292f86ba45SStephan Aßmus rect.right = fDivider - kLabelInputSpacing; 4302f86ba45SStephan Aßmus // rect.right = fText->Frame().left - 2; 4312f86ba45SStephan Aßmus // rect.right -= 3;//be_control_look->DefaultLabelSpacing(); 4322f86ba45SStephan Aßmus be_control_look->DrawLabel(this, Label(), rect, updateRect, 4332f86ba45SStephan Aßmus base, flags, BAlignment(fLabelAlign, B_ALIGN_MIDDLE)); 4342f86ba45SStephan Aßmus 4352f86ba45SStephan Aßmus return; 4362f86ba45SStephan Aßmus } 4372f86ba45SStephan Aßmus 4382f86ba45SStephan Aßmus // outer bevel 4392f86ba45SStephan Aßmus 440c432fbbbSAxel Dörfler rgb_color noTint = ui_color(B_PANEL_BACKGROUND_COLOR); 441c432fbbbSAxel Dörfler rgb_color lighten1 = tint_color(noTint, B_LIGHTEN_1_TINT); 442c432fbbbSAxel Dörfler rgb_color lighten2 = tint_color(noTint, B_LIGHTEN_2_TINT); 443c432fbbbSAxel Dörfler rgb_color lightenMax = tint_color(noTint, B_LIGHTEN_MAX_TINT); 444c432fbbbSAxel Dörfler rgb_color darken1 = tint_color(noTint, B_DARKEN_1_TINT); 445c432fbbbSAxel Dörfler rgb_color darken2 = tint_color(noTint, B_DARKEN_2_TINT); 446c432fbbbSAxel Dörfler rgb_color darken4 = tint_color(noTint, B_DARKEN_4_TINT); 447c432fbbbSAxel Dörfler rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); 4489cb2dbe2SMarc Flerackers 449455d1c46SAxel Dörfler if (enabled) 450455d1c46SAxel Dörfler SetHighColor(darken1); 451455d1c46SAxel Dörfler else 452455d1c46SAxel Dörfler SetHighColor(noTint); 453455d1c46SAxel Dörfler 454455d1c46SAxel Dörfler StrokeLine(rect.LeftBottom(), rect.LeftTop()); 455455d1c46SAxel Dörfler StrokeLine(rect.RightTop()); 456455d1c46SAxel Dörfler 457455d1c46SAxel Dörfler if (enabled) 458455d1c46SAxel Dörfler SetHighColor(lighten2); 459455d1c46SAxel Dörfler else 460455d1c46SAxel Dörfler SetHighColor(lighten1); 461455d1c46SAxel Dörfler 462455d1c46SAxel Dörfler StrokeLine(BPoint(rect.left + 1.0f, rect.bottom), rect.RightBottom()); 463455d1c46SAxel Dörfler StrokeLine(BPoint(rect.right, rect.top + 1.0f), rect.RightBottom()); 464455d1c46SAxel Dörfler 465455d1c46SAxel Dörfler // inner bevel 466455d1c46SAxel Dörfler 467455d1c46SAxel Dörfler rect.InsetBy(1.0f, 1.0f); 4689cb2dbe2SMarc Flerackers 469058691d4SStefano Ceccherini if (active) { 470105644bfSAxel Dörfler SetHighColor(navigationColor); 4719cb2dbe2SMarc Flerackers StrokeRect(rect); 472058691d4SStefano Ceccherini } else { 4739cb2dbe2SMarc Flerackers if (enabled) 4749cb2dbe2SMarc Flerackers SetHighColor(darken4); 4759cb2dbe2SMarc Flerackers else 4769cb2dbe2SMarc Flerackers SetHighColor(darken2); 4779cb2dbe2SMarc Flerackers 4789cb2dbe2SMarc Flerackers StrokeLine(rect.LeftTop(), rect.LeftBottom()); 4799cb2dbe2SMarc Flerackers StrokeLine(rect.LeftTop(), rect.RightTop()); 4809cb2dbe2SMarc Flerackers 481105644bfSAxel Dörfler SetHighColor(noTint); 4829cb2dbe2SMarc Flerackers StrokeLine(BPoint(rect.left + 1.0f, rect.bottom), rect.RightBottom()); 4839cb2dbe2SMarc Flerackers StrokeLine(BPoint(rect.right, rect.top + 1.0f)); 4849cb2dbe2SMarc Flerackers } 4859cb2dbe2SMarc Flerackers 4867a25fcafSStefano Ceccherini // label 4877a25fcafSStefano Ceccherini 488058691d4SStefano Ceccherini if (Label()) { 489349c911eSStephan Aßmus _ValidateLayoutData(); 490349c911eSStephan Aßmus font_height& fontHeight = fLayoutData->font_info; 4919cb2dbe2SMarc Flerackers 492a68292ddSStephan Aßmus float y = Bounds().top + (Bounds().Height() + 1 - fontHeight.ascent 493a68292ddSStephan Aßmus - fontHeight.descent) / 2 + fontHeight.ascent; 49452a38012Sejakowatz float x; 4959cb2dbe2SMarc Flerackers 4967a25fcafSStefano Ceccherini float labelWidth = StringWidth(Label()); 497058691d4SStefano Ceccherini switch (fLabelAlign) { 49852a38012Sejakowatz case B_ALIGN_RIGHT: 499349c911eSStephan Aßmus x = fDivider - labelWidth - kLabelInputSpacing; 50052a38012Sejakowatz break; 50152a38012Sejakowatz 50252a38012Sejakowatz case B_ALIGN_CENTER: 503b8872c02SStephan Aßmus x = fDivider - labelWidth / 2.0; 50452a38012Sejakowatz break; 50552a38012Sejakowatz 50652a38012Sejakowatz default: 507b8872c02SStephan Aßmus x = 0.0; 50852a38012Sejakowatz break; 50952a38012Sejakowatz } 51052a38012Sejakowatz 5112c5a8894SStephan Aßmus BRect labelArea(x, Bounds().top, x + labelWidth, Bounds().bottom); 5127a25fcafSStefano Ceccherini if (x < fDivider && updateRect.Intersects(labelArea)) { 513349c911eSStephan Aßmus labelArea.right = fText->Frame().left - kLabelInputSpacing; 5147a25fcafSStefano Ceccherini 5157a25fcafSStefano Ceccherini BRegion clipRegion(labelArea); 5167a25fcafSStefano Ceccherini ConstrainClippingRegion(&clipRegion); 517c432fbbbSAxel Dörfler SetHighColor(IsEnabled() ? ui_color(B_CONTROL_TEXT_COLOR) 518fa815db3SAxel Dörfler : tint_color(noTint, B_DISABLED_LABEL_TINT)); 51952a38012Sejakowatz DrawString(Label(), BPoint(x, y)); 52052a38012Sejakowatz } 52152a38012Sejakowatz } 5227a25fcafSStefano Ceccherini } 523058691d4SStefano Ceccherini 524058691d4SStefano Ceccherini 525058691d4SStefano Ceccherini void 526058691d4SStefano Ceccherini BTextControl::MouseDown(BPoint where) 52752a38012Sejakowatz { 528058691d4SStefano Ceccherini if (!fText->IsFocus()) { 5299cb2dbe2SMarc Flerackers fText->MakeFocus(true); 53052a38012Sejakowatz } 53152a38012Sejakowatz } 532058691d4SStefano Ceccherini 533058691d4SStefano Ceccherini 534058691d4SStefano Ceccherini void 535058691d4SStefano Ceccherini BTextControl::AttachedToWindow() 53652a38012Sejakowatz { 53752a38012Sejakowatz BControl::AttachedToWindow(); 53852a38012Sejakowatz 53979c35b39SAxel Dörfler _UpdateTextViewColors(IsEnabled()); 5403a3f6c1eSAxel Dörfler fText->MakeEditable(IsEnabled()); 54152a38012Sejakowatz } 542058691d4SStefano Ceccherini 543058691d4SStefano Ceccherini 544058691d4SStefano Ceccherini void 545058691d4SStefano Ceccherini BTextControl::MakeFocus(bool state) 54652a38012Sejakowatz { 5476d8d6cadSStephan Aßmus if (state != fText->IsFocus()) { 54852a38012Sejakowatz fText->MakeFocus(state); 5499cb2dbe2SMarc Flerackers 5509cb2dbe2SMarc Flerackers if (state) 5519cb2dbe2SMarc Flerackers fText->SelectAll(); 55252a38012Sejakowatz } 5536d8d6cadSStephan Aßmus } 554058691d4SStefano Ceccherini 555058691d4SStefano Ceccherini 556058691d4SStefano Ceccherini void 55779c35b39SAxel Dörfler BTextControl::SetEnabled(bool enabled) 55852a38012Sejakowatz { 55979c35b39SAxel Dörfler if (IsEnabled() == enabled) 5609cb2dbe2SMarc Flerackers return; 5619cb2dbe2SMarc Flerackers 562058691d4SStefano Ceccherini if (Window()) { 56379c35b39SAxel Dörfler fText->MakeEditable(enabled); 564c80f8962SJérôme Duval if (enabled) 565c80f8962SJérôme Duval fText->SetFlags(fText->Flags() | B_NAVIGABLE); 566c80f8962SJérôme Duval else 567c80f8962SJérôme Duval fText->SetFlags(fText->Flags() & ~B_NAVIGABLE); 5689cb2dbe2SMarc Flerackers 56979c35b39SAxel Dörfler _UpdateTextViewColors(enabled); 5709cb2dbe2SMarc Flerackers 5719cb2dbe2SMarc Flerackers fText->Invalidate(); 5729cb2dbe2SMarc Flerackers Window()->UpdateIfNeeded(); 5739cb2dbe2SMarc Flerackers } 5749cb2dbe2SMarc Flerackers 57579c35b39SAxel Dörfler BControl::SetEnabled(enabled); 57652a38012Sejakowatz } 577058691d4SStefano Ceccherini 578058691d4SStefano Ceccherini 579058691d4SStefano Ceccherini void 580105644bfSAxel Dörfler BTextControl::GetPreferredSize(float *_width, float *_height) 58152a38012Sejakowatz { 582349c911eSStephan Aßmus CALLED(); 58352a38012Sejakowatz 584349c911eSStephan Aßmus _ValidateLayoutData(); 585105644bfSAxel Dörfler 5861aaf53ecSStephan Aßmus if (_width) { 5871aaf53ecSStephan Aßmus float minWidth = fLayoutData->min.width; 5881aaf53ecSStephan Aßmus if (Label() == NULL && !(Flags() & B_SUPPORTS_LAYOUT)) { 5891aaf53ecSStephan Aßmus // Indeed, only if there is no label! BeOS backwards compatible 5901aaf53ecSStephan Aßmus // behavior: 5911aaf53ecSStephan Aßmus minWidth = max_c(minWidth, Bounds().Width()); 5921aaf53ecSStephan Aßmus } 5931aaf53ecSStephan Aßmus *_width = minWidth; 5941aaf53ecSStephan Aßmus } 595349c911eSStephan Aßmus 596349c911eSStephan Aßmus if (_height) 597349c911eSStephan Aßmus *_height = fLayoutData->min.height; 59852a38012Sejakowatz } 599058691d4SStefano Ceccherini 600058691d4SStefano Ceccherini 601058691d4SStefano Ceccherini void 602058691d4SStefano Ceccherini BTextControl::ResizeToPreferred() 60352a38012Sejakowatz { 604105644bfSAxel Dörfler BView::ResizeToPreferred(); 6051bdc2a52SKarsten Heimrich 6061bdc2a52SKarsten Heimrich fDivider = 0.0; 6071bdc2a52SKarsten Heimrich const char* label = Label(); 6081bdc2a52SKarsten Heimrich if (label) 6091bdc2a52SKarsten Heimrich fDivider = ceil(StringWidth(label)) + 2.0; 6101bdc2a52SKarsten Heimrich 6111bdc2a52SKarsten Heimrich _LayoutTextView(); 61252a38012Sejakowatz } 613058691d4SStefano Ceccherini 614058691d4SStefano Ceccherini 615058691d4SStefano Ceccherini void 616058691d4SStefano Ceccherini BTextControl::SetFlags(uint32 flags) 61752a38012Sejakowatz { 6189cb2dbe2SMarc Flerackers // If the textview is navigable, set it to not navigable if needed 6199cb2dbe2SMarc Flerackers // Else if it is not navigable, set it to navigable if needed 620058691d4SStefano Ceccherini if (fText->Flags() & B_NAVIGABLE) { 6219cb2dbe2SMarc Flerackers if (!(flags & B_NAVIGABLE)) 6229cb2dbe2SMarc Flerackers fText->SetFlags(fText->Flags() & ~B_NAVIGABLE); 623058691d4SStefano Ceccherini 624058691d4SStefano Ceccherini } else { 6259cb2dbe2SMarc Flerackers if (flags & B_NAVIGABLE) 6269cb2dbe2SMarc Flerackers fText->SetFlags(fText->Flags() | B_NAVIGABLE); 6279cb2dbe2SMarc Flerackers } 6289cb2dbe2SMarc Flerackers 629c80f8962SJérôme Duval // Don't make this one navigable 630c80f8962SJérôme Duval flags &= ~B_NAVIGABLE; 631c80f8962SJérôme Duval 63252a38012Sejakowatz BView::SetFlags(flags); 63352a38012Sejakowatz } 634058691d4SStefano Ceccherini 635058691d4SStefano Ceccherini 636058691d4SStefano Ceccherini void 6372a30a9e9SRene Gollent BTextControl::MessageReceived(BMessage *message) 63852a38012Sejakowatz { 6392a30a9e9SRene Gollent if (message->what == B_GET_PROPERTY || message->what == B_SET_PROPERTY) { 6402a30a9e9SRene Gollent BMessage reply(B_REPLY); 6412a30a9e9SRene Gollent bool handled = false; 6424438cb3bSRene Gollent 6432a30a9e9SRene Gollent BMessage specifier; 6442a30a9e9SRene Gollent int32 index; 6452a30a9e9SRene Gollent int32 form; 6462a30a9e9SRene Gollent const char *property; 6472a30a9e9SRene Gollent if (message->GetCurrentSpecifier(&index, &specifier, &form, &property) == B_OK) { 6482a30a9e9SRene Gollent if (strcmp(property, "Value") == 0) { 6492a30a9e9SRene Gollent if (message->what == B_GET_PROPERTY) { 6502a30a9e9SRene Gollent reply.AddString("result", fText->Text()); 6512a30a9e9SRene Gollent handled = true; 6522a30a9e9SRene Gollent } else { 6532a30a9e9SRene Gollent const char *value = NULL; 6542a30a9e9SRene Gollent // B_SET_PROPERTY 6552a30a9e9SRene Gollent if (message->FindString("data", &value) == B_OK) { 6562a30a9e9SRene Gollent fText->SetText(value); 6572a30a9e9SRene Gollent reply.AddInt32("error", B_OK); 6582a30a9e9SRene Gollent handled = true; 65952a38012Sejakowatz } 66052a38012Sejakowatz } 6612a30a9e9SRene Gollent } 6622a30a9e9SRene Gollent } 6632a30a9e9SRene Gollent 6642a30a9e9SRene Gollent if (handled) { 6652a30a9e9SRene Gollent message->SendReply(&reply); 6662a30a9e9SRene Gollent return; 6672a30a9e9SRene Gollent } 6682a30a9e9SRene Gollent } 6692a30a9e9SRene Gollent 6702a30a9e9SRene Gollent BControl::MessageReceived(message); 6712a30a9e9SRene Gollent } 672058691d4SStefano Ceccherini 673058691d4SStefano Ceccherini 674058691d4SStefano Ceccherini BHandler * 6752a30a9e9SRene Gollent BTextControl::ResolveSpecifier(BMessage *message, int32 index, 6762a30a9e9SRene Gollent BMessage *specifier, int32 what, 67752a38012Sejakowatz const char *property) 67852a38012Sejakowatz { 6792a30a9e9SRene Gollent BPropertyInfo propInfo(sPropertyList); 6809cb2dbe2SMarc Flerackers 6812a30a9e9SRene Gollent if (propInfo.FindMatch(message, 0, specifier, what, property) >= B_OK) 6822a30a9e9SRene Gollent return this; 6832a30a9e9SRene Gollent 6849cb2dbe2SMarc Flerackers return BControl::ResolveSpecifier(message, index, specifier, what, 6859cb2dbe2SMarc Flerackers property); 68652a38012Sejakowatz } 687058691d4SStefano Ceccherini 688058691d4SStefano Ceccherini 689058691d4SStefano Ceccherini status_t 690058691d4SStefano Ceccherini BTextControl::GetSupportedSuites(BMessage *data) 69152a38012Sejakowatz { 6929cb2dbe2SMarc Flerackers return BControl::GetSupportedSuites(data); 69352a38012Sejakowatz } 694058691d4SStefano Ceccherini 695058691d4SStefano Ceccherini 696058691d4SStefano Ceccherini void 697058691d4SStefano Ceccherini BTextControl::MouseUp(BPoint pt) 69852a38012Sejakowatz { 69952a38012Sejakowatz BControl::MouseUp(pt); 70052a38012Sejakowatz } 701058691d4SStefano Ceccherini 702058691d4SStefano Ceccherini 703058691d4SStefano Ceccherini void 704058691d4SStefano Ceccherini BTextControl::MouseMoved(BPoint pt, uint32 code, const BMessage *msg) 70552a38012Sejakowatz { 70652a38012Sejakowatz BControl::MouseMoved(pt, code, msg); 70752a38012Sejakowatz } 708058691d4SStefano Ceccherini 709058691d4SStefano Ceccherini 710058691d4SStefano Ceccherini void 711058691d4SStefano Ceccherini BTextControl::DetachedFromWindow() 71252a38012Sejakowatz { 71352a38012Sejakowatz BControl::DetachedFromWindow(); 71452a38012Sejakowatz } 715058691d4SStefano Ceccherini 716058691d4SStefano Ceccherini 717058691d4SStefano Ceccherini void 718058691d4SStefano Ceccherini BTextControl::AllAttached() 71952a38012Sejakowatz { 72052a38012Sejakowatz BControl::AllAttached(); 72152a38012Sejakowatz } 722058691d4SStefano Ceccherini 723058691d4SStefano Ceccherini 724058691d4SStefano Ceccherini void 725058691d4SStefano Ceccherini BTextControl::AllDetached() 72652a38012Sejakowatz { 72752a38012Sejakowatz BControl::AllDetached(); 72852a38012Sejakowatz } 729058691d4SStefano Ceccherini 730058691d4SStefano Ceccherini 731058691d4SStefano Ceccherini void 732058691d4SStefano Ceccherini BTextControl::FrameMoved(BPoint newPosition) 73352a38012Sejakowatz { 73452a38012Sejakowatz BControl::FrameMoved(newPosition); 73552a38012Sejakowatz } 736058691d4SStefano Ceccherini 737058691d4SStefano Ceccherini 738058691d4SStefano Ceccherini void 739ffe72abdSAxel Dörfler BTextControl::FrameResized(float width, float height) 74052a38012Sejakowatz { 74193ba577cSStephan Aßmus CALLED(); 74293ba577cSStephan Aßmus 743ffe72abdSAxel Dörfler BControl::FrameResized(width, height); 744ffe72abdSAxel Dörfler 745349c911eSStephan Aßmus // TODO: this causes flickering still... 746349c911eSStephan Aßmus 747ffe72abdSAxel Dörfler // changes in width 748ffe72abdSAxel Dörfler 749ffe72abdSAxel Dörfler BRect bounds = Bounds(); 750ffe72abdSAxel Dörfler 751349c911eSStephan Aßmus if (bounds.Width() > fLayoutData->previous_width) { 752ffe72abdSAxel Dörfler // invalidate the region between the old and the new right border 753ffe72abdSAxel Dörfler BRect rect = bounds; 754349c911eSStephan Aßmus rect.left += fLayoutData->previous_width - kFrameMargin; 755ffe72abdSAxel Dörfler rect.right--; 756ffe72abdSAxel Dörfler Invalidate(rect); 757349c911eSStephan Aßmus } else if (bounds.Width() < fLayoutData->previous_width) { 758ffe72abdSAxel Dörfler // invalidate the region of the new right border 759ffe72abdSAxel Dörfler BRect rect = bounds; 760349c911eSStephan Aßmus rect.left = rect.right - kFrameMargin; 761ffe72abdSAxel Dörfler Invalidate(rect); 762ffe72abdSAxel Dörfler } 763ffe72abdSAxel Dörfler 764ffe72abdSAxel Dörfler // changes in height 765ffe72abdSAxel Dörfler 766349c911eSStephan Aßmus if (bounds.Height() > fLayoutData->previous_height) { 767ffe72abdSAxel Dörfler // invalidate the region between the old and the new bottom border 768ffe72abdSAxel Dörfler BRect rect = bounds; 769349c911eSStephan Aßmus rect.top += fLayoutData->previous_height - kFrameMargin; 770ffe72abdSAxel Dörfler rect.bottom--; 771ffe72abdSAxel Dörfler Invalidate(rect); 772349c911eSStephan Aßmus // invalidate label area 773349c911eSStephan Aßmus rect = bounds; 774349c911eSStephan Aßmus rect.right = fDivider; 775349c911eSStephan Aßmus Invalidate(rect); 776349c911eSStephan Aßmus } else if (bounds.Height() < fLayoutData->previous_height) { 777ffe72abdSAxel Dörfler // invalidate the region of the new bottom border 778ffe72abdSAxel Dörfler BRect rect = bounds; 779349c911eSStephan Aßmus rect.top = rect.bottom - kFrameMargin; 780349c911eSStephan Aßmus Invalidate(rect); 781349c911eSStephan Aßmus // invalidate label area 782349c911eSStephan Aßmus rect = bounds; 783349c911eSStephan Aßmus rect.right = fDivider; 784ffe72abdSAxel Dörfler Invalidate(rect); 785ffe72abdSAxel Dörfler } 786ffe72abdSAxel Dörfler 787349c911eSStephan Aßmus fLayoutData->previous_width = bounds.Width(); 788349c911eSStephan Aßmus fLayoutData->previous_height = bounds.Height(); 78993ba577cSStephan Aßmus 79093ba577cSStephan Aßmus TRACE("width: %.2f, height: %.2f\n", bounds.Width(), bounds.Height()); 79152a38012Sejakowatz } 792058691d4SStefano Ceccherini 793058691d4SStefano Ceccherini 794058691d4SStefano Ceccherini void 795058691d4SStefano Ceccherini BTextControl::WindowActivated(bool active) 79652a38012Sejakowatz { 7976d8d6cadSStephan Aßmus if (fText->IsFocus()) { 798dde10e45SStephan Aßmus // invalidate to remove/show focus indication 7992c5a8894SStephan Aßmus BRect rect = fText->Frame(); 8002c5a8894SStephan Aßmus rect.InsetBy(-1, -1); 8016d8d6cadSStephan Aßmus Invalidate(rect); 802dde10e45SStephan Aßmus 803dde10e45SStephan Aßmus // help out embedded text view which doesn't 804dde10e45SStephan Aßmus // get notified of this 805dde10e45SStephan Aßmus fText->Invalidate(); 8066d8d6cadSStephan Aßmus } 80752a38012Sejakowatz } 808058691d4SStefano Ceccherini 809058691d4SStefano Ceccherini 810349c911eSStephan Aßmus BSize 811349c911eSStephan Aßmus BTextControl::MinSize() 81252a38012Sejakowatz { 813349c911eSStephan Aßmus CALLED(); 814349c911eSStephan Aßmus 815349c911eSStephan Aßmus _ValidateLayoutData(); 816349c911eSStephan Aßmus return BLayoutUtils::ComposeSize(ExplicitMinSize(), fLayoutData->min); 817349c911eSStephan Aßmus } 818349c911eSStephan Aßmus 819349c911eSStephan Aßmus 820349c911eSStephan Aßmus BSize 821349c911eSStephan Aßmus BTextControl::MaxSize() 822349c911eSStephan Aßmus { 823349c911eSStephan Aßmus CALLED(); 824349c911eSStephan Aßmus 825349c911eSStephan Aßmus _ValidateLayoutData(); 826349c911eSStephan Aßmus 827349c911eSStephan Aßmus BSize max = fLayoutData->min; 828349c911eSStephan Aßmus max.width = B_SIZE_UNLIMITED; 829349c911eSStephan Aßmus 830349c911eSStephan Aßmus return BLayoutUtils::ComposeSize(ExplicitMaxSize(), max); 831349c911eSStephan Aßmus } 832349c911eSStephan Aßmus 833349c911eSStephan Aßmus 834349c911eSStephan Aßmus BSize 835349c911eSStephan Aßmus BTextControl::PreferredSize() 836349c911eSStephan Aßmus { 837349c911eSStephan Aßmus CALLED(); 838349c911eSStephan Aßmus 839349c911eSStephan Aßmus _ValidateLayoutData(); 840349c911eSStephan Aßmus return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), fLayoutData->min); 841349c911eSStephan Aßmus } 842349c911eSStephan Aßmus 843349c911eSStephan Aßmus 844349c911eSStephan Aßmus void 845349c911eSStephan Aßmus BTextControl::InvalidateLayout(bool descendants) 846349c911eSStephan Aßmus { 847349c911eSStephan Aßmus CALLED(); 848349c911eSStephan Aßmus 849349c911eSStephan Aßmus fLayoutData->valid = false; 850349c911eSStephan Aßmus 851349c911eSStephan Aßmus BView::InvalidateLayout(descendants); 85252a38012Sejakowatz } 853058691d4SStefano Ceccherini 854058691d4SStefano Ceccherini 8559ecf9d1cSIngo Weinhold BLayoutItem* 8569ecf9d1cSIngo Weinhold BTextControl::CreateLabelLayoutItem() 8579ecf9d1cSIngo Weinhold { 858349c911eSStephan Aßmus if (!fLayoutData->label_layout_item) 859349c911eSStephan Aßmus fLayoutData->label_layout_item = new LabelLayoutItem(this); 860349c911eSStephan Aßmus return fLayoutData->label_layout_item; 8619ecf9d1cSIngo Weinhold } 8629ecf9d1cSIngo Weinhold 8639ecf9d1cSIngo Weinhold 8649ecf9d1cSIngo Weinhold BLayoutItem* 8659ecf9d1cSIngo Weinhold BTextControl::CreateTextViewLayoutItem() 8669ecf9d1cSIngo Weinhold { 867349c911eSStephan Aßmus if (!fLayoutData->text_view_layout_item) 868349c911eSStephan Aßmus fLayoutData->text_view_layout_item = new TextViewLayoutItem(this); 869349c911eSStephan Aßmus return fLayoutData->text_view_layout_item; 870349c911eSStephan Aßmus } 871349c911eSStephan Aßmus 872349c911eSStephan Aßmus 873349c911eSStephan Aßmus void 874349c911eSStephan Aßmus BTextControl::DoLayout() 875349c911eSStephan Aßmus { 876349c911eSStephan Aßmus // Bail out, if we shan't do layout. 877349c911eSStephan Aßmus if (!(Flags() & B_SUPPORTS_LAYOUT)) 878349c911eSStephan Aßmus return; 879349c911eSStephan Aßmus 880349c911eSStephan Aßmus CALLED(); 881349c911eSStephan Aßmus 882349c911eSStephan Aßmus // If the user set a layout, we let the base class version call its 883349c911eSStephan Aßmus // hook. 884349c911eSStephan Aßmus if (GetLayout()) { 885349c911eSStephan Aßmus BView::DoLayout(); 886349c911eSStephan Aßmus return; 887349c911eSStephan Aßmus } 888349c911eSStephan Aßmus 889349c911eSStephan Aßmus _ValidateLayoutData(); 890349c911eSStephan Aßmus 891349c911eSStephan Aßmus // validate current size 892349c911eSStephan Aßmus BSize size(Bounds().Size()); 893349c911eSStephan Aßmus if (size.width < fLayoutData->min.width) 894349c911eSStephan Aßmus size.width = fLayoutData->min.width; 895349c911eSStephan Aßmus if (size.height < fLayoutData->min.height) 896349c911eSStephan Aßmus size.height = fLayoutData->min.height; 897349c911eSStephan Aßmus 898349c911eSStephan Aßmus // divider 899349c911eSStephan Aßmus float divider = 0; 900349c911eSStephan Aßmus if (fLayoutData->label_layout_item && fLayoutData->text_view_layout_item) { 901349c911eSStephan Aßmus // We have layout items. They define the divider location. 902349c911eSStephan Aßmus divider = fLayoutData->text_view_layout_item->Frame().left 903349c911eSStephan Aßmus - fLayoutData->label_layout_item->Frame().left; 904349c911eSStephan Aßmus } else { 905349c911eSStephan Aßmus if (fLayoutData->label_width > 0) 906349c911eSStephan Aßmus divider = fLayoutData->label_width + 5; 907349c911eSStephan Aßmus } 908349c911eSStephan Aßmus 909349c911eSStephan Aßmus // text view 910349c911eSStephan Aßmus BRect dirty(fText->Frame()); 91184b7e122SStephan Aßmus BRect textFrame(divider + kFrameMargin, kFrameMargin, 91284b7e122SStephan Aßmus size.width - kFrameMargin, size.height - kFrameMargin); 913349c911eSStephan Aßmus 914349c911eSStephan Aßmus // place the text view and set the divider 915349c911eSStephan Aßmus BLayoutUtils::AlignInFrame(fText, textFrame); 916349c911eSStephan Aßmus 917349c911eSStephan Aßmus fDivider = divider; 918349c911eSStephan Aßmus 919349c911eSStephan Aßmus // invalidate dirty region 920349c911eSStephan Aßmus dirty = dirty | fText->Frame(); 921349c911eSStephan Aßmus dirty.InsetBy(-kFrameMargin, -kFrameMargin); 922349c911eSStephan Aßmus 923349c911eSStephan Aßmus Invalidate(dirty); 924349c911eSStephan Aßmus } 925349c911eSStephan Aßmus 926349c911eSStephan Aßmus 927349c911eSStephan Aßmus // #pragma mark - 928349c911eSStephan Aßmus 929349c911eSStephan Aßmus 930349c911eSStephan Aßmus status_t 93139fbf550SOliver Tappe BTextControl::Perform(perform_code code, void* _data) 932349c911eSStephan Aßmus { 93339fbf550SOliver Tappe switch (code) { 93439fbf550SOliver Tappe case PERFORM_CODE_MIN_SIZE: 93539fbf550SOliver Tappe ((perform_data_min_size*)_data)->return_value 93639fbf550SOliver Tappe = BTextControl::MinSize(); 93739fbf550SOliver Tappe return B_OK; 93839fbf550SOliver Tappe case PERFORM_CODE_MAX_SIZE: 93939fbf550SOliver Tappe ((perform_data_max_size*)_data)->return_value 94039fbf550SOliver Tappe = BTextControl::MaxSize(); 94139fbf550SOliver Tappe return B_OK; 94239fbf550SOliver Tappe case PERFORM_CODE_PREFERRED_SIZE: 94339fbf550SOliver Tappe ((perform_data_preferred_size*)_data)->return_value 94439fbf550SOliver Tappe = BTextControl::PreferredSize(); 94539fbf550SOliver Tappe return B_OK; 94639fbf550SOliver Tappe case PERFORM_CODE_LAYOUT_ALIGNMENT: 94739fbf550SOliver Tappe ((perform_data_layout_alignment*)_data)->return_value 94839fbf550SOliver Tappe = BTextControl::LayoutAlignment(); 94939fbf550SOliver Tappe return B_OK; 95039fbf550SOliver Tappe case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH: 95139fbf550SOliver Tappe ((perform_data_has_height_for_width*)_data)->return_value 95239fbf550SOliver Tappe = BTextControl::HasHeightForWidth(); 95339fbf550SOliver Tappe return B_OK; 95439fbf550SOliver Tappe case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH: 95539fbf550SOliver Tappe { 95639fbf550SOliver Tappe perform_data_get_height_for_width* data 95739fbf550SOliver Tappe = (perform_data_get_height_for_width*)_data; 95839fbf550SOliver Tappe BTextControl::GetHeightForWidth(data->width, &data->min, &data->max, 95939fbf550SOliver Tappe &data->preferred); 96039fbf550SOliver Tappe return B_OK; 96139fbf550SOliver Tappe } 96239fbf550SOliver Tappe case PERFORM_CODE_SET_LAYOUT: 96339fbf550SOliver Tappe { 96439fbf550SOliver Tappe perform_data_set_layout* data = (perform_data_set_layout*)_data; 96539fbf550SOliver Tappe BTextControl::SetLayout(data->layout); 96639fbf550SOliver Tappe return B_OK; 96739fbf550SOliver Tappe } 968*eee4243dSAlex Wilson case PERFORM_CODE_LAYOUT_INVALIDATED: 96939fbf550SOliver Tappe { 970*eee4243dSAlex Wilson perform_data_layout_invalidated* data 971*eee4243dSAlex Wilson = (perform_data_layout_invalidated*)_data; 972*eee4243dSAlex Wilson BTextControl::LayoutInvalidated(data->descendants); 97339fbf550SOliver Tappe return B_OK; 97439fbf550SOliver Tappe } 97539fbf550SOliver Tappe case PERFORM_CODE_DO_LAYOUT: 97639fbf550SOliver Tappe { 97739fbf550SOliver Tappe BTextControl::DoLayout(); 97839fbf550SOliver Tappe return B_OK; 97939fbf550SOliver Tappe } 9805c47e35eSAlex Wilson case PERFORM_CODE_ALL_UNARCHIVED: 9815c47e35eSAlex Wilson { 9825c47e35eSAlex Wilson perform_data_all_unarchived* data 9835c47e35eSAlex Wilson = (perform_data_all_unarchived*)_data; 9845c47e35eSAlex Wilson 9855c47e35eSAlex Wilson data->return_value = BTextControl::AllUnarchived(data->archive); 9865c47e35eSAlex Wilson return B_OK; 9875c47e35eSAlex Wilson } 9885c47e35eSAlex Wilson case PERFORM_CODE_ALL_ARCHIVED: 9895c47e35eSAlex Wilson { 9905c47e35eSAlex Wilson perform_data_all_archived* data 9915c47e35eSAlex Wilson = (perform_data_all_archived*)_data; 9925c47e35eSAlex Wilson 9935c47e35eSAlex Wilson data->return_value = BTextControl::AllArchived(data->archive); 9945c47e35eSAlex Wilson return B_OK; 9955c47e35eSAlex Wilson } 99639fbf550SOliver Tappe } 99739fbf550SOliver Tappe 99839fbf550SOliver Tappe return BControl::Perform(code, _data); 9999ecf9d1cSIngo Weinhold } 10009ecf9d1cSIngo Weinhold 10019ecf9d1cSIngo Weinhold 10029cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl1() {} 10039cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl2() {} 10049cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl3() {} 10059cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl4() {} 1006058691d4SStefano Ceccherini 1007058691d4SStefano Ceccherini 1008058691d4SStefano Ceccherini BTextControl & 1009058691d4SStefano Ceccherini BTextControl::operator=(const BTextControl&) 101052a38012Sejakowatz { 101152a38012Sejakowatz return *this; 101252a38012Sejakowatz } 1013058691d4SStefano Ceccherini 1014058691d4SStefano Ceccherini 1015058691d4SStefano Ceccherini void 101679c35b39SAxel Dörfler BTextControl::_UpdateTextViewColors(bool enabled) 10173a3f6c1eSAxel Dörfler { 10183a3f6c1eSAxel Dörfler rgb_color textColor; 1019aae7000dSAxel Dörfler rgb_color color; 10203a3f6c1eSAxel Dörfler BFont font; 10213a3f6c1eSAxel Dörfler 1022aae7000dSAxel Dörfler fText->GetFontAndColor(0, &font); 10233a3f6c1eSAxel Dörfler 10243a3f6c1eSAxel Dörfler if (enabled) 1025aae7000dSAxel Dörfler textColor = ui_color(B_DOCUMENT_TEXT_COLOR); 102612aefeb4SAxel Dörfler else { 102712aefeb4SAxel Dörfler textColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 102812aefeb4SAxel Dörfler B_DISABLED_LABEL_TINT); 102912aefeb4SAxel Dörfler } 10303a3f6c1eSAxel Dörfler 10313a3f6c1eSAxel Dörfler fText->SetFontAndColor(&font, B_FONT_ALL, &textColor); 10323a3f6c1eSAxel Dörfler 10333a3f6c1eSAxel Dörfler if (enabled) { 1034aae7000dSAxel Dörfler color = ui_color(B_DOCUMENT_BACKGROUND_COLOR); 10353a3f6c1eSAxel Dörfler } else { 10363a3f6c1eSAxel Dörfler color = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 10373a3f6c1eSAxel Dörfler B_LIGHTEN_2_TINT); 10383a3f6c1eSAxel Dörfler } 10393a3f6c1eSAxel Dörfler 10403a3f6c1eSAxel Dörfler fText->SetViewColor(color); 10413a3f6c1eSAxel Dörfler fText->SetLowColor(color); 10423a3f6c1eSAxel Dörfler } 10433a3f6c1eSAxel Dörfler 10443a3f6c1eSAxel Dörfler 10453a3f6c1eSAxel Dörfler void 1046ffe72abdSAxel Dörfler BTextControl::_CommitValue() 10479cb2dbe2SMarc Flerackers { 10489cb2dbe2SMarc Flerackers } 1049058691d4SStefano Ceccherini 1050058691d4SStefano Ceccherini 1051058691d4SStefano Ceccherini void 10525c47e35eSAlex Wilson BTextControl::_InitData(const char* label, const BMessage* archive) 10539cb2dbe2SMarc Flerackers { 10549cb2dbe2SMarc Flerackers BRect bounds(Bounds()); 10559cb2dbe2SMarc Flerackers 10569cb2dbe2SMarc Flerackers fText = NULL; 10579cb2dbe2SMarc Flerackers fModificationMessage = NULL; 10589cb2dbe2SMarc Flerackers fLabelAlign = B_ALIGN_LEFT; 10599cb2dbe2SMarc Flerackers fDivider = 0.0f; 1060349c911eSStephan Aßmus fLayoutData = new LayoutData(bounds.Width(), bounds.Height()); 10619cb2dbe2SMarc Flerackers 10629cb2dbe2SMarc Flerackers int32 flags = 0; 10639cb2dbe2SMarc Flerackers 1064918a22d9SDarkWyrm BFont font(be_plain_font); 10659cb2dbe2SMarc Flerackers 1066ffe72abdSAxel Dörfler if (!archive || !archive->HasString("_fname")) 1067058691d4SStefano Ceccherini flags |= B_FONT_FAMILY_AND_STYLE; 10689cb2dbe2SMarc Flerackers 1069ffe72abdSAxel Dörfler if (!archive || !archive->HasFloat("_fflt")) 1070058691d4SStefano Ceccherini flags |= B_FONT_SIZE; 10719cb2dbe2SMarc Flerackers 10729cb2dbe2SMarc Flerackers if (flags != 0) 10739cb2dbe2SMarc Flerackers SetFont(&font, flags); 10749cb2dbe2SMarc Flerackers 10759cb2dbe2SMarc Flerackers if (label) 10762e6a5805SStephan Aßmus fDivider = floorf(bounds.Width() / 2.0f); 10779cb2dbe2SMarc Flerackers 10785c47e35eSAlex Wilson } 10795c47e35eSAlex Wilson 10805c47e35eSAlex Wilson 10815c47e35eSAlex Wilson void 10825c47e35eSAlex Wilson BTextControl::_InitText(const char* initialText, const BMessage* archive) 10835c47e35eSAlex Wilson { 1084ffe72abdSAxel Dörfler if (archive) 1085b8872c02SStephan Aßmus fText = static_cast<BPrivate::_BTextInput_*>(FindView("_input_")); 1086991c062fSAxel Dörfler 1087991c062fSAxel Dörfler if (fText == NULL) { 10885c47e35eSAlex Wilson BRect bounds(Bounds()); 1089ee2a3473SStephan Aßmus BRect frame(fDivider, bounds.top, bounds.right, bounds.bottom); 1090105644bfSAxel Dörfler // we are stroking the frame around the text view, which 10912e6a5805SStephan Aßmus // is 2 pixels wide 1092349c911eSStephan Aßmus frame.InsetBy(kFrameMargin, kFrameMargin); 1093111b4fbcSStefano Ceccherini BRect textRect(frame.OffsetToCopy(B_ORIGIN)); 10949cb2dbe2SMarc Flerackers 1095b8872c02SStephan Aßmus fText = new BPrivate::_BTextInput_(frame, textRect, 10965c47e35eSAlex Wilson B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS 10975c47e35eSAlex Wilson | (Flags() & B_NAVIGABLE)); 10989cb2dbe2SMarc Flerackers AddChild(fText); 10999cb2dbe2SMarc Flerackers 1100455d1c46SAxel Dörfler SetText(initialText); 11019cb2dbe2SMarc Flerackers fText->SetAlignment(B_ALIGN_LEFT); 11029cb2dbe2SMarc Flerackers fText->AlignTextRect(); 11039cb2dbe2SMarc Flerackers } 11045c47e35eSAlex Wilson 11055c47e35eSAlex Wilson // Although this is not strictly initializing the text view, 11065c47e35eSAlex Wilson // it cannot be done while fText is NULL, so it resides here. 11075c47e35eSAlex Wilson if (archive) { 11085c47e35eSAlex Wilson int32 labelAlignment = B_ALIGN_LEFT; 11095c47e35eSAlex Wilson int32 textAlignment = B_ALIGN_LEFT; 11105c47e35eSAlex Wilson 11115c47e35eSAlex Wilson status_t err = B_OK; 11125c47e35eSAlex Wilson if (archive->HasInt32("_a_label")) 11135c47e35eSAlex Wilson err = archive->FindInt32("_a_label", &labelAlignment); 11145c47e35eSAlex Wilson 11155c47e35eSAlex Wilson if (err == B_OK && archive->HasInt32("_a_text")) 11165c47e35eSAlex Wilson err = archive->FindInt32("_a_text", &textAlignment); 11175c47e35eSAlex Wilson 11185c47e35eSAlex Wilson SetAlignment((alignment)labelAlignment, (alignment)textAlignment); 11195c47e35eSAlex Wilson } 112050960935SClemens Zeidler 112150960935SClemens Zeidler uint32 navigableFlags = Flags() & B_NAVIGABLE; 112250960935SClemens Zeidler if (navigableFlags != 0) 112350960935SClemens Zeidler BView::SetFlags(Flags() & ~B_NAVIGABLE); 11249cb2dbe2SMarc Flerackers } 11259ecf9d1cSIngo Weinhold 11269ecf9d1cSIngo Weinhold 11279ecf9d1cSIngo Weinhold void 11289ecf9d1cSIngo Weinhold BTextControl::_ValidateLayout() 11299ecf9d1cSIngo Weinhold { 113093ba577cSStephan Aßmus CALLED(); 113193ba577cSStephan Aßmus 1132349c911eSStephan Aßmus _ValidateLayoutData(); 11339ecf9d1cSIngo Weinhold 1134349c911eSStephan Aßmus ResizeTo(Bounds().Width(), fLayoutData->min.height); 11359ecf9d1cSIngo Weinhold 1136a431f44bSStephan Aßmus _LayoutTextView(); 11379ecf9d1cSIngo Weinhold } 11389ecf9d1cSIngo Weinhold 11399ecf9d1cSIngo Weinhold 11409ecf9d1cSIngo Weinhold void 1141a431f44bSStephan Aßmus BTextControl::_LayoutTextView() 1142a431f44bSStephan Aßmus { 114393ba577cSStephan Aßmus CALLED(); 114493ba577cSStephan Aßmus 1145a431f44bSStephan Aßmus BRect frame = Bounds(); 1146a431f44bSStephan Aßmus frame.left = fDivider; 1147a431f44bSStephan Aßmus // we are stroking the frame around the text view, which 1148a431f44bSStephan Aßmus // is 2 pixels wide 114984b7e122SStephan Aßmus frame.InsetBy(kFrameMargin, kFrameMargin); 1150a431f44bSStephan Aßmus fText->MoveTo(frame.left, frame.top); 1151a431f44bSStephan Aßmus fText->ResizeTo(frame.Width(), frame.Height()); 1152b8872c02SStephan Aßmus fText->AlignTextRect(); 115393ba577cSStephan Aßmus 115493ba577cSStephan Aßmus TRACE("width: %.2f, height: %.2f\n", Frame().Width(), Frame().Height()); 115593ba577cSStephan Aßmus TRACE("fDivider: %.2f\n", fDivider); 115693ba577cSStephan Aßmus TRACE("fText frame: (%.2f, %.2f, %.2f, %.2f)\n", 115793ba577cSStephan Aßmus frame.left, frame.top, frame.right, frame.bottom); 1158a431f44bSStephan Aßmus } 1159a431f44bSStephan Aßmus 1160a431f44bSStephan Aßmus 1161a431f44bSStephan Aßmus void 11629ecf9d1cSIngo Weinhold BTextControl::_UpdateFrame() 11639ecf9d1cSIngo Weinhold { 1164349c911eSStephan Aßmus CALLED(); 1165349c911eSStephan Aßmus 1166349c911eSStephan Aßmus if (fLayoutData->label_layout_item && fLayoutData->text_view_layout_item) { 1167349c911eSStephan Aßmus BRect labelFrame = fLayoutData->label_layout_item->Frame(); 1168349c911eSStephan Aßmus BRect textFrame = fLayoutData->text_view_layout_item->Frame(); 1169349c911eSStephan Aßmus 1170349c911eSStephan Aßmus // update divider 1171349c911eSStephan Aßmus fDivider = textFrame.left - labelFrame.left; 1172349c911eSStephan Aßmus 11739ecf9d1cSIngo Weinhold MoveTo(labelFrame.left, labelFrame.top); 1174349c911eSStephan Aßmus BSize oldSize = Bounds().Size(); 11759ecf9d1cSIngo Weinhold ResizeTo(textFrame.left + textFrame.Width() - labelFrame.left, 11769ecf9d1cSIngo Weinhold textFrame.top + textFrame.Height() - labelFrame.top); 1177349c911eSStephan Aßmus BSize newSize = Bounds().Size(); 1178349c911eSStephan Aßmus 1179349c911eSStephan Aßmus // If the size changes, ResizeTo() will trigger a relayout, otherwise 1180349c911eSStephan Aßmus // we need to do that explicitly. 1181349c911eSStephan Aßmus if (newSize != oldSize) 1182349c911eSStephan Aßmus Relayout(); 11839ecf9d1cSIngo Weinhold } 11849ecf9d1cSIngo Weinhold } 11859ecf9d1cSIngo Weinhold 11869ecf9d1cSIngo Weinhold 1187349c911eSStephan Aßmus void 1188349c911eSStephan Aßmus BTextControl::_ValidateLayoutData() 1189349c911eSStephan Aßmus { 1190349c911eSStephan Aßmus CALLED(); 1191349c911eSStephan Aßmus 1192349c911eSStephan Aßmus if (fLayoutData->valid) 1193349c911eSStephan Aßmus return; 1194349c911eSStephan Aßmus 1195349c911eSStephan Aßmus // cache font height 1196349c911eSStephan Aßmus font_height& fh = fLayoutData->font_info; 1197349c911eSStephan Aßmus GetFontHeight(&fh); 1198349c911eSStephan Aßmus 1199349c911eSStephan Aßmus if (Label() != NULL) { 1200349c911eSStephan Aßmus fLayoutData->label_width = ceilf(StringWidth(Label())); 1201349c911eSStephan Aßmus fLayoutData->label_height = ceilf(fh.ascent) + ceilf(fh.descent); 1202349c911eSStephan Aßmus } else { 1203349c911eSStephan Aßmus fLayoutData->label_width = 0; 1204349c911eSStephan Aßmus fLayoutData->label_height = 0; 1205349c911eSStephan Aßmus } 1206349c911eSStephan Aßmus 1207349c911eSStephan Aßmus // compute the minimal divider 1208349c911eSStephan Aßmus float divider = 0; 1209349c911eSStephan Aßmus if (fLayoutData->label_width > 0) 1210349c911eSStephan Aßmus divider = fLayoutData->label_width + 5; 1211349c911eSStephan Aßmus 1212349c911eSStephan Aßmus // If we shan't do real layout, we let the current divider take influence. 1213349c911eSStephan Aßmus if (!(Flags() & B_SUPPORTS_LAYOUT)) 1214349c911eSStephan Aßmus divider = max_c(divider, fDivider); 1215349c911eSStephan Aßmus 1216349c911eSStephan Aßmus // get the minimal (== preferred) text view size 1217349c911eSStephan Aßmus fLayoutData->text_view_min = fText->MinSize(); 1218349c911eSStephan Aßmus 1219349c911eSStephan Aßmus TRACE("text view min width: %.2f\n", fLayoutData->text_view_min.width); 1220349c911eSStephan Aßmus 1221349c911eSStephan Aßmus // compute our minimal (== preferred) size 1222349c911eSStephan Aßmus BSize min(fLayoutData->text_view_min); 1223349c911eSStephan Aßmus min.width += 2 * kFrameMargin; 1224349c911eSStephan Aßmus min.height += 2 * kFrameMargin; 1225349c911eSStephan Aßmus 1226349c911eSStephan Aßmus if (divider > 0) 1227349c911eSStephan Aßmus min.width += divider; 1228349c911eSStephan Aßmus if (fLayoutData->label_height > min.height) 1229349c911eSStephan Aßmus min.height = fLayoutData->label_height; 1230349c911eSStephan Aßmus 1231349c911eSStephan Aßmus fLayoutData->min = min; 1232349c911eSStephan Aßmus 1233349c911eSStephan Aßmus fLayoutData->valid = true; 1234c944d11fSStephan Aßmus ResetLayoutInvalidation(); 1235349c911eSStephan Aßmus 1236349c911eSStephan Aßmus TRACE("width: %.2f, height: %.2f\n", min.width, min.height); 1237349c911eSStephan Aßmus } 1238349c911eSStephan Aßmus 1239349c911eSStephan Aßmus 12409ecf9d1cSIngo Weinhold // #pragma mark - 12419ecf9d1cSIngo Weinhold 12429ecf9d1cSIngo Weinhold 12439ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::LabelLayoutItem(BTextControl* parent) 12445c47e35eSAlex Wilson : 12455c47e35eSAlex Wilson fParent(parent), 12469ecf9d1cSIngo Weinhold fFrame() 12479ecf9d1cSIngo Weinhold { 12489ecf9d1cSIngo Weinhold } 12499ecf9d1cSIngo Weinhold 12509ecf9d1cSIngo Weinhold 12515c47e35eSAlex Wilson BTextControl::LabelLayoutItem::LabelLayoutItem(BMessage* from) 12525c47e35eSAlex Wilson : 12535c47e35eSAlex Wilson BAbstractLayoutItem(from), 12545c47e35eSAlex Wilson fParent(NULL), 12555c47e35eSAlex Wilson fFrame() 12565c47e35eSAlex Wilson { 12575c47e35eSAlex Wilson from->FindRect(kFrameField, &fFrame); 12585c47e35eSAlex Wilson } 12595c47e35eSAlex Wilson 12605c47e35eSAlex Wilson 12619ecf9d1cSIngo Weinhold bool 12629ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::IsVisible() 12639ecf9d1cSIngo Weinhold { 12649ecf9d1cSIngo Weinhold return !fParent->IsHidden(fParent); 12659ecf9d1cSIngo Weinhold } 12669ecf9d1cSIngo Weinhold 12679ecf9d1cSIngo Weinhold 12689ecf9d1cSIngo Weinhold void 12699ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::SetVisible(bool visible) 12709ecf9d1cSIngo Weinhold { 12719ecf9d1cSIngo Weinhold // not allowed 12729ecf9d1cSIngo Weinhold } 12739ecf9d1cSIngo Weinhold 12749ecf9d1cSIngo Weinhold 12759ecf9d1cSIngo Weinhold BRect 12769ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::Frame() 12779ecf9d1cSIngo Weinhold { 12789ecf9d1cSIngo Weinhold return fFrame; 12799ecf9d1cSIngo Weinhold } 12809ecf9d1cSIngo Weinhold 12819ecf9d1cSIngo Weinhold 12829ecf9d1cSIngo Weinhold void 12839ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::SetFrame(BRect frame) 12849ecf9d1cSIngo Weinhold { 12859ecf9d1cSIngo Weinhold fFrame = frame; 12869ecf9d1cSIngo Weinhold fParent->_UpdateFrame(); 12879ecf9d1cSIngo Weinhold } 12889ecf9d1cSIngo Weinhold 12899ecf9d1cSIngo Weinhold 12905c47e35eSAlex Wilson void 12915c47e35eSAlex Wilson BTextControl::LabelLayoutItem::SetParent(BTextControl* parent) 12925c47e35eSAlex Wilson { 12935c47e35eSAlex Wilson fParent = parent; 12945c47e35eSAlex Wilson } 12955c47e35eSAlex Wilson 12965c47e35eSAlex Wilson 12979ecf9d1cSIngo Weinhold BView* 12989ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::View() 12999ecf9d1cSIngo Weinhold { 13009ecf9d1cSIngo Weinhold return fParent; 13019ecf9d1cSIngo Weinhold } 13029ecf9d1cSIngo Weinhold 13039ecf9d1cSIngo Weinhold 13049ecf9d1cSIngo Weinhold BSize 13059ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BaseMinSize() 13069ecf9d1cSIngo Weinhold { 1307349c911eSStephan Aßmus fParent->_ValidateLayoutData(); 1308349c911eSStephan Aßmus 1309349c911eSStephan Aßmus if (!fParent->Label()) 13109ecf9d1cSIngo Weinhold return BSize(-1, -1); 13119ecf9d1cSIngo Weinhold 1312349c911eSStephan Aßmus return BSize(fParent->fLayoutData->label_width + 5, 1313349c911eSStephan Aßmus fParent->fLayoutData->label_height); 13149ecf9d1cSIngo Weinhold } 13159ecf9d1cSIngo Weinhold 13169ecf9d1cSIngo Weinhold 13179ecf9d1cSIngo Weinhold BSize 13189ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BaseMaxSize() 13199ecf9d1cSIngo Weinhold { 13209ecf9d1cSIngo Weinhold return BaseMinSize(); 13219ecf9d1cSIngo Weinhold } 13229ecf9d1cSIngo Weinhold 13239ecf9d1cSIngo Weinhold 13249ecf9d1cSIngo Weinhold BSize 13259ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BasePreferredSize() 13269ecf9d1cSIngo Weinhold { 13279ecf9d1cSIngo Weinhold return BaseMinSize(); 13289ecf9d1cSIngo Weinhold } 13299ecf9d1cSIngo Weinhold 13309ecf9d1cSIngo Weinhold 13319ecf9d1cSIngo Weinhold BAlignment 13329ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BaseAlignment() 13339ecf9d1cSIngo Weinhold { 13349ecf9d1cSIngo Weinhold return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); 13359ecf9d1cSIngo Weinhold } 13369ecf9d1cSIngo Weinhold 13379ecf9d1cSIngo Weinhold 13385c47e35eSAlex Wilson status_t 13395c47e35eSAlex Wilson BTextControl::LabelLayoutItem::Archive(BMessage* into, bool deep) const 13405c47e35eSAlex Wilson { 13415c47e35eSAlex Wilson BArchiver archiver(into); 13425c47e35eSAlex Wilson status_t err = BAbstractLayoutItem::Archive(into, deep); 13435c47e35eSAlex Wilson if (err == B_OK) 13445c47e35eSAlex Wilson err = into->AddRect(kFrameField, fFrame); 13455c47e35eSAlex Wilson 13465c47e35eSAlex Wilson return archiver.Finish(err); 13475c47e35eSAlex Wilson } 13485c47e35eSAlex Wilson 13495c47e35eSAlex Wilson 13505c47e35eSAlex Wilson BArchivable* 13515c47e35eSAlex Wilson BTextControl::LabelLayoutItem::Instantiate(BMessage* from) 13525c47e35eSAlex Wilson { 13535c47e35eSAlex Wilson if (validate_instantiation(from, "BTextControl::LabelLayoutItem")) 13545c47e35eSAlex Wilson return new LabelLayoutItem(from); 13555c47e35eSAlex Wilson return NULL; 13565c47e35eSAlex Wilson } 13575c47e35eSAlex Wilson 13585c47e35eSAlex Wilson 13599ecf9d1cSIngo Weinhold // #pragma mark - 13609ecf9d1cSIngo Weinhold 13619ecf9d1cSIngo Weinhold 13629ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::TextViewLayoutItem(BTextControl* parent) 13635c47e35eSAlex Wilson : 13645c47e35eSAlex Wilson fParent(parent), 13659ecf9d1cSIngo Weinhold fFrame() 13669ecf9d1cSIngo Weinhold { 1367349c911eSStephan Aßmus // by default the part right of the divider shall have an unlimited maximum 1368349c911eSStephan Aßmus // width 1369349c911eSStephan Aßmus SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 13709ecf9d1cSIngo Weinhold } 13719ecf9d1cSIngo Weinhold 13729ecf9d1cSIngo Weinhold 13735c47e35eSAlex Wilson BTextControl::TextViewLayoutItem::TextViewLayoutItem(BMessage* from) 13745c47e35eSAlex Wilson : 13755c47e35eSAlex Wilson BAbstractLayoutItem(from), 13765c47e35eSAlex Wilson fParent(NULL), 13775c47e35eSAlex Wilson fFrame() 13785c47e35eSAlex Wilson { 13795c47e35eSAlex Wilson from->FindRect(kFrameField, &fFrame); 13805c47e35eSAlex Wilson } 13815c47e35eSAlex Wilson 13825c47e35eSAlex Wilson 13839ecf9d1cSIngo Weinhold bool 13849ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::IsVisible() 13859ecf9d1cSIngo Weinhold { 13869ecf9d1cSIngo Weinhold return !fParent->IsHidden(fParent); 13879ecf9d1cSIngo Weinhold } 13889ecf9d1cSIngo Weinhold 13899ecf9d1cSIngo Weinhold 13909ecf9d1cSIngo Weinhold void 13919ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::SetVisible(bool visible) 13929ecf9d1cSIngo Weinhold { 13939ecf9d1cSIngo Weinhold // not allowed 13949ecf9d1cSIngo Weinhold } 13959ecf9d1cSIngo Weinhold 13969ecf9d1cSIngo Weinhold 13979ecf9d1cSIngo Weinhold BRect 13989ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::Frame() 13999ecf9d1cSIngo Weinhold { 14009ecf9d1cSIngo Weinhold return fFrame; 14019ecf9d1cSIngo Weinhold } 14029ecf9d1cSIngo Weinhold 14039ecf9d1cSIngo Weinhold 14049ecf9d1cSIngo Weinhold void 14059ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::SetFrame(BRect frame) 14069ecf9d1cSIngo Weinhold { 14079ecf9d1cSIngo Weinhold fFrame = frame; 14089ecf9d1cSIngo Weinhold fParent->_UpdateFrame(); 14099ecf9d1cSIngo Weinhold } 14109ecf9d1cSIngo Weinhold 14119ecf9d1cSIngo Weinhold 14125c47e35eSAlex Wilson void 14135c47e35eSAlex Wilson BTextControl::TextViewLayoutItem::SetParent(BTextControl* parent) 14145c47e35eSAlex Wilson { 14155c47e35eSAlex Wilson fParent = parent; 14165c47e35eSAlex Wilson } 14175c47e35eSAlex Wilson 14185c47e35eSAlex Wilson 14199ecf9d1cSIngo Weinhold BView* 14209ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::View() 14219ecf9d1cSIngo Weinhold { 14229ecf9d1cSIngo Weinhold return fParent; 14239ecf9d1cSIngo Weinhold } 14249ecf9d1cSIngo Weinhold 14259ecf9d1cSIngo Weinhold 14269ecf9d1cSIngo Weinhold BSize 14279ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BaseMinSize() 14289ecf9d1cSIngo Weinhold { 1429349c911eSStephan Aßmus fParent->_ValidateLayoutData(); 14309ecf9d1cSIngo Weinhold 1431349c911eSStephan Aßmus BSize size = fParent->fLayoutData->text_view_min; 1432349c911eSStephan Aßmus size.width += 2 * kFrameMargin; 1433349c911eSStephan Aßmus size.height += 2 * kFrameMargin; 14349ecf9d1cSIngo Weinhold 14359ecf9d1cSIngo Weinhold return size; 14369ecf9d1cSIngo Weinhold } 14379ecf9d1cSIngo Weinhold 14389ecf9d1cSIngo Weinhold 14399ecf9d1cSIngo Weinhold BSize 14409ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BaseMaxSize() 14419ecf9d1cSIngo Weinhold { 14429ecf9d1cSIngo Weinhold BSize size(BaseMinSize()); 14439ecf9d1cSIngo Weinhold size.width = B_SIZE_UNLIMITED; 14449ecf9d1cSIngo Weinhold return size; 14459ecf9d1cSIngo Weinhold } 14469ecf9d1cSIngo Weinhold 14479ecf9d1cSIngo Weinhold 14489ecf9d1cSIngo Weinhold BSize 14499ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BasePreferredSize() 14509ecf9d1cSIngo Weinhold { 14519ecf9d1cSIngo Weinhold BSize size(BaseMinSize()); 14529ecf9d1cSIngo Weinhold // puh, no idea... 14539ecf9d1cSIngo Weinhold size.width = 100; 14549ecf9d1cSIngo Weinhold return size; 14559ecf9d1cSIngo Weinhold } 14569ecf9d1cSIngo Weinhold 14579ecf9d1cSIngo Weinhold 14589ecf9d1cSIngo Weinhold BAlignment 14599ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BaseAlignment() 14609ecf9d1cSIngo Weinhold { 14619ecf9d1cSIngo Weinhold return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); 14629ecf9d1cSIngo Weinhold } 14639ecf9d1cSIngo Weinhold 14645c47e35eSAlex Wilson 14655c47e35eSAlex Wilson status_t 14665c47e35eSAlex Wilson BTextControl::TextViewLayoutItem::Archive(BMessage* into, bool deep) const 14675c47e35eSAlex Wilson { 14685c47e35eSAlex Wilson BArchiver archiver(into); 14695c47e35eSAlex Wilson status_t err = BAbstractLayoutItem::Archive(into, deep); 14705c47e35eSAlex Wilson if (err == B_OK) 14715c47e35eSAlex Wilson err = into->AddRect(kFrameField, fFrame); 14725c47e35eSAlex Wilson 14735c47e35eSAlex Wilson return archiver.Finish(err); 14745c47e35eSAlex Wilson } 14755c47e35eSAlex Wilson 14765c47e35eSAlex Wilson 14775c47e35eSAlex Wilson BArchivable* 14785c47e35eSAlex Wilson BTextControl::TextViewLayoutItem::Instantiate(BMessage* from) 14795c47e35eSAlex Wilson { 14805c47e35eSAlex Wilson if (validate_instantiation(from, "BTextControl::TextViewLayoutItem")) 14815c47e35eSAlex Wilson return new TextViewLayoutItem(from); 14825c47e35eSAlex Wilson return NULL; 14835c47e35eSAlex Wilson } 14845c47e35eSAlex Wilson 14855c47e35eSAlex Wilson 1486