1105644bfSAxel Dörfler /*
2d9385a9dSJohn Scipione * Copyright 2001-2020 Haiku Inc. All rights reserved.
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>
9d9385a9dSJohn Scipione * John Scipione <jscipione@gmail.com>
10105644bfSAxel Dörfler */
11105644bfSAxel Dörfler
1209d87d91SAxel Dörfler
13991c062fSAxel Dörfler /*! BTextControl displays text that can act like a control. */
14105644bfSAxel Dörfler
15c121b41fSRene Gollent
162f86ba45SStephan Aßmus #include <TextControl.h>
17105644bfSAxel Dörfler
1809d87d91SAxel Dörfler #include <string.h>
1909d87d91SAxel Dörfler
209ecf9d1cSIngo Weinhold #include <AbstractLayoutItem.h>
212f86ba45SStephan Aßmus #include <ControlLook.h>
22*ca985445SPascal Abresch #include <HSL.h>
239ecf9d1cSIngo Weinhold #include <LayoutUtils.h>
24058691d4SStefano Ceccherini #include <Message.h>
252a30a9e9SRene Gollent #include <PropertyInfo.h>
26455d1c46SAxel Dörfler #include <Region.h>
2752a38012Sejakowatz #include <Window.h>
2852a38012Sejakowatz
2939fbf550SOliver Tappe #include <binary_compatibility/Interface.h>
305c47e35eSAlex Wilson #include <binary_compatibility/Support.h>
3139fbf550SOliver Tappe
3252a38012Sejakowatz #include "TextInput.h"
3352a38012Sejakowatz
3452a38012Sejakowatz
3593ba577cSStephan Aßmus //#define TRACE_TEXT_CONTROL
3693ba577cSStephan Aßmus #ifdef TRACE_TEXT_CONTROL
3773161598SJérôme Duval # include <stdio.h>
3893ba577cSStephan Aßmus # include <FunctionTracer.h>
3993ba577cSStephan Aßmus static int32 sFunctionDepth = -1;
40349c911eSStephan Aßmus # define CALLED(x...) FunctionTracer _ft("BTextControl", __FUNCTION__, \
4193ba577cSStephan Aßmus sFunctionDepth)
4293ba577cSStephan Aßmus # define TRACE(x...) { BString _to; \
4393ba577cSStephan Aßmus _to.Append(' ', (sFunctionDepth + 1) * 2); \
4493ba577cSStephan Aßmus printf("%s", _to.String()); printf(x); }
4593ba577cSStephan Aßmus #else
4693ba577cSStephan Aßmus # define CALLED(x...)
4793ba577cSStephan Aßmus # define TRACE(x...)
4893ba577cSStephan Aßmus #endif
4993ba577cSStephan Aßmus
5093ba577cSStephan Aßmus
515c47e35eSAlex Wilson namespace {
525c47e35eSAlex Wilson const char* const kFrameField = "BTextControl:layoutitem:frame";
535c47e35eSAlex Wilson const char* const kTextViewItemField = "BTextControl:textViewItem";
545c47e35eSAlex Wilson const char* const kLabelItemField = "BMenuField:labelItem";
555c47e35eSAlex Wilson }
565c47e35eSAlex Wilson
575c47e35eSAlex Wilson
582a30a9e9SRene Gollent static property_info sPropertyList[] = {
592a30a9e9SRene Gollent {
602a30a9e9SRene Gollent "Value",
612a30a9e9SRene Gollent { B_GET_PROPERTY, B_SET_PROPERTY },
622a30a9e9SRene Gollent { B_DIRECT_SPECIFIER },
632a30a9e9SRene Gollent NULL, 0,
642a30a9e9SRene Gollent { B_STRING_TYPE }
652a30a9e9SRene Gollent },
66346d1496SHumdinger
67346d1496SHumdinger { 0 }
682a30a9e9SRene Gollent };
692a30a9e9SRene Gollent
702a30a9e9SRene Gollent
719ecf9d1cSIngo Weinhold class BTextControl::LabelLayoutItem : public BAbstractLayoutItem {
729ecf9d1cSIngo Weinhold public:
739ecf9d1cSIngo Weinhold LabelLayoutItem(BTextControl* parent);
745c47e35eSAlex Wilson LabelLayoutItem(BMessage* from);
759ecf9d1cSIngo Weinhold
769ecf9d1cSIngo Weinhold virtual bool IsVisible();
779ecf9d1cSIngo Weinhold virtual void SetVisible(bool visible);
789ecf9d1cSIngo Weinhold
799ecf9d1cSIngo Weinhold virtual BRect Frame();
809ecf9d1cSIngo Weinhold virtual void SetFrame(BRect frame);
819ecf9d1cSIngo Weinhold
825c47e35eSAlex Wilson void SetParent(BTextControl* parent);
839ecf9d1cSIngo Weinhold virtual BView* View();
849ecf9d1cSIngo Weinhold
859ecf9d1cSIngo Weinhold virtual BSize BaseMinSize();
869ecf9d1cSIngo Weinhold virtual BSize BaseMaxSize();
879ecf9d1cSIngo Weinhold virtual BSize BasePreferredSize();
889ecf9d1cSIngo Weinhold virtual BAlignment BaseAlignment();
899ecf9d1cSIngo Weinhold
9009d87d91SAxel Dörfler BRect FrameInParent() const;
9109d87d91SAxel Dörfler
925c47e35eSAlex Wilson virtual status_t Archive(BMessage* into, bool deep = true) const;
935c47e35eSAlex Wilson static BArchivable* Instantiate(BMessage* from);
9409d87d91SAxel Dörfler
959ecf9d1cSIngo Weinhold private:
969ecf9d1cSIngo Weinhold BTextControl* fParent;
979ecf9d1cSIngo Weinhold BRect fFrame;
989ecf9d1cSIngo Weinhold };
999ecf9d1cSIngo Weinhold
1009ecf9d1cSIngo Weinhold
1019ecf9d1cSIngo Weinhold class BTextControl::TextViewLayoutItem : public BAbstractLayoutItem {
1029ecf9d1cSIngo Weinhold public:
1039ecf9d1cSIngo Weinhold TextViewLayoutItem(BTextControl* parent);
1045c47e35eSAlex Wilson TextViewLayoutItem(BMessage* from);
1059ecf9d1cSIngo Weinhold
1069ecf9d1cSIngo Weinhold virtual bool IsVisible();
1079ecf9d1cSIngo Weinhold virtual void SetVisible(bool visible);
1089ecf9d1cSIngo Weinhold
1099ecf9d1cSIngo Weinhold virtual BRect Frame();
1109ecf9d1cSIngo Weinhold virtual void SetFrame(BRect frame);
1119ecf9d1cSIngo Weinhold
1125c47e35eSAlex Wilson void SetParent(BTextControl* parent);
1139ecf9d1cSIngo Weinhold virtual BView* View();
1149ecf9d1cSIngo Weinhold
1159ecf9d1cSIngo Weinhold virtual BSize BaseMinSize();
1169ecf9d1cSIngo Weinhold virtual BSize BaseMaxSize();
1179ecf9d1cSIngo Weinhold virtual BSize BasePreferredSize();
1189ecf9d1cSIngo Weinhold virtual BAlignment BaseAlignment();
1199ecf9d1cSIngo Weinhold
12009d87d91SAxel Dörfler BRect FrameInParent() const;
12109d87d91SAxel Dörfler
1225c47e35eSAlex Wilson virtual status_t Archive(BMessage* into, bool deep = true) const;
1235c47e35eSAlex Wilson static BArchivable* Instantiate(BMessage* from);
1249ecf9d1cSIngo Weinhold private:
1259ecf9d1cSIngo Weinhold BTextControl* fParent;
1269ecf9d1cSIngo Weinhold BRect fFrame;
1279ecf9d1cSIngo Weinhold };
1289ecf9d1cSIngo Weinhold
1299ecf9d1cSIngo Weinhold
130349c911eSStephan Aßmus struct BTextControl::LayoutData {
LayoutDataBTextControl::LayoutData131349c911eSStephan Aßmus LayoutData(float width, float height)
1325c47e35eSAlex Wilson :
1335c47e35eSAlex Wilson label_layout_item(NULL),
134349c911eSStephan Aßmus text_view_layout_item(NULL),
135349c911eSStephan Aßmus previous_width(width),
136349c911eSStephan Aßmus previous_height(height),
137349c911eSStephan Aßmus valid(false)
138349c911eSStephan Aßmus {
139349c911eSStephan Aßmus }
140349c911eSStephan Aßmus
141349c911eSStephan Aßmus LabelLayoutItem* label_layout_item;
142349c911eSStephan Aßmus TextViewLayoutItem* text_view_layout_item;
143349c911eSStephan Aßmus float previous_width; // used in FrameResized() for
144349c911eSStephan Aßmus float previous_height; // invalidation
145349c911eSStephan Aßmus font_height font_info;
146349c911eSStephan Aßmus float label_width;
147349c911eSStephan Aßmus float label_height;
148349c911eSStephan Aßmus BSize min;
149349c911eSStephan Aßmus BSize text_view_min;
150349c911eSStephan Aßmus bool valid;
151349c911eSStephan Aßmus };
152349c911eSStephan Aßmus
153349c911eSStephan Aßmus
154349c911eSStephan Aßmus static const int32 kFrameMargin = 2;
155349c911eSStephan Aßmus static const int32 kLabelInputSpacing = 3;
156349c911eSStephan Aßmus
157349c911eSStephan Aßmus
158b11edca4SJohn Scipione // #pragma mark - BTextControl
159b11edca4SJohn Scipione
160b11edca4SJohn Scipione
BTextControl(BRect frame,const char * name,const char * label,const char * text,BMessage * message,uint32 resizeMask,uint32 flags)16152a38012Sejakowatz BTextControl::BTextControl(BRect frame, const char* name, const char* label,
162f4664459SJohn Scipione const char* text, BMessage* message, uint32 resizeMask, uint32 flags)
1635c47e35eSAlex Wilson :
164f4664459SJohn Scipione BControl(frame, name, label, message, resizeMask, flags | B_FRAME_EVENTS)
16552a38012Sejakowatz {
1665c47e35eSAlex Wilson _InitData(label);
1675c47e35eSAlex Wilson _InitText(text);
1689ecf9d1cSIngo Weinhold _ValidateLayout();
1699ecf9d1cSIngo Weinhold }
17052a38012Sejakowatz
171105644bfSAxel Dörfler
BTextControl(const char * name,const char * label,const char * text,BMessage * message,uint32 flags)1729ecf9d1cSIngo Weinhold BTextControl::BTextControl(const char* name, const char* label,
173991c062fSAxel Dörfler const char* text, BMessage* message, uint32 flags)
1745c47e35eSAlex Wilson :
1755c47e35eSAlex Wilson BControl(name, label, message, flags | B_FRAME_EVENTS)
1769ecf9d1cSIngo Weinhold {
1775c47e35eSAlex Wilson _InitData(label);
1785c47e35eSAlex Wilson _InitText(text);
1799ecf9d1cSIngo Weinhold _ValidateLayout();
1809ecf9d1cSIngo Weinhold }
181105644bfSAxel Dörfler
182ffe72abdSAxel Dörfler
BTextControl(const char * label,const char * text,BMessage * message)183991c062fSAxel Dörfler BTextControl::BTextControl(const char* label, const char* text,
184991c062fSAxel Dörfler BMessage* message)
1855c47e35eSAlex Wilson :
1865c47e35eSAlex Wilson BControl(NULL, label, message,
18793ba577cSStephan Aßmus B_WILL_DRAW | B_NAVIGABLE | B_FRAME_EVENTS)
1889ecf9d1cSIngo Weinhold {
1895c47e35eSAlex Wilson _InitData(label);
1905c47e35eSAlex Wilson _InitText(text);
1919ecf9d1cSIngo Weinhold _ValidateLayout();
19252a38012Sejakowatz }
193058691d4SStefano Ceccherini
194058691d4SStefano Ceccherini
~BTextControl()19552a38012Sejakowatz BTextControl::~BTextControl()
19652a38012Sejakowatz {
1979cb2dbe2SMarc Flerackers SetModificationMessage(NULL);
19853aaed9fSStephan Aßmus delete fLayoutData;
19952a38012Sejakowatz }
200058691d4SStefano Ceccherini
201058691d4SStefano Ceccherini
202f4664459SJohn Scipione // #pragma mark - Archiving
203f4664459SJohn Scipione
204f4664459SJohn Scipione
BTextControl(BMessage * archive)205ffe72abdSAxel Dörfler BTextControl::BTextControl(BMessage* archive)
2065c47e35eSAlex Wilson :
2075c47e35eSAlex Wilson BControl(BUnarchiver::PrepareArchive(archive))
20852a38012Sejakowatz {
2095c47e35eSAlex Wilson BUnarchiver unarchiver(archive);
21052a38012Sejakowatz
2115c47e35eSAlex Wilson _InitData(Label(), archive);
21252a38012Sejakowatz
2135c47e35eSAlex Wilson if (!BUnarchiver::IsArchiveManaged(archive))
2145c47e35eSAlex Wilson _InitText(NULL, archive);
21552a38012Sejakowatz
2165c47e35eSAlex Wilson status_t err = B_OK;
217ffe72abdSAxel Dörfler if (archive->HasFloat("_divide"))
2185c47e35eSAlex Wilson err = archive->FindFloat("_divide", &fDivider);
2199cb2dbe2SMarc Flerackers
2205c47e35eSAlex Wilson if (err == B_OK && archive->HasMessage("_mod_msg")) {
221ffe72abdSAxel Dörfler BMessage* message = new BMessage;
2225c47e35eSAlex Wilson err = archive->FindMessage("_mod_msg", message);
223ffe72abdSAxel Dörfler SetModificationMessage(message);
2249cb2dbe2SMarc Flerackers }
2255c47e35eSAlex Wilson
2265c47e35eSAlex Wilson unarchiver.Finish(err);
22752a38012Sejakowatz }
228058691d4SStefano Ceccherini
229058691d4SStefano Ceccherini
230058691d4SStefano Ceccherini BArchivable*
Instantiate(BMessage * archive)231058691d4SStefano Ceccherini BTextControl::Instantiate(BMessage* archive)
23252a38012Sejakowatz {
2339cb2dbe2SMarc Flerackers if (validate_instantiation(archive, "BTextControl"))
2349cb2dbe2SMarc Flerackers return new BTextControl(archive);
235991c062fSAxel Dörfler
23652a38012Sejakowatz return NULL;
23752a38012Sejakowatz }
238058691d4SStefano Ceccherini
239058691d4SStefano Ceccherini
240058691d4SStefano Ceccherini status_t
Archive(BMessage * data,bool deep) const241058691d4SStefano Ceccherini BTextControl::Archive(BMessage* data, bool deep) const
24252a38012Sejakowatz {
2435c47e35eSAlex Wilson BArchiver archiver(data);
244f4664459SJohn Scipione status_t result = BControl::Archive(data, deep);
24552a38012Sejakowatz
246f4664459SJohn Scipione alignment labelAlignment;
247f4664459SJohn Scipione alignment textAlignment;
248f4664459SJohn Scipione if (result == B_OK)
249058691d4SStefano Ceccherini GetAlignment(&labelAlignment, &textAlignment);
2509cb2dbe2SMarc Flerackers
251f4664459SJohn Scipione if (result == B_OK)
252f4664459SJohn Scipione result = data->AddInt32("_a_label", labelAlignment);
2539cb2dbe2SMarc Flerackers
254f4664459SJohn Scipione if (result == B_OK)
255f4664459SJohn Scipione result = data->AddInt32("_a_text", textAlignment);
2569cb2dbe2SMarc Flerackers
257f4664459SJohn Scipione if (result == B_OK)
258f4664459SJohn Scipione result = data->AddFloat("_divide", Divider());
259f4664459SJohn Scipione
260f4664459SJohn Scipione if (result == B_OK && ModificationMessage() != NULL)
261f4664459SJohn Scipione result = data->AddMessage("_mod_msg", ModificationMessage());
262f4664459SJohn Scipione
263f4664459SJohn Scipione return archiver.Finish(result);
2645c47e35eSAlex Wilson }
2655c47e35eSAlex Wilson
2665c47e35eSAlex Wilson
2675c47e35eSAlex Wilson status_t
AllArchived(BMessage * into) const2685c47e35eSAlex Wilson BTextControl::AllArchived(BMessage* into) const
2695c47e35eSAlex Wilson {
2705c47e35eSAlex Wilson BArchiver archiver(into);
2715c47e35eSAlex Wilson status_t err = B_OK;
2725c47e35eSAlex Wilson
2735c47e35eSAlex Wilson if (archiver.IsArchived(fLayoutData->text_view_layout_item)) {
2745c47e35eSAlex Wilson err = archiver.AddArchivable(kTextViewItemField,
2755c47e35eSAlex Wilson fLayoutData->text_view_layout_item);
2765c47e35eSAlex Wilson }
2775c47e35eSAlex Wilson
2785c47e35eSAlex Wilson if (err == B_OK && archiver.IsArchived(fLayoutData->label_layout_item)) {
2795c47e35eSAlex Wilson err = archiver.AddArchivable(kLabelItemField,
2805c47e35eSAlex Wilson fLayoutData->label_layout_item);
2815c47e35eSAlex Wilson }
2825c47e35eSAlex Wilson
2835c47e35eSAlex Wilson return err;
2845c47e35eSAlex Wilson }
2855c47e35eSAlex Wilson
2865c47e35eSAlex Wilson
2875c47e35eSAlex Wilson status_t
AllUnarchived(const BMessage * from)2885c47e35eSAlex Wilson BTextControl::AllUnarchived(const BMessage* from)
2895c47e35eSAlex Wilson {
2905c47e35eSAlex Wilson status_t err;
2915c47e35eSAlex Wilson if ((err = BControl::AllUnarchived(from)) != B_OK)
2925c47e35eSAlex Wilson return err;
2935c47e35eSAlex Wilson
2945c47e35eSAlex Wilson _InitText(NULL, from);
2955c47e35eSAlex Wilson
2965c47e35eSAlex Wilson BUnarchiver unarchiver(from);
2975c47e35eSAlex Wilson if (unarchiver.IsInstantiated(kTextViewItemField)) {
2985c47e35eSAlex Wilson err = unarchiver.FindObject(kTextViewItemField,
2995c47e35eSAlex Wilson BUnarchiver::B_DONT_ASSUME_OWNERSHIP,
3005c47e35eSAlex Wilson fLayoutData->text_view_layout_item);
3015c47e35eSAlex Wilson
3025c47e35eSAlex Wilson if (err == B_OK)
3035c47e35eSAlex Wilson fLayoutData->text_view_layout_item->SetParent(this);
3045c47e35eSAlex Wilson else
3055c47e35eSAlex Wilson return err;
3065c47e35eSAlex Wilson }
3075c47e35eSAlex Wilson
3085c47e35eSAlex Wilson if (unarchiver.IsInstantiated(kLabelItemField)) {
3095c47e35eSAlex Wilson err = unarchiver.FindObject(kLabelItemField,
3105c47e35eSAlex Wilson BUnarchiver::B_DONT_ASSUME_OWNERSHIP,
3115c47e35eSAlex Wilson fLayoutData->label_layout_item);
3125c47e35eSAlex Wilson
3135c47e35eSAlex Wilson if (err == B_OK)
3145c47e35eSAlex Wilson fLayoutData->label_layout_item->SetParent(this);
3155c47e35eSAlex Wilson }
3165c47e35eSAlex Wilson return err;
31752a38012Sejakowatz }
318058691d4SStefano Ceccherini
319058691d4SStefano Ceccherini
320f4664459SJohn Scipione // #pragma mark - Hook methods
321f4664459SJohn Scipione
322f4664459SJohn Scipione
323058691d4SStefano Ceccherini void
AllAttached()324f4664459SJohn Scipione BTextControl::AllAttached()
32552a38012Sejakowatz {
326f4664459SJohn Scipione BControl::AllAttached();
32752a38012Sejakowatz }
328058691d4SStefano Ceccherini
329058691d4SStefano Ceccherini
330058691d4SStefano Ceccherini void
AllDetached()331f4664459SJohn Scipione BTextControl::AllDetached()
33213d147b1SAdrien Destugues {
333f4664459SJohn Scipione BControl::AllDetached();
33452a38012Sejakowatz }
335058691d4SStefano Ceccherini
336058691d4SStefano Ceccherini
337058691d4SStefano Ceccherini void
AttachedToWindow()338058691d4SStefano Ceccherini BTextControl::AttachedToWindow()
33952a38012Sejakowatz {
34052a38012Sejakowatz BControl::AttachedToWindow();
34152a38012Sejakowatz
34279c35b39SAxel Dörfler _UpdateTextViewColors(IsEnabled());
3433a3f6c1eSAxel Dörfler fText->MakeEditable(IsEnabled());
34452a38012Sejakowatz }
345058691d4SStefano Ceccherini
346058691d4SStefano Ceccherini
347058691d4SStefano Ceccherini void
DetachedFromWindow()348058691d4SStefano Ceccherini BTextControl::DetachedFromWindow()
34952a38012Sejakowatz {
35052a38012Sejakowatz BControl::DetachedFromWindow();
35152a38012Sejakowatz }
352058691d4SStefano Ceccherini
353058691d4SStefano Ceccherini
354058691d4SStefano Ceccherini void
Draw(BRect updateRect)355f4664459SJohn Scipione BTextControl::Draw(BRect updateRect)
35652a38012Sejakowatz {
357f4664459SJohn Scipione bool enabled = IsEnabled();
358f4664459SJohn Scipione bool active = fText->IsFocus() && Window()->IsActive();
359f4664459SJohn Scipione
360f4664459SJohn Scipione BRect rect = fText->Frame();
361f4664459SJohn Scipione rect.InsetBy(-2, -2);
362f4664459SJohn Scipione
3637a96554cSlooncraz rgb_color base = ViewColor();
364f4664459SJohn Scipione uint32 flags = fLook;
365f4664459SJohn Scipione if (!enabled)
366f4664459SJohn Scipione flags |= BControlLook::B_DISABLED;
367f4664459SJohn Scipione
368f4664459SJohn Scipione if (active)
369f4664459SJohn Scipione flags |= BControlLook::B_FOCUSED;
370f4664459SJohn Scipione
37142df4f96SJohn Scipione be_control_look->DrawTextControlBorder(this, rect, updateRect, base, flags);
372f4664459SJohn Scipione
373f4664459SJohn Scipione if (Label() != NULL) {
374f4664459SJohn Scipione if (fLayoutData->label_layout_item != NULL) {
375f4664459SJohn Scipione rect = fLayoutData->label_layout_item->FrameInParent();
376f4664459SJohn Scipione } else {
377f4664459SJohn Scipione rect = Bounds();
378f4664459SJohn Scipione rect.right = fDivider - kLabelInputSpacing;
37952a38012Sejakowatz }
380058691d4SStefano Ceccherini
381f4664459SJohn Scipione be_control_look->DrawLabel(this, Label(), rect, updateRect,
382f4664459SJohn Scipione base, flags, BAlignment(fLabelAlign, B_ALIGN_MIDDLE));
383f4664459SJohn Scipione }
38452a38012Sejakowatz }
385058691d4SStefano Ceccherini
386058691d4SStefano Ceccherini
387058691d4SStefano Ceccherini void
FrameMoved(BPoint newPosition)388058691d4SStefano Ceccherini BTextControl::FrameMoved(BPoint newPosition)
38952a38012Sejakowatz {
39052a38012Sejakowatz BControl::FrameMoved(newPosition);
39152a38012Sejakowatz }
392058691d4SStefano Ceccherini
393058691d4SStefano Ceccherini
394058691d4SStefano Ceccherini void
FrameResized(float width,float height)395ffe72abdSAxel Dörfler BTextControl::FrameResized(float width, float height)
39652a38012Sejakowatz {
39793ba577cSStephan Aßmus CALLED();
39893ba577cSStephan Aßmus
399ffe72abdSAxel Dörfler BControl::FrameResized(width, height);
400ffe72abdSAxel Dörfler
401349c911eSStephan Aßmus // TODO: this causes flickering still...
402349c911eSStephan Aßmus
403ffe72abdSAxel Dörfler // changes in width
404ffe72abdSAxel Dörfler
405ffe72abdSAxel Dörfler BRect bounds = Bounds();
406ffe72abdSAxel Dörfler
407349c911eSStephan Aßmus if (bounds.Width() > fLayoutData->previous_width) {
408ffe72abdSAxel Dörfler // invalidate the region between the old and the new right border
409ffe72abdSAxel Dörfler BRect rect = bounds;
410349c911eSStephan Aßmus rect.left += fLayoutData->previous_width - kFrameMargin;
411ffe72abdSAxel Dörfler rect.right--;
412ffe72abdSAxel Dörfler Invalidate(rect);
413349c911eSStephan Aßmus } else if (bounds.Width() < fLayoutData->previous_width) {
414ffe72abdSAxel Dörfler // invalidate the region of the new right border
415ffe72abdSAxel Dörfler BRect rect = bounds;
416349c911eSStephan Aßmus rect.left = rect.right - kFrameMargin;
417ffe72abdSAxel Dörfler Invalidate(rect);
418ffe72abdSAxel Dörfler }
419ffe72abdSAxel Dörfler
420ffe72abdSAxel Dörfler // changes in height
421ffe72abdSAxel Dörfler
422349c911eSStephan Aßmus if (bounds.Height() > fLayoutData->previous_height) {
423ffe72abdSAxel Dörfler // invalidate the region between the old and the new bottom border
424ffe72abdSAxel Dörfler BRect rect = bounds;
425349c911eSStephan Aßmus rect.top += fLayoutData->previous_height - kFrameMargin;
426ffe72abdSAxel Dörfler rect.bottom--;
427ffe72abdSAxel Dörfler Invalidate(rect);
428349c911eSStephan Aßmus // invalidate label area
429349c911eSStephan Aßmus rect = bounds;
430349c911eSStephan Aßmus rect.right = fDivider;
431349c911eSStephan Aßmus Invalidate(rect);
432349c911eSStephan Aßmus } else if (bounds.Height() < fLayoutData->previous_height) {
433ffe72abdSAxel Dörfler // invalidate the region of the new bottom border
434ffe72abdSAxel Dörfler BRect rect = bounds;
435349c911eSStephan Aßmus rect.top = rect.bottom - kFrameMargin;
436349c911eSStephan Aßmus Invalidate(rect);
437349c911eSStephan Aßmus // invalidate label area
438349c911eSStephan Aßmus rect = bounds;
439349c911eSStephan Aßmus rect.right = fDivider;
440ffe72abdSAxel Dörfler Invalidate(rect);
441ffe72abdSAxel Dörfler }
442ffe72abdSAxel Dörfler
443349c911eSStephan Aßmus fLayoutData->previous_width = bounds.Width();
444349c911eSStephan Aßmus fLayoutData->previous_height = bounds.Height();
44593ba577cSStephan Aßmus
44693ba577cSStephan Aßmus TRACE("width: %.2f, height: %.2f\n", bounds.Width(), bounds.Height());
44752a38012Sejakowatz }
448058691d4SStefano Ceccherini
449058691d4SStefano Ceccherini
450f4664459SJohn Scipione status_t
Invoke(BMessage * message)451f4664459SJohn Scipione BTextControl::Invoke(BMessage* message)
452f4664459SJohn Scipione {
453f4664459SJohn Scipione return BControl::Invoke(message);
454f4664459SJohn Scipione }
455f4664459SJohn Scipione
456f4664459SJohn Scipione
457f4664459SJohn Scipione void
LayoutInvalidated(bool descendants)458f4664459SJohn Scipione BTextControl::LayoutInvalidated(bool descendants)
459f4664459SJohn Scipione {
460f4664459SJohn Scipione CALLED();
461f4664459SJohn Scipione
462f4664459SJohn Scipione fLayoutData->valid = false;
463f4664459SJohn Scipione }
464f4664459SJohn Scipione
465f4664459SJohn Scipione
466f4664459SJohn Scipione void
MessageReceived(BMessage * message)467f4664459SJohn Scipione BTextControl::MessageReceived(BMessage* message)
468f4664459SJohn Scipione {
4697a96554cSlooncraz if (message->what == B_COLORS_UPDATED) {
4707a96554cSlooncraz
4717a96554cSlooncraz if (message->HasColor(ui_color_name(B_PANEL_BACKGROUND_COLOR))
4727a96554cSlooncraz || message->HasColor(ui_color_name(B_PANEL_TEXT_COLOR))
4737a96554cSlooncraz || message->HasColor(ui_color_name(B_DOCUMENT_BACKGROUND_COLOR))
474*ca985445SPascal Abresch || message->HasColor(ui_color_name(B_DOCUMENT_TEXT_COLOR))
475*ca985445SPascal Abresch || message->HasColor(ui_color_name(B_FAILURE_COLOR))) {
4767a96554cSlooncraz _UpdateTextViewColors(IsEnabled());
4777a96554cSlooncraz }
4787a96554cSlooncraz }
4797a96554cSlooncraz
480f4664459SJohn Scipione if (message->what == B_GET_PROPERTY || message->what == B_SET_PROPERTY) {
481f4664459SJohn Scipione BMessage reply(B_REPLY);
482f4664459SJohn Scipione bool handled = false;
483f4664459SJohn Scipione
484f4664459SJohn Scipione BMessage specifier;
485f4664459SJohn Scipione int32 index;
486f4664459SJohn Scipione int32 form;
487f4664459SJohn Scipione const char* property;
488f4664459SJohn Scipione if (message->GetCurrentSpecifier(&index, &specifier, &form, &property) == B_OK) {
489f4664459SJohn Scipione if (strcmp(property, "Value") == 0) {
490f4664459SJohn Scipione if (message->what == B_GET_PROPERTY) {
491f4664459SJohn Scipione reply.AddString("result", fText->Text());
492f4664459SJohn Scipione handled = true;
493f4664459SJohn Scipione } else {
494f4664459SJohn Scipione const char* value = NULL;
495f4664459SJohn Scipione // B_SET_PROPERTY
496f4664459SJohn Scipione if (message->FindString("data", &value) == B_OK) {
497f4664459SJohn Scipione fText->SetText(value);
498f4664459SJohn Scipione reply.AddInt32("error", B_OK);
499f4664459SJohn Scipione handled = true;
500f4664459SJohn Scipione }
501f4664459SJohn Scipione }
502f4664459SJohn Scipione }
503f4664459SJohn Scipione }
504f4664459SJohn Scipione
505f4664459SJohn Scipione if (handled) {
506f4664459SJohn Scipione message->SendReply(&reply);
507f4664459SJohn Scipione return;
508f4664459SJohn Scipione }
509f4664459SJohn Scipione }
510f4664459SJohn Scipione
511f4664459SJohn Scipione BControl::MessageReceived(message);
512f4664459SJohn Scipione }
513f4664459SJohn Scipione
514f4664459SJohn Scipione
515f4664459SJohn Scipione void
MouseDown(BPoint where)516f4664459SJohn Scipione BTextControl::MouseDown(BPoint where)
517f4664459SJohn Scipione {
518f4664459SJohn Scipione if (!fText->IsFocus())
519f4664459SJohn Scipione fText->MakeFocus(true);
520f4664459SJohn Scipione }
521f4664459SJohn Scipione
522f4664459SJohn Scipione
523f4664459SJohn Scipione void
MouseMoved(BPoint where,uint32 transit,const BMessage * dragMessage)524f4664459SJohn Scipione BTextControl::MouseMoved(BPoint where, uint32 transit,
525f4664459SJohn Scipione const BMessage* dragMessage)
526f4664459SJohn Scipione {
527f4664459SJohn Scipione BControl::MouseMoved(where, transit, dragMessage);
528f4664459SJohn Scipione }
529f4664459SJohn Scipione
530f4664459SJohn Scipione
531f4664459SJohn Scipione void
MouseUp(BPoint where)532f4664459SJohn Scipione BTextControl::MouseUp(BPoint where)
533f4664459SJohn Scipione {
534f4664459SJohn Scipione BControl::MouseUp(where);
535f4664459SJohn Scipione }
536f4664459SJohn Scipione
537f4664459SJohn Scipione
538058691d4SStefano Ceccherini void
WindowActivated(bool active)539058691d4SStefano Ceccherini BTextControl::WindowActivated(bool active)
54052a38012Sejakowatz {
5416d8d6cadSStephan Aßmus if (fText->IsFocus()) {
542dde10e45SStephan Aßmus // invalidate to remove/show focus indication
5432c5a8894SStephan Aßmus BRect rect = fText->Frame();
5442c5a8894SStephan Aßmus rect.InsetBy(-1, -1);
5456d8d6cadSStephan Aßmus Invalidate(rect);
546dde10e45SStephan Aßmus
547dde10e45SStephan Aßmus // help out embedded text view which doesn't
548dde10e45SStephan Aßmus // get notified of this
549dde10e45SStephan Aßmus fText->Invalidate();
5506d8d6cadSStephan Aßmus }
55152a38012Sejakowatz }
552058691d4SStefano Ceccherini
553058691d4SStefano Ceccherini
554f4664459SJohn Scipione // #pragma mark - Getters and Setters
555f4664459SJohn Scipione
556f4664459SJohn Scipione
557f4664459SJohn Scipione void
SetText(const char * text)558f4664459SJohn Scipione BTextControl::SetText(const char* text)
559f4664459SJohn Scipione {
560f4664459SJohn Scipione if (InvokeKind() != B_CONTROL_INVOKED)
561f4664459SJohn Scipione return;
562f4664459SJohn Scipione
563f4664459SJohn Scipione CALLED();
564f4664459SJohn Scipione
565f4664459SJohn Scipione fText->SetText(text);
566f4664459SJohn Scipione
567f4664459SJohn Scipione if (fText->IsFocus()) {
568f4664459SJohn Scipione fText->SetInitialText();
569f4664459SJohn Scipione fText->SelectAll();
570f4664459SJohn Scipione }
571f4664459SJohn Scipione
572f4664459SJohn Scipione fText->Invalidate();
573f4664459SJohn Scipione }
574f4664459SJohn Scipione
575f4664459SJohn Scipione
576f4664459SJohn Scipione const char*
Text() const577f4664459SJohn Scipione BTextControl::Text() const
578f4664459SJohn Scipione {
579f4664459SJohn Scipione return fText->Text();
580f4664459SJohn Scipione }
581f4664459SJohn Scipione
582f4664459SJohn Scipione
5838bc3ecb0SAxel Dörfler int32
TextLength() const5848bc3ecb0SAxel Dörfler BTextControl::TextLength() const
5858bc3ecb0SAxel Dörfler {
5868bc3ecb0SAxel Dörfler return fText->TextLength();
5878bc3ecb0SAxel Dörfler }
5888bc3ecb0SAxel Dörfler
5898bc3ecb0SAxel Dörfler
590f4664459SJohn Scipione void
MarkAsInvalid(bool invalid)591f4664459SJohn Scipione BTextControl::MarkAsInvalid(bool invalid)
592f4664459SJohn Scipione {
593f4664459SJohn Scipione uint32 look = fLook;
594f4664459SJohn Scipione
595f4664459SJohn Scipione if (invalid)
596f4664459SJohn Scipione fLook |= BControlLook::B_INVALID;
597f4664459SJohn Scipione else
598f4664459SJohn Scipione fLook &= ~BControlLook::B_INVALID;
599f4664459SJohn Scipione
600*ca985445SPascal Abresch if (look != fLook) {
601*ca985445SPascal Abresch _UpdateTextViewColors(IsEnabled());
602f4664459SJohn Scipione Invalidate();
603f4664459SJohn Scipione }
604*ca985445SPascal Abresch }
605f4664459SJohn Scipione
606f4664459SJohn Scipione
607f4664459SJohn Scipione void
SetValue(int32 value)608f4664459SJohn Scipione BTextControl::SetValue(int32 value)
609f4664459SJohn Scipione {
610f4664459SJohn Scipione BControl::SetValue(value);
611f4664459SJohn Scipione }
612f4664459SJohn Scipione
613f4664459SJohn Scipione
614f4664459SJohn Scipione BTextView*
TextView() const615f4664459SJohn Scipione BTextControl::TextView() const
616f4664459SJohn Scipione {
617f4664459SJohn Scipione return fText;
618f4664459SJohn Scipione }
619f4664459SJohn Scipione
620f4664459SJohn Scipione
621f4664459SJohn Scipione void
SetModificationMessage(BMessage * message)622f4664459SJohn Scipione BTextControl::SetModificationMessage(BMessage* message)
623f4664459SJohn Scipione {
624f4664459SJohn Scipione delete fModificationMessage;
625f4664459SJohn Scipione fModificationMessage = message;
626f4664459SJohn Scipione }
627f4664459SJohn Scipione
628f4664459SJohn Scipione
629f4664459SJohn Scipione BMessage*
ModificationMessage() const630f4664459SJohn Scipione BTextControl::ModificationMessage() const
631f4664459SJohn Scipione {
632f4664459SJohn Scipione return fModificationMessage;
633f4664459SJohn Scipione }
634f4664459SJohn Scipione
635f4664459SJohn Scipione
636f4664459SJohn Scipione void
SetAlignment(alignment labelAlignment,alignment textAlignment)637f4664459SJohn Scipione BTextControl::SetAlignment(alignment labelAlignment, alignment textAlignment)
638f4664459SJohn Scipione {
639f4664459SJohn Scipione fText->SetAlignment(textAlignment);
640f4664459SJohn Scipione
641f4664459SJohn Scipione if (fLabelAlign != labelAlignment) {
642f4664459SJohn Scipione fLabelAlign = labelAlignment;
643f4664459SJohn Scipione Invalidate();
644f4664459SJohn Scipione }
645f4664459SJohn Scipione }
646f4664459SJohn Scipione
647f4664459SJohn Scipione
648f4664459SJohn Scipione void
GetAlignment(alignment * _label,alignment * _text) const649f4664459SJohn Scipione BTextControl::GetAlignment(alignment* _label, alignment* _text) const
650f4664459SJohn Scipione {
651f4664459SJohn Scipione if (_label != NULL)
652f4664459SJohn Scipione *_label = fLabelAlign;
653f4664459SJohn Scipione
654f4664459SJohn Scipione if (_text != NULL)
655f4664459SJohn Scipione *_text = fText->Alignment();
656f4664459SJohn Scipione }
657f4664459SJohn Scipione
658f4664459SJohn Scipione
659f4664459SJohn Scipione void
SetDivider(float position)660f4664459SJohn Scipione BTextControl::SetDivider(float position)
661f4664459SJohn Scipione {
662f4664459SJohn Scipione fDivider = floorf(position + 0.5);
663f4664459SJohn Scipione
664f4664459SJohn Scipione _LayoutTextView();
665f4664459SJohn Scipione
666f4664459SJohn Scipione if (Window()) {
667f4664459SJohn Scipione fText->Invalidate();
668f4664459SJohn Scipione Invalidate();
669f4664459SJohn Scipione }
670f4664459SJohn Scipione }
671f4664459SJohn Scipione
672f4664459SJohn Scipione
673f4664459SJohn Scipione float
Divider() const674f4664459SJohn Scipione BTextControl::Divider() const
675f4664459SJohn Scipione {
676f4664459SJohn Scipione return fDivider;
677f4664459SJohn Scipione }
678f4664459SJohn Scipione
679f4664459SJohn Scipione
680f4664459SJohn Scipione void
MakeFocus(bool state)681f4664459SJohn Scipione BTextControl::MakeFocus(bool state)
682f4664459SJohn Scipione {
683f4664459SJohn Scipione if (state != fText->IsFocus()) {
684f4664459SJohn Scipione fText->MakeFocus(state);
685f4664459SJohn Scipione
686f4664459SJohn Scipione if (state)
687f4664459SJohn Scipione fText->SelectAll();
688f4664459SJohn Scipione }
689f4664459SJohn Scipione }
690f4664459SJohn Scipione
691f4664459SJohn Scipione
692f4664459SJohn Scipione void
SetEnabled(bool enable)693f4664459SJohn Scipione BTextControl::SetEnabled(bool enable)
694f4664459SJohn Scipione {
695f4664459SJohn Scipione if (IsEnabled() == enable)
696f4664459SJohn Scipione return;
697f4664459SJohn Scipione
698f4664459SJohn Scipione if (Window() != NULL) {
699f4664459SJohn Scipione fText->MakeEditable(enable);
700f4664459SJohn Scipione if (enable)
701f4664459SJohn Scipione fText->SetFlags(fText->Flags() | B_NAVIGABLE);
702f4664459SJohn Scipione else
703f4664459SJohn Scipione fText->SetFlags(fText->Flags() & ~B_NAVIGABLE);
704f4664459SJohn Scipione
705f4664459SJohn Scipione _UpdateTextViewColors(enable);
706f4664459SJohn Scipione
707f4664459SJohn Scipione fText->Invalidate();
708f4664459SJohn Scipione Window()->UpdateIfNeeded();
709f4664459SJohn Scipione }
710f4664459SJohn Scipione
711f4664459SJohn Scipione BControl::SetEnabled(enable);
712f4664459SJohn Scipione }
713f4664459SJohn Scipione
714f4664459SJohn Scipione
715f4664459SJohn Scipione void
GetPreferredSize(float * _width,float * _height)716f4664459SJohn Scipione BTextControl::GetPreferredSize(float* _width, float* _height)
717f4664459SJohn Scipione {
718f4664459SJohn Scipione CALLED();
719f4664459SJohn Scipione
720f4664459SJohn Scipione _ValidateLayoutData();
721f4664459SJohn Scipione
722f4664459SJohn Scipione if (_width) {
723f4664459SJohn Scipione float minWidth = fLayoutData->min.width;
724f4664459SJohn Scipione if (Label() == NULL && !(Flags() & B_SUPPORTS_LAYOUT)) {
725f4664459SJohn Scipione // Indeed, only if there is no label! BeOS backwards compatible
726f4664459SJohn Scipione // behavior:
727f4664459SJohn Scipione minWidth = max_c(minWidth, Bounds().Width());
728f4664459SJohn Scipione }
729f4664459SJohn Scipione *_width = minWidth;
730f4664459SJohn Scipione }
731f4664459SJohn Scipione
732f4664459SJohn Scipione if (_height)
733f4664459SJohn Scipione *_height = fLayoutData->min.height;
734f4664459SJohn Scipione }
735f4664459SJohn Scipione
736f4664459SJohn Scipione
737f4664459SJohn Scipione void
ResizeToPreferred()738f4664459SJohn Scipione BTextControl::ResizeToPreferred()
739f4664459SJohn Scipione {
740f4664459SJohn Scipione BView::ResizeToPreferred();
741f4664459SJohn Scipione
742f4664459SJohn Scipione fDivider = 0.0;
743f4664459SJohn Scipione const char* label = Label();
744f4664459SJohn Scipione if (label)
745f4664459SJohn Scipione fDivider = ceil(StringWidth(label)) + 2.0;
746f4664459SJohn Scipione
747f4664459SJohn Scipione _LayoutTextView();
748f4664459SJohn Scipione }
749f4664459SJohn Scipione
750f4664459SJohn Scipione
751f4664459SJohn Scipione void
SetFlags(uint32 flags)752f4664459SJohn Scipione BTextControl::SetFlags(uint32 flags)
753f4664459SJohn Scipione {
754f4664459SJohn Scipione // If the textview is navigable, set it to not navigable if needed
755f4664459SJohn Scipione // Else if it is not navigable, set it to navigable if needed
756f4664459SJohn Scipione if (fText->Flags() & B_NAVIGABLE) {
757f4664459SJohn Scipione if (!(flags & B_NAVIGABLE))
758f4664459SJohn Scipione fText->SetFlags(fText->Flags() & ~B_NAVIGABLE);
759f4664459SJohn Scipione
760f4664459SJohn Scipione } else {
761f4664459SJohn Scipione if (flags & B_NAVIGABLE)
762f4664459SJohn Scipione fText->SetFlags(fText->Flags() | B_NAVIGABLE);
763f4664459SJohn Scipione }
764f4664459SJohn Scipione
765f4664459SJohn Scipione // Don't make this one navigable
766f4664459SJohn Scipione flags &= ~B_NAVIGABLE;
767f4664459SJohn Scipione
768f4664459SJohn Scipione BView::SetFlags(flags);
769f4664459SJohn Scipione }
770f4664459SJohn Scipione
771f4664459SJohn Scipione
772f4664459SJohn Scipione // #pragma mark - Scripting
773f4664459SJohn Scipione
774f4664459SJohn Scipione
775f4664459SJohn Scipione BHandler*
ResolveSpecifier(BMessage * message,int32 index,BMessage * specifier,int32 what,const char * property)776f4664459SJohn Scipione BTextControl::ResolveSpecifier(BMessage* message, int32 index,
777f4664459SJohn Scipione BMessage* specifier, int32 what, const char* property)
778f4664459SJohn Scipione {
779f4664459SJohn Scipione BPropertyInfo propInfo(sPropertyList);
780f4664459SJohn Scipione
781f4664459SJohn Scipione if (propInfo.FindMatch(message, 0, specifier, what, property) >= B_OK)
782f4664459SJohn Scipione return this;
783f4664459SJohn Scipione
784f4664459SJohn Scipione return BControl::ResolveSpecifier(message, index, specifier, what,
785f4664459SJohn Scipione property);
786f4664459SJohn Scipione }
787f4664459SJohn Scipione
788f4664459SJohn Scipione
789f4664459SJohn Scipione status_t
GetSupportedSuites(BMessage * data)790f4664459SJohn Scipione BTextControl::GetSupportedSuites(BMessage* data)
791f4664459SJohn Scipione {
792f4664459SJohn Scipione return BControl::GetSupportedSuites(data);
793f4664459SJohn Scipione }
794f4664459SJohn Scipione
795f4664459SJohn Scipione
796f4664459SJohn Scipione // #pragma mark - Layout
797f4664459SJohn Scipione
798f4664459SJohn Scipione
799349c911eSStephan Aßmus BSize
MinSize()800349c911eSStephan Aßmus BTextControl::MinSize()
80152a38012Sejakowatz {
802349c911eSStephan Aßmus CALLED();
803349c911eSStephan Aßmus
804349c911eSStephan Aßmus _ValidateLayoutData();
805349c911eSStephan Aßmus return BLayoutUtils::ComposeSize(ExplicitMinSize(), fLayoutData->min);
806349c911eSStephan Aßmus }
807349c911eSStephan Aßmus
808349c911eSStephan Aßmus
809349c911eSStephan Aßmus BSize
MaxSize()810349c911eSStephan Aßmus BTextControl::MaxSize()
811349c911eSStephan Aßmus {
812349c911eSStephan Aßmus CALLED();
813349c911eSStephan Aßmus
814349c911eSStephan Aßmus _ValidateLayoutData();
815349c911eSStephan Aßmus
816349c911eSStephan Aßmus BSize max = fLayoutData->min;
817349c911eSStephan Aßmus max.width = B_SIZE_UNLIMITED;
818349c911eSStephan Aßmus
819349c911eSStephan Aßmus return BLayoutUtils::ComposeSize(ExplicitMaxSize(), max);
820349c911eSStephan Aßmus }
821349c911eSStephan Aßmus
822349c911eSStephan Aßmus
823349c911eSStephan Aßmus BSize
PreferredSize()824349c911eSStephan Aßmus BTextControl::PreferredSize()
825349c911eSStephan Aßmus {
826349c911eSStephan Aßmus CALLED();
827349c911eSStephan Aßmus
828349c911eSStephan Aßmus _ValidateLayoutData();
829349c911eSStephan Aßmus return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), fLayoutData->min);
830349c911eSStephan Aßmus }
831349c911eSStephan Aßmus
832349c911eSStephan Aßmus
83346d6e9d9SRene Gollent BAlignment
LayoutAlignment()83446d6e9d9SRene Gollent BTextControl::LayoutAlignment()
83546d6e9d9SRene Gollent {
83646d6e9d9SRene Gollent CALLED();
83746d6e9d9SRene Gollent
83846d6e9d9SRene Gollent _ValidateLayoutData();
83946d6e9d9SRene Gollent return BLayoutUtils::ComposeAlignment(ExplicitAlignment(),
840be92485fSHumdinger BAlignment(B_ALIGN_LEFT, B_ALIGN_VERTICAL_CENTER));
84146d6e9d9SRene Gollent }
84246d6e9d9SRene Gollent
84346d6e9d9SRene Gollent
8449ecf9d1cSIngo Weinhold BLayoutItem*
CreateLabelLayoutItem()8459ecf9d1cSIngo Weinhold BTextControl::CreateLabelLayoutItem()
8469ecf9d1cSIngo Weinhold {
847349c911eSStephan Aßmus if (!fLayoutData->label_layout_item)
848349c911eSStephan Aßmus fLayoutData->label_layout_item = new LabelLayoutItem(this);
849b11edca4SJohn Scipione
850349c911eSStephan Aßmus return fLayoutData->label_layout_item;
8519ecf9d1cSIngo Weinhold }
8529ecf9d1cSIngo Weinhold
8539ecf9d1cSIngo Weinhold
8549ecf9d1cSIngo Weinhold BLayoutItem*
CreateTextViewLayoutItem()8559ecf9d1cSIngo Weinhold BTextControl::CreateTextViewLayoutItem()
8569ecf9d1cSIngo Weinhold {
857349c911eSStephan Aßmus if (!fLayoutData->text_view_layout_item)
858349c911eSStephan Aßmus fLayoutData->text_view_layout_item = new TextViewLayoutItem(this);
859b11edca4SJohn Scipione
860349c911eSStephan Aßmus return fLayoutData->text_view_layout_item;
861349c911eSStephan Aßmus }
862349c911eSStephan Aßmus
863349c911eSStephan Aßmus
864349c911eSStephan Aßmus void
DoLayout()865349c911eSStephan Aßmus BTextControl::DoLayout()
866349c911eSStephan Aßmus {
867349c911eSStephan Aßmus // Bail out, if we shan't do layout.
868349c911eSStephan Aßmus if (!(Flags() & B_SUPPORTS_LAYOUT))
869349c911eSStephan Aßmus return;
870349c911eSStephan Aßmus
871349c911eSStephan Aßmus CALLED();
872349c911eSStephan Aßmus
873349c911eSStephan Aßmus // If the user set a layout, we let the base class version call its
874349c911eSStephan Aßmus // hook.
875349c911eSStephan Aßmus if (GetLayout()) {
876349c911eSStephan Aßmus BView::DoLayout();
877349c911eSStephan Aßmus return;
878349c911eSStephan Aßmus }
879349c911eSStephan Aßmus
880349c911eSStephan Aßmus _ValidateLayoutData();
881349c911eSStephan Aßmus
882349c911eSStephan Aßmus // validate current size
883349c911eSStephan Aßmus BSize size(Bounds().Size());
884349c911eSStephan Aßmus if (size.width < fLayoutData->min.width)
885349c911eSStephan Aßmus size.width = fLayoutData->min.width;
886b11edca4SJohn Scipione
887349c911eSStephan Aßmus if (size.height < fLayoutData->min.height)
888349c911eSStephan Aßmus size.height = fLayoutData->min.height;
889349c911eSStephan Aßmus
89009d87d91SAxel Dörfler BRect dirty(fText->Frame());
89109d87d91SAxel Dörfler BRect textFrame;
89209d87d91SAxel Dörfler
893349c911eSStephan Aßmus // divider
894349c911eSStephan Aßmus float divider = 0;
89509d87d91SAxel Dörfler if (fLayoutData->text_view_layout_item != NULL) {
89609d87d91SAxel Dörfler if (fLayoutData->label_layout_item != NULL) {
897349c911eSStephan Aßmus // We have layout items. They define the divider location.
89809d87d91SAxel Dörfler divider = fabs(fLayoutData->text_view_layout_item->Frame().left
89909d87d91SAxel Dörfler - fLayoutData->label_layout_item->Frame().left);
90009d87d91SAxel Dörfler }
90109d87d91SAxel Dörfler textFrame = fLayoutData->text_view_layout_item->FrameInParent();
902349c911eSStephan Aßmus } else {
90309d87d91SAxel Dörfler if (fLayoutData->label_width > 0) {
90409d87d91SAxel Dörfler divider = fLayoutData->label_width
90509d87d91SAxel Dörfler + be_control_look->DefaultLabelSpacing();
90609d87d91SAxel Dörfler }
90709d87d91SAxel Dörfler textFrame.Set(divider, 0, size.width, size.height);
908349c911eSStephan Aßmus }
909349c911eSStephan Aßmus
910349c911eSStephan Aßmus // place the text view and set the divider
91109d87d91SAxel Dörfler textFrame.InsetBy(kFrameMargin, kFrameMargin);
912349c911eSStephan Aßmus BLayoutUtils::AlignInFrame(fText, textFrame);
913d9385a9dSJohn Scipione fText->SetTextRect(textFrame.OffsetToCopy(B_ORIGIN));
914349c911eSStephan Aßmus
915349c911eSStephan Aßmus fDivider = divider;
916349c911eSStephan Aßmus
917349c911eSStephan Aßmus // invalidate dirty region
918349c911eSStephan Aßmus dirty = dirty | fText->Frame();
919349c911eSStephan Aßmus dirty.InsetBy(-kFrameMargin, -kFrameMargin);
920349c911eSStephan Aßmus
921349c911eSStephan Aßmus Invalidate(dirty);
922349c911eSStephan Aßmus }
923349c911eSStephan Aßmus
924349c911eSStephan Aßmus
925f4664459SJohn Scipione // #pragma mark - protected methods
926f4664459SJohn Scipione
927f4664459SJohn Scipione
928be436742SIngo Weinhold status_t
SetIcon(const BBitmap * icon,uint32 flags)929be436742SIngo Weinhold BTextControl::SetIcon(const BBitmap* icon, uint32 flags)
930be436742SIngo Weinhold {
931be436742SIngo Weinhold return BControl::SetIcon(icon, flags);
932be436742SIngo Weinhold }
933be436742SIngo Weinhold
934be436742SIngo Weinhold
935f4664459SJohn Scipione // #pragma mark - private methods
936349c911eSStephan Aßmus
937349c911eSStephan Aßmus
938349c911eSStephan Aßmus status_t
Perform(perform_code code,void * _data)93939fbf550SOliver Tappe BTextControl::Perform(perform_code code, void* _data)
940349c911eSStephan Aßmus {
94139fbf550SOliver Tappe switch (code) {
94239fbf550SOliver Tappe case PERFORM_CODE_MIN_SIZE:
94339fbf550SOliver Tappe ((perform_data_min_size*)_data)->return_value
94439fbf550SOliver Tappe = BTextControl::MinSize();
94539fbf550SOliver Tappe return B_OK;
946b11edca4SJohn Scipione
94739fbf550SOliver Tappe case PERFORM_CODE_MAX_SIZE:
94839fbf550SOliver Tappe ((perform_data_max_size*)_data)->return_value
94939fbf550SOliver Tappe = BTextControl::MaxSize();
95039fbf550SOliver Tappe return B_OK;
951b11edca4SJohn Scipione
95239fbf550SOliver Tappe case PERFORM_CODE_PREFERRED_SIZE:
95339fbf550SOliver Tappe ((perform_data_preferred_size*)_data)->return_value
95439fbf550SOliver Tappe = BTextControl::PreferredSize();
95539fbf550SOliver Tappe return B_OK;
956b11edca4SJohn Scipione
95739fbf550SOliver Tappe case PERFORM_CODE_LAYOUT_ALIGNMENT:
95839fbf550SOliver Tappe ((perform_data_layout_alignment*)_data)->return_value
95939fbf550SOliver Tappe = BTextControl::LayoutAlignment();
96039fbf550SOliver Tappe return B_OK;
961b11edca4SJohn Scipione
96239fbf550SOliver Tappe case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
96339fbf550SOliver Tappe ((perform_data_has_height_for_width*)_data)->return_value
96439fbf550SOliver Tappe = BTextControl::HasHeightForWidth();
96539fbf550SOliver Tappe return B_OK;
966b11edca4SJohn Scipione
96739fbf550SOliver Tappe case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
96839fbf550SOliver Tappe {
96939fbf550SOliver Tappe perform_data_get_height_for_width* data
97039fbf550SOliver Tappe = (perform_data_get_height_for_width*)_data;
97139fbf550SOliver Tappe BTextControl::GetHeightForWidth(data->width, &data->min, &data->max,
97239fbf550SOliver Tappe &data->preferred);
97339fbf550SOliver Tappe return B_OK;
97439fbf550SOliver Tappe }
975b11edca4SJohn Scipione
97639fbf550SOliver Tappe case PERFORM_CODE_SET_LAYOUT:
97739fbf550SOliver Tappe {
97839fbf550SOliver Tappe perform_data_set_layout* data = (perform_data_set_layout*)_data;
97939fbf550SOliver Tappe BTextControl::SetLayout(data->layout);
98039fbf550SOliver Tappe return B_OK;
98139fbf550SOliver Tappe }
982b11edca4SJohn Scipione
983eee4243dSAlex Wilson case PERFORM_CODE_LAYOUT_INVALIDATED:
98439fbf550SOliver Tappe {
985eee4243dSAlex Wilson perform_data_layout_invalidated* data
986eee4243dSAlex Wilson = (perform_data_layout_invalidated*)_data;
987eee4243dSAlex Wilson BTextControl::LayoutInvalidated(data->descendants);
98839fbf550SOliver Tappe return B_OK;
98939fbf550SOliver Tappe }
990b11edca4SJohn Scipione
99139fbf550SOliver Tappe case PERFORM_CODE_DO_LAYOUT:
99239fbf550SOliver Tappe {
99339fbf550SOliver Tappe BTextControl::DoLayout();
99439fbf550SOliver Tappe return B_OK;
99539fbf550SOliver Tappe }
996b11edca4SJohn Scipione
997be436742SIngo Weinhold case PERFORM_CODE_SET_ICON:
998be436742SIngo Weinhold {
999be436742SIngo Weinhold perform_data_set_icon* data = (perform_data_set_icon*)_data;
1000be436742SIngo Weinhold return BTextControl::SetIcon(data->icon, data->flags);
1001be436742SIngo Weinhold }
1002b11edca4SJohn Scipione
10035c47e35eSAlex Wilson case PERFORM_CODE_ALL_UNARCHIVED:
10045c47e35eSAlex Wilson {
10055c47e35eSAlex Wilson perform_data_all_unarchived* data
10065c47e35eSAlex Wilson = (perform_data_all_unarchived*)_data;
10075c47e35eSAlex Wilson data->return_value = BTextControl::AllUnarchived(data->archive);
10085c47e35eSAlex Wilson return B_OK;
10095c47e35eSAlex Wilson }
1010b11edca4SJohn Scipione
10115c47e35eSAlex Wilson case PERFORM_CODE_ALL_ARCHIVED:
10125c47e35eSAlex Wilson {
10135c47e35eSAlex Wilson perform_data_all_archived* data
10145c47e35eSAlex Wilson = (perform_data_all_archived*)_data;
10155c47e35eSAlex Wilson data->return_value = BTextControl::AllArchived(data->archive);
10165c47e35eSAlex Wilson return B_OK;
10175c47e35eSAlex Wilson }
101839fbf550SOliver Tappe }
101939fbf550SOliver Tappe
102039fbf550SOliver Tappe return BControl::Perform(code, _data);
10219ecf9d1cSIngo Weinhold }
10229ecf9d1cSIngo Weinhold
10239ecf9d1cSIngo Weinhold
1024f4664459SJohn Scipione // #pragma mark - FBC padding
1025f4664459SJohn Scipione
1026f4664459SJohn Scipione
_ReservedTextControl1()10279cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl1() {}
_ReservedTextControl2()10289cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl2() {}
_ReservedTextControl3()10299cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl3() {}
_ReservedTextControl4()10309cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl4() {}
1031058691d4SStefano Ceccherini
1032058691d4SStefano Ceccherini
1033058691d4SStefano Ceccherini BTextControl&
operator =(const BTextControl &)1034058691d4SStefano Ceccherini BTextControl::operator=(const BTextControl&)
103552a38012Sejakowatz {
103652a38012Sejakowatz return *this;
103752a38012Sejakowatz }
1038058691d4SStefano Ceccherini
1039058691d4SStefano Ceccherini
1040058691d4SStefano Ceccherini void
_UpdateTextViewColors(bool enable)1041f4664459SJohn Scipione BTextControl::_UpdateTextViewColors(bool enable)
10423a3f6c1eSAxel Dörfler {
10437a96554cSlooncraz rgb_color textColor = ui_color(B_DOCUMENT_TEXT_COLOR);
10447a96554cSlooncraz rgb_color viewColor = ui_color(B_DOCUMENT_BACKGROUND_COLOR);
10453a3f6c1eSAxel Dörfler BFont font;
10463a3f6c1eSAxel Dörfler
1047aae7000dSAxel Dörfler fText->GetFontAndColor(0, &font);
10483a3f6c1eSAxel Dörfler
10497a96554cSlooncraz if (!enable) {
10507a96554cSlooncraz textColor = disable_color(textColor, ViewColor());
10517a96554cSlooncraz viewColor = disable_color(ViewColor(), viewColor);
1052*ca985445SPascal Abresch } else if (fLook & BControlLook::B_INVALID) {
1053*ca985445SPascal Abresch hsl_color normalViewColor = hsl_color::from_rgb(viewColor);
1054*ca985445SPascal Abresch rgb_color failureColor = ui_color(B_FAILURE_COLOR);
1055*ca985445SPascal Abresch hsl_color newViewColor = hsl_color::from_rgb(failureColor);
1056*ca985445SPascal Abresch if (normalViewColor.lightness < 0.15)
1057*ca985445SPascal Abresch newViewColor.lightness = 0.15;
1058*ca985445SPascal Abresch else if (normalViewColor.lightness > 0.95)
1059*ca985445SPascal Abresch newViewColor.lightness = 0.95;
1060*ca985445SPascal Abresch else
1061*ca985445SPascal Abresch newViewColor.lightness = normalViewColor.lightness;
1062*ca985445SPascal Abresch
1063*ca985445SPascal Abresch viewColor = newViewColor.to_rgb();
106412aefeb4SAxel Dörfler }
10653a3f6c1eSAxel Dörfler
10663a3f6c1eSAxel Dörfler fText->SetFontAndColor(&font, B_FONT_ALL, &textColor);
10677a96554cSlooncraz fText->SetViewColor(viewColor);
10687a96554cSlooncraz fText->SetLowColor(viewColor);
10693a3f6c1eSAxel Dörfler }
10703a3f6c1eSAxel Dörfler
10713a3f6c1eSAxel Dörfler
10723a3f6c1eSAxel Dörfler void
_CommitValue()1073ffe72abdSAxel Dörfler BTextControl::_CommitValue()
10749cb2dbe2SMarc Flerackers {
10759cb2dbe2SMarc Flerackers }
1076058691d4SStefano Ceccherini
1077058691d4SStefano Ceccherini
1078058691d4SStefano Ceccherini void
_InitData(const char * label,const BMessage * archive)10795c47e35eSAlex Wilson BTextControl::_InitData(const char* label, const BMessage* archive)
10809cb2dbe2SMarc Flerackers {
10819cb2dbe2SMarc Flerackers BRect bounds(Bounds());
10829cb2dbe2SMarc Flerackers
10839cb2dbe2SMarc Flerackers fText = NULL;
10849cb2dbe2SMarc Flerackers fModificationMessage = NULL;
10859cb2dbe2SMarc Flerackers fLabelAlign = B_ALIGN_LEFT;
10869cb2dbe2SMarc Flerackers fDivider = 0.0f;
1087349c911eSStephan Aßmus fLayoutData = new LayoutData(bounds.Width(), bounds.Height());
10889cb2dbe2SMarc Flerackers
10899cb2dbe2SMarc Flerackers int32 flags = 0;
10909cb2dbe2SMarc Flerackers
1091918a22d9SDarkWyrm BFont font(be_plain_font);
10929cb2dbe2SMarc Flerackers
1093ffe72abdSAxel Dörfler if (!archive || !archive->HasString("_fname"))
1094058691d4SStefano Ceccherini flags |= B_FONT_FAMILY_AND_STYLE;
10959cb2dbe2SMarc Flerackers
1096ffe72abdSAxel Dörfler if (!archive || !archive->HasFloat("_fflt"))
1097058691d4SStefano Ceccherini flags |= B_FONT_SIZE;
10989cb2dbe2SMarc Flerackers
10999cb2dbe2SMarc Flerackers if (flags != 0)
11009cb2dbe2SMarc Flerackers SetFont(&font, flags);
11019cb2dbe2SMarc Flerackers
1102f4664459SJohn Scipione if (label != NULL)
11032e6a5805SStephan Aßmus fDivider = floorf(bounds.Width() / 2.0f);
110413d147b1SAdrien Destugues
110513d147b1SAdrien Destugues fLook = 0;
11065c47e35eSAlex Wilson }
11075c47e35eSAlex Wilson
11085c47e35eSAlex Wilson
11095c47e35eSAlex Wilson void
_InitText(const char * initialText,const BMessage * archive)11105c47e35eSAlex Wilson BTextControl::_InitText(const char* initialText, const BMessage* archive)
11115c47e35eSAlex Wilson {
1112ffe72abdSAxel Dörfler if (archive)
1113b8872c02SStephan Aßmus fText = static_cast<BPrivate::_BTextInput_*>(FindView("_input_"));
1114991c062fSAxel Dörfler
1115991c062fSAxel Dörfler if (fText == NULL) {
11165c47e35eSAlex Wilson BRect bounds(Bounds());
1117ee2a3473SStephan Aßmus BRect frame(fDivider, bounds.top, bounds.right, bounds.bottom);
1118105644bfSAxel Dörfler // we are stroking the frame around the text view, which
11192e6a5805SStephan Aßmus // is 2 pixels wide
1120349c911eSStephan Aßmus frame.InsetBy(kFrameMargin, kFrameMargin);
1121111b4fbcSStefano Ceccherini BRect textRect(frame.OffsetToCopy(B_ORIGIN));
11229cb2dbe2SMarc Flerackers
1123b8872c02SStephan Aßmus fText = new BPrivate::_BTextInput_(frame, textRect,
11245c47e35eSAlex Wilson B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS
11255c47e35eSAlex Wilson | (Flags() & B_NAVIGABLE));
11269cb2dbe2SMarc Flerackers AddChild(fText);
11279cb2dbe2SMarc Flerackers
1128455d1c46SAxel Dörfler SetText(initialText);
11299cb2dbe2SMarc Flerackers fText->SetAlignment(B_ALIGN_LEFT);
11309cb2dbe2SMarc Flerackers }
11315c47e35eSAlex Wilson
11325c47e35eSAlex Wilson // Although this is not strictly initializing the text view,
11335c47e35eSAlex Wilson // it cannot be done while fText is NULL, so it resides here.
11345c47e35eSAlex Wilson if (archive) {
11355c47e35eSAlex Wilson int32 labelAlignment = B_ALIGN_LEFT;
11365c47e35eSAlex Wilson int32 textAlignment = B_ALIGN_LEFT;
11375c47e35eSAlex Wilson
11385c47e35eSAlex Wilson status_t err = B_OK;
11395c47e35eSAlex Wilson if (archive->HasInt32("_a_label"))
11405c47e35eSAlex Wilson err = archive->FindInt32("_a_label", &labelAlignment);
11415c47e35eSAlex Wilson
11425c47e35eSAlex Wilson if (err == B_OK && archive->HasInt32("_a_text"))
11435c47e35eSAlex Wilson err = archive->FindInt32("_a_text", &textAlignment);
11445c47e35eSAlex Wilson
11455c47e35eSAlex Wilson SetAlignment((alignment)labelAlignment, (alignment)textAlignment);
11465c47e35eSAlex Wilson }
114750960935SClemens Zeidler
114850960935SClemens Zeidler uint32 navigableFlags = Flags() & B_NAVIGABLE;
114950960935SClemens Zeidler if (navigableFlags != 0)
115050960935SClemens Zeidler BView::SetFlags(Flags() & ~B_NAVIGABLE);
11519cb2dbe2SMarc Flerackers }
11529ecf9d1cSIngo Weinhold
11539ecf9d1cSIngo Weinhold
11549ecf9d1cSIngo Weinhold void
_ValidateLayout()11559ecf9d1cSIngo Weinhold BTextControl::_ValidateLayout()
11569ecf9d1cSIngo Weinhold {
115793ba577cSStephan Aßmus CALLED();
115893ba577cSStephan Aßmus
1159349c911eSStephan Aßmus _ValidateLayoutData();
11609ecf9d1cSIngo Weinhold
1161349c911eSStephan Aßmus ResizeTo(Bounds().Width(), fLayoutData->min.height);
11629ecf9d1cSIngo Weinhold
1163a431f44bSStephan Aßmus _LayoutTextView();
11649ecf9d1cSIngo Weinhold }
11659ecf9d1cSIngo Weinhold
11669ecf9d1cSIngo Weinhold
11679ecf9d1cSIngo Weinhold void
_LayoutTextView()1168a431f44bSStephan Aßmus BTextControl::_LayoutTextView()
1169a431f44bSStephan Aßmus {
117093ba577cSStephan Aßmus CALLED();
117193ba577cSStephan Aßmus
117209d87d91SAxel Dörfler BRect frame;
117309d87d91SAxel Dörfler if (fLayoutData->text_view_layout_item != NULL) {
117409d87d91SAxel Dörfler frame = fLayoutData->text_view_layout_item->FrameInParent();
117509d87d91SAxel Dörfler } else {
117609d87d91SAxel Dörfler frame = Bounds();
1177a431f44bSStephan Aßmus frame.left = fDivider;
117809d87d91SAxel Dörfler }
117909d87d91SAxel Dörfler
1180a431f44bSStephan Aßmus // we are stroking the frame around the text view, which
1181a431f44bSStephan Aßmus // is 2 pixels wide
118284b7e122SStephan Aßmus frame.InsetBy(kFrameMargin, kFrameMargin);
1183a431f44bSStephan Aßmus fText->MoveTo(frame.left, frame.top);
1184a431f44bSStephan Aßmus fText->ResizeTo(frame.Width(), frame.Height());
118593ba577cSStephan Aßmus
118693ba577cSStephan Aßmus TRACE("width: %.2f, height: %.2f\n", Frame().Width(), Frame().Height());
118793ba577cSStephan Aßmus TRACE("fDivider: %.2f\n", fDivider);
118893ba577cSStephan Aßmus TRACE("fText frame: (%.2f, %.2f, %.2f, %.2f)\n",
118993ba577cSStephan Aßmus frame.left, frame.top, frame.right, frame.bottom);
1190a431f44bSStephan Aßmus }
1191a431f44bSStephan Aßmus
1192a431f44bSStephan Aßmus
1193a431f44bSStephan Aßmus void
_UpdateFrame()11949ecf9d1cSIngo Weinhold BTextControl::_UpdateFrame()
11959ecf9d1cSIngo Weinhold {
1196349c911eSStephan Aßmus CALLED();
1197349c911eSStephan Aßmus
119809d87d91SAxel Dörfler if (fLayoutData->text_view_layout_item != NULL) {
1199349c911eSStephan Aßmus BRect textFrame = fLayoutData->text_view_layout_item->Frame();
120009d87d91SAxel Dörfler BRect labelFrame;
120109d87d91SAxel Dörfler if (fLayoutData->label_layout_item != NULL)
120209d87d91SAxel Dörfler labelFrame = fLayoutData->label_layout_item->Frame();
120309d87d91SAxel Dörfler
120409d87d91SAxel Dörfler BRect frame;
120509d87d91SAxel Dörfler if (labelFrame.IsValid()) {
120609d87d91SAxel Dörfler frame = textFrame | labelFrame;
1207349c911eSStephan Aßmus
1208349c911eSStephan Aßmus // update divider
120909d87d91SAxel Dörfler fDivider = fabs(textFrame.left - labelFrame.left);
121009d87d91SAxel Dörfler } else {
121109d87d91SAxel Dörfler frame = textFrame;
121209d87d91SAxel Dörfler fDivider = 0;
121309d87d91SAxel Dörfler }
1214349c911eSStephan Aßmus
1215b11edca4SJohn Scipione // update our frame
121609d87d91SAxel Dörfler MoveTo(frame.left, frame.top);
1217b11edca4SJohn Scipione BSize oldSize(Bounds().Size());
121809d87d91SAxel Dörfler ResizeTo(frame.Width(), frame.Height());
1219b11edca4SJohn Scipione BSize newSize(Bounds().Size());
1220349c911eSStephan Aßmus
1221349c911eSStephan Aßmus // If the size changes, ResizeTo() will trigger a relayout, otherwise
1222349c911eSStephan Aßmus // we need to do that explicitly.
1223349c911eSStephan Aßmus if (newSize != oldSize)
1224349c911eSStephan Aßmus Relayout();
12259ecf9d1cSIngo Weinhold }
12269ecf9d1cSIngo Weinhold }
12279ecf9d1cSIngo Weinhold
12289ecf9d1cSIngo Weinhold
1229349c911eSStephan Aßmus void
_ValidateLayoutData()1230349c911eSStephan Aßmus BTextControl::_ValidateLayoutData()
1231349c911eSStephan Aßmus {
1232349c911eSStephan Aßmus CALLED();
1233349c911eSStephan Aßmus
1234349c911eSStephan Aßmus if (fLayoutData->valid)
1235349c911eSStephan Aßmus return;
1236349c911eSStephan Aßmus
1237349c911eSStephan Aßmus // cache font height
1238349c911eSStephan Aßmus font_height& fh = fLayoutData->font_info;
1239349c911eSStephan Aßmus GetFontHeight(&fh);
1240349c911eSStephan Aßmus
124160370b9aSJohn Scipione const char* label = Label();
124260370b9aSJohn Scipione if (label != NULL) {
124360370b9aSJohn Scipione fLayoutData->label_width = ceilf(StringWidth(label));
1244349c911eSStephan Aßmus fLayoutData->label_height = ceilf(fh.ascent) + ceilf(fh.descent);
1245349c911eSStephan Aßmus } else {
1246349c911eSStephan Aßmus fLayoutData->label_width = 0;
1247349c911eSStephan Aßmus fLayoutData->label_height = 0;
1248349c911eSStephan Aßmus }
1249349c911eSStephan Aßmus
1250349c911eSStephan Aßmus // compute the minimal divider
1251349c911eSStephan Aßmus float divider = 0;
125209d87d91SAxel Dörfler if (fLayoutData->label_width > 0) {
125309d87d91SAxel Dörfler divider = fLayoutData->label_width
125409d87d91SAxel Dörfler + be_control_look->DefaultLabelSpacing();
125509d87d91SAxel Dörfler }
1256349c911eSStephan Aßmus
1257349c911eSStephan Aßmus // If we shan't do real layout, we let the current divider take influence.
1258349c911eSStephan Aßmus if (!(Flags() & B_SUPPORTS_LAYOUT))
1259349c911eSStephan Aßmus divider = max_c(divider, fDivider);
1260349c911eSStephan Aßmus
1261349c911eSStephan Aßmus // get the minimal (== preferred) text view size
1262349c911eSStephan Aßmus fLayoutData->text_view_min = fText->MinSize();
1263349c911eSStephan Aßmus
1264349c911eSStephan Aßmus TRACE("text view min width: %.2f\n", fLayoutData->text_view_min.width);
1265349c911eSStephan Aßmus
1266349c911eSStephan Aßmus // compute our minimal (== preferred) size
1267349c911eSStephan Aßmus BSize min(fLayoutData->text_view_min);
1268349c911eSStephan Aßmus min.width += 2 * kFrameMargin;
1269349c911eSStephan Aßmus min.height += 2 * kFrameMargin;
1270349c911eSStephan Aßmus
1271349c911eSStephan Aßmus if (divider > 0)
1272349c911eSStephan Aßmus min.width += divider;
1273b11edca4SJohn Scipione
1274349c911eSStephan Aßmus if (fLayoutData->label_height > min.height)
1275349c911eSStephan Aßmus min.height = fLayoutData->label_height;
1276349c911eSStephan Aßmus
1277349c911eSStephan Aßmus fLayoutData->min = min;
1278349c911eSStephan Aßmus
1279349c911eSStephan Aßmus fLayoutData->valid = true;
1280c944d11fSStephan Aßmus ResetLayoutInvalidation();
1281349c911eSStephan Aßmus
1282349c911eSStephan Aßmus TRACE("width: %.2f, height: %.2f\n", min.width, min.height);
1283349c911eSStephan Aßmus }
1284349c911eSStephan Aßmus
1285349c911eSStephan Aßmus
1286b11edca4SJohn Scipione // #pragma mark - BTextControl::LabelLayoutItem
12879ecf9d1cSIngo Weinhold
12889ecf9d1cSIngo Weinhold
LabelLayoutItem(BTextControl * parent)12899ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::LabelLayoutItem(BTextControl* parent)
12905c47e35eSAlex Wilson :
12915c47e35eSAlex Wilson fParent(parent),
12929ecf9d1cSIngo Weinhold fFrame()
12939ecf9d1cSIngo Weinhold {
12949ecf9d1cSIngo Weinhold }
12959ecf9d1cSIngo Weinhold
12969ecf9d1cSIngo Weinhold
LabelLayoutItem(BMessage * from)12975c47e35eSAlex Wilson BTextControl::LabelLayoutItem::LabelLayoutItem(BMessage* from)
12985c47e35eSAlex Wilson :
12995c47e35eSAlex Wilson BAbstractLayoutItem(from),
13005c47e35eSAlex Wilson fParent(NULL),
13015c47e35eSAlex Wilson fFrame()
13025c47e35eSAlex Wilson {
13035c47e35eSAlex Wilson from->FindRect(kFrameField, &fFrame);
13045c47e35eSAlex Wilson }
13055c47e35eSAlex Wilson
13065c47e35eSAlex Wilson
13079ecf9d1cSIngo Weinhold bool
IsVisible()13089ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::IsVisible()
13099ecf9d1cSIngo Weinhold {
13109ecf9d1cSIngo Weinhold return !fParent->IsHidden(fParent);
13119ecf9d1cSIngo Weinhold }
13129ecf9d1cSIngo Weinhold
13139ecf9d1cSIngo Weinhold
13149ecf9d1cSIngo Weinhold void
SetVisible(bool visible)13159ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::SetVisible(bool visible)
13169ecf9d1cSIngo Weinhold {
13179ecf9d1cSIngo Weinhold // not allowed
13189ecf9d1cSIngo Weinhold }
13199ecf9d1cSIngo Weinhold
13209ecf9d1cSIngo Weinhold
13219ecf9d1cSIngo Weinhold BRect
Frame()13229ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::Frame()
13239ecf9d1cSIngo Weinhold {
13249ecf9d1cSIngo Weinhold return fFrame;
13259ecf9d1cSIngo Weinhold }
13269ecf9d1cSIngo Weinhold
13279ecf9d1cSIngo Weinhold
13289ecf9d1cSIngo Weinhold void
SetFrame(BRect frame)13299ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::SetFrame(BRect frame)
13309ecf9d1cSIngo Weinhold {
13319ecf9d1cSIngo Weinhold fFrame = frame;
13329ecf9d1cSIngo Weinhold fParent->_UpdateFrame();
13339ecf9d1cSIngo Weinhold }
13349ecf9d1cSIngo Weinhold
13359ecf9d1cSIngo Weinhold
13365c47e35eSAlex Wilson void
SetParent(BTextControl * parent)13375c47e35eSAlex Wilson BTextControl::LabelLayoutItem::SetParent(BTextControl* parent)
13385c47e35eSAlex Wilson {
13395c47e35eSAlex Wilson fParent = parent;
13405c47e35eSAlex Wilson }
13415c47e35eSAlex Wilson
13425c47e35eSAlex Wilson
13439ecf9d1cSIngo Weinhold BView*
View()13449ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::View()
13459ecf9d1cSIngo Weinhold {
13469ecf9d1cSIngo Weinhold return fParent;
13479ecf9d1cSIngo Weinhold }
13489ecf9d1cSIngo Weinhold
13499ecf9d1cSIngo Weinhold
13509ecf9d1cSIngo Weinhold BSize
BaseMinSize()13519ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BaseMinSize()
13529ecf9d1cSIngo Weinhold {
1353349c911eSStephan Aßmus fParent->_ValidateLayoutData();
1354349c911eSStephan Aßmus
1355349c911eSStephan Aßmus if (!fParent->Label())
13569ecf9d1cSIngo Weinhold return BSize(-1, -1);
13579ecf9d1cSIngo Weinhold
135809d87d91SAxel Dörfler return BSize(fParent->fLayoutData->label_width
135909d87d91SAxel Dörfler + be_control_look->DefaultLabelSpacing(),
1360349c911eSStephan Aßmus fParent->fLayoutData->label_height);
13619ecf9d1cSIngo Weinhold }
13629ecf9d1cSIngo Weinhold
13639ecf9d1cSIngo Weinhold
13649ecf9d1cSIngo Weinhold BSize
BaseMaxSize()13659ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BaseMaxSize()
13669ecf9d1cSIngo Weinhold {
13679ecf9d1cSIngo Weinhold return BaseMinSize();
13689ecf9d1cSIngo Weinhold }
13699ecf9d1cSIngo Weinhold
13709ecf9d1cSIngo Weinhold
13719ecf9d1cSIngo Weinhold BSize
BasePreferredSize()13729ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BasePreferredSize()
13739ecf9d1cSIngo Weinhold {
13749ecf9d1cSIngo Weinhold return BaseMinSize();
13759ecf9d1cSIngo Weinhold }
13769ecf9d1cSIngo Weinhold
13779ecf9d1cSIngo Weinhold
13789ecf9d1cSIngo Weinhold BAlignment
BaseAlignment()13799ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BaseAlignment()
13809ecf9d1cSIngo Weinhold {
13819ecf9d1cSIngo Weinhold return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
13829ecf9d1cSIngo Weinhold }
13839ecf9d1cSIngo Weinhold
13849ecf9d1cSIngo Weinhold
138509d87d91SAxel Dörfler BRect
FrameInParent() const138609d87d91SAxel Dörfler BTextControl::LabelLayoutItem::FrameInParent() const
138709d87d91SAxel Dörfler {
138809d87d91SAxel Dörfler return fFrame.OffsetByCopy(-fParent->Frame().left, -fParent->Frame().top);
138909d87d91SAxel Dörfler }
139009d87d91SAxel Dörfler
139109d87d91SAxel Dörfler
13925c47e35eSAlex Wilson status_t
Archive(BMessage * into,bool deep) const13935c47e35eSAlex Wilson BTextControl::LabelLayoutItem::Archive(BMessage* into, bool deep) const
13945c47e35eSAlex Wilson {
13955c47e35eSAlex Wilson BArchiver archiver(into);
13965c47e35eSAlex Wilson status_t err = BAbstractLayoutItem::Archive(into, deep);
13975c47e35eSAlex Wilson if (err == B_OK)
13985c47e35eSAlex Wilson err = into->AddRect(kFrameField, fFrame);
13995c47e35eSAlex Wilson
14005c47e35eSAlex Wilson return archiver.Finish(err);
14015c47e35eSAlex Wilson }
14025c47e35eSAlex Wilson
14035c47e35eSAlex Wilson
14045c47e35eSAlex Wilson BArchivable*
Instantiate(BMessage * from)14055c47e35eSAlex Wilson BTextControl::LabelLayoutItem::Instantiate(BMessage* from)
14065c47e35eSAlex Wilson {
14075c47e35eSAlex Wilson if (validate_instantiation(from, "BTextControl::LabelLayoutItem"))
14085c47e35eSAlex Wilson return new LabelLayoutItem(from);
14095c47e35eSAlex Wilson return NULL;
14105c47e35eSAlex Wilson }
14115c47e35eSAlex Wilson
14125c47e35eSAlex Wilson
1413b11edca4SJohn Scipione // #pragma mark - BTextControl::TextViewLayoutItem
14149ecf9d1cSIngo Weinhold
14159ecf9d1cSIngo Weinhold
TextViewLayoutItem(BTextControl * parent)14169ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::TextViewLayoutItem(BTextControl* parent)
14175c47e35eSAlex Wilson :
14185c47e35eSAlex Wilson fParent(parent),
14199ecf9d1cSIngo Weinhold fFrame()
14209ecf9d1cSIngo Weinhold {
1421349c911eSStephan Aßmus // by default the part right of the divider shall have an unlimited maximum
1422349c911eSStephan Aßmus // width
1423349c911eSStephan Aßmus SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
14249ecf9d1cSIngo Weinhold }
14259ecf9d1cSIngo Weinhold
14269ecf9d1cSIngo Weinhold
TextViewLayoutItem(BMessage * from)14275c47e35eSAlex Wilson BTextControl::TextViewLayoutItem::TextViewLayoutItem(BMessage* from)
14285c47e35eSAlex Wilson :
14295c47e35eSAlex Wilson BAbstractLayoutItem(from),
14305c47e35eSAlex Wilson fParent(NULL),
14315c47e35eSAlex Wilson fFrame()
14325c47e35eSAlex Wilson {
14335c47e35eSAlex Wilson from->FindRect(kFrameField, &fFrame);
14345c47e35eSAlex Wilson }
14355c47e35eSAlex Wilson
14365c47e35eSAlex Wilson
14379ecf9d1cSIngo Weinhold bool
IsVisible()14389ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::IsVisible()
14399ecf9d1cSIngo Weinhold {
14409ecf9d1cSIngo Weinhold return !fParent->IsHidden(fParent);
14419ecf9d1cSIngo Weinhold }
14429ecf9d1cSIngo Weinhold
14439ecf9d1cSIngo Weinhold
14449ecf9d1cSIngo Weinhold void
SetVisible(bool visible)14459ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::SetVisible(bool visible)
14469ecf9d1cSIngo Weinhold {
14479ecf9d1cSIngo Weinhold // not allowed
14489ecf9d1cSIngo Weinhold }
14499ecf9d1cSIngo Weinhold
14509ecf9d1cSIngo Weinhold
14519ecf9d1cSIngo Weinhold BRect
Frame()14529ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::Frame()
14539ecf9d1cSIngo Weinhold {
14549ecf9d1cSIngo Weinhold return fFrame;
14559ecf9d1cSIngo Weinhold }
14569ecf9d1cSIngo Weinhold
14579ecf9d1cSIngo Weinhold
14589ecf9d1cSIngo Weinhold void
SetFrame(BRect frame)14599ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::SetFrame(BRect frame)
14609ecf9d1cSIngo Weinhold {
14619ecf9d1cSIngo Weinhold fFrame = frame;
14629ecf9d1cSIngo Weinhold fParent->_UpdateFrame();
14639ecf9d1cSIngo Weinhold }
14649ecf9d1cSIngo Weinhold
14659ecf9d1cSIngo Weinhold
14665c47e35eSAlex Wilson void
SetParent(BTextControl * parent)14675c47e35eSAlex Wilson BTextControl::TextViewLayoutItem::SetParent(BTextControl* parent)
14685c47e35eSAlex Wilson {
14695c47e35eSAlex Wilson fParent = parent;
14705c47e35eSAlex Wilson }
14715c47e35eSAlex Wilson
14725c47e35eSAlex Wilson
14739ecf9d1cSIngo Weinhold BView*
View()14749ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::View()
14759ecf9d1cSIngo Weinhold {
14769ecf9d1cSIngo Weinhold return fParent;
14779ecf9d1cSIngo Weinhold }
14789ecf9d1cSIngo Weinhold
14799ecf9d1cSIngo Weinhold
14809ecf9d1cSIngo Weinhold BSize
BaseMinSize()14819ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BaseMinSize()
14829ecf9d1cSIngo Weinhold {
1483349c911eSStephan Aßmus fParent->_ValidateLayoutData();
14849ecf9d1cSIngo Weinhold
1485349c911eSStephan Aßmus BSize size = fParent->fLayoutData->text_view_min;
1486349c911eSStephan Aßmus size.width += 2 * kFrameMargin;
1487349c911eSStephan Aßmus size.height += 2 * kFrameMargin;
14889ecf9d1cSIngo Weinhold
14899ecf9d1cSIngo Weinhold return size;
14909ecf9d1cSIngo Weinhold }
14919ecf9d1cSIngo Weinhold
14929ecf9d1cSIngo Weinhold
14939ecf9d1cSIngo Weinhold BSize
BaseMaxSize()14949ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BaseMaxSize()
14959ecf9d1cSIngo Weinhold {
14969ecf9d1cSIngo Weinhold BSize size(BaseMinSize());
14979ecf9d1cSIngo Weinhold size.width = B_SIZE_UNLIMITED;
1498b11edca4SJohn Scipione
14999ecf9d1cSIngo Weinhold return size;
15009ecf9d1cSIngo Weinhold }
15019ecf9d1cSIngo Weinhold
15029ecf9d1cSIngo Weinhold
15039ecf9d1cSIngo Weinhold BSize
BasePreferredSize()15049ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BasePreferredSize()
15059ecf9d1cSIngo Weinhold {
15069ecf9d1cSIngo Weinhold BSize size(BaseMinSize());
15079ecf9d1cSIngo Weinhold // puh, no idea...
15089ecf9d1cSIngo Weinhold size.width = 100;
1509b11edca4SJohn Scipione
15109ecf9d1cSIngo Weinhold return size;
15119ecf9d1cSIngo Weinhold }
15129ecf9d1cSIngo Weinhold
15139ecf9d1cSIngo Weinhold
15149ecf9d1cSIngo Weinhold BAlignment
BaseAlignment()15159ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BaseAlignment()
15169ecf9d1cSIngo Weinhold {
15179ecf9d1cSIngo Weinhold return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
15189ecf9d1cSIngo Weinhold }
15199ecf9d1cSIngo Weinhold
15205c47e35eSAlex Wilson
152109d87d91SAxel Dörfler BRect
FrameInParent() const152209d87d91SAxel Dörfler BTextControl::TextViewLayoutItem::FrameInParent() const
152309d87d91SAxel Dörfler {
152409d87d91SAxel Dörfler return fFrame.OffsetByCopy(-fParent->Frame().left, -fParent->Frame().top);
152509d87d91SAxel Dörfler }
152609d87d91SAxel Dörfler
152709d87d91SAxel Dörfler
15285c47e35eSAlex Wilson status_t
Archive(BMessage * into,bool deep) const15295c47e35eSAlex Wilson BTextControl::TextViewLayoutItem::Archive(BMessage* into, bool deep) const
15305c47e35eSAlex Wilson {
15315c47e35eSAlex Wilson BArchiver archiver(into);
15325c47e35eSAlex Wilson status_t err = BAbstractLayoutItem::Archive(into, deep);
15335c47e35eSAlex Wilson if (err == B_OK)
15345c47e35eSAlex Wilson err = into->AddRect(kFrameField, fFrame);
15355c47e35eSAlex Wilson
15365c47e35eSAlex Wilson return archiver.Finish(err);
15375c47e35eSAlex Wilson }
15385c47e35eSAlex Wilson
15395c47e35eSAlex Wilson
15405c47e35eSAlex Wilson BArchivable*
Instantiate(BMessage * from)15415c47e35eSAlex Wilson BTextControl::TextViewLayoutItem::Instantiate(BMessage* from)
15425c47e35eSAlex Wilson {
15435c47e35eSAlex Wilson if (validate_instantiation(from, "BTextControl::TextViewLayoutItem"))
15445c47e35eSAlex Wilson return new TextViewLayoutItem(from);
1545b11edca4SJohn Scipione
15465c47e35eSAlex Wilson return NULL;
15475c47e35eSAlex Wilson }
15485c47e35eSAlex Wilson
15495c47e35eSAlex Wilson
1550466f2b8fSRene Gollent extern "C" void
B_IF_GCC_2(InvalidateLayout__12BTextControlb,_ZN12BTextControl16InvalidateLayoutEb)15518adaa6c5SJerome Duval B_IF_GCC_2(InvalidateLayout__12BTextControlb,
15528adaa6c5SJerome Duval _ZN12BTextControl16InvalidateLayoutEb)(BView* view, bool descendants)
1553466f2b8fSRene Gollent {
1554f6c8d242SRene Gollent perform_data_layout_invalidated data;
1555f6c8d242SRene Gollent data.descendants = descendants;
1556f6c8d242SRene Gollent
1557f6c8d242SRene Gollent view->Perform(PERFORM_CODE_LAYOUT_INVALIDATED, &data);
1558466f2b8fSRene Gollent }
1559