xref: /haiku/src/kits/interface/TextControl.cpp (revision ca9854451dd3266c6f098a006549c70f26f4b368)
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