xref: /haiku/src/kits/interface/TextControl.cpp (revision d9385a9d38cfb73714aa3939a928b7e952015dff)
1105644bfSAxel Dörfler /*
2*d9385a9dSJohn 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>
9*d9385a9dSJohn 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>
229ecf9d1cSIngo Weinhold #include <LayoutUtils.h>
23058691d4SStefano Ceccherini #include <Message.h>
242a30a9e9SRene Gollent #include <PropertyInfo.h>
25455d1c46SAxel Dörfler #include <Region.h>
2652a38012Sejakowatz #include <Window.h>
2752a38012Sejakowatz 
2839fbf550SOliver Tappe #include <binary_compatibility/Interface.h>
295c47e35eSAlex Wilson #include <binary_compatibility/Support.h>
3039fbf550SOliver Tappe 
3152a38012Sejakowatz #include "TextInput.h"
3252a38012Sejakowatz 
3352a38012Sejakowatz 
3493ba577cSStephan Aßmus //#define TRACE_TEXT_CONTROL
3593ba577cSStephan Aßmus #ifdef TRACE_TEXT_CONTROL
3673161598SJérôme Duval #	include <stdio.h>
3793ba577cSStephan Aßmus #	include <FunctionTracer.h>
3893ba577cSStephan Aßmus 	static int32 sFunctionDepth = -1;
39349c911eSStephan Aßmus #	define CALLED(x...)	FunctionTracer _ft("BTextControl", __FUNCTION__, \
4093ba577cSStephan Aßmus 							sFunctionDepth)
4193ba577cSStephan Aßmus #	define TRACE(x...)	{ BString _to; \
4293ba577cSStephan Aßmus 							_to.Append(' ', (sFunctionDepth + 1) * 2); \
4393ba577cSStephan Aßmus 							printf("%s", _to.String()); printf(x); }
4493ba577cSStephan Aßmus #else
4593ba577cSStephan Aßmus #	define CALLED(x...)
4693ba577cSStephan Aßmus #	define TRACE(x...)
4793ba577cSStephan Aßmus #endif
4893ba577cSStephan Aßmus 
4993ba577cSStephan Aßmus 
505c47e35eSAlex Wilson namespace {
515c47e35eSAlex Wilson 	const char* const kFrameField = "BTextControl:layoutitem:frame";
525c47e35eSAlex Wilson 	const char* const kTextViewItemField = "BTextControl:textViewItem";
535c47e35eSAlex Wilson 	const char* const kLabelItemField = "BMenuField:labelItem";
545c47e35eSAlex Wilson }
555c47e35eSAlex Wilson 
565c47e35eSAlex Wilson 
572a30a9e9SRene Gollent static property_info sPropertyList[] = {
582a30a9e9SRene Gollent 	{
592a30a9e9SRene Gollent 		"Value",
602a30a9e9SRene Gollent 		{ B_GET_PROPERTY, B_SET_PROPERTY },
612a30a9e9SRene Gollent 		{ B_DIRECT_SPECIFIER },
622a30a9e9SRene Gollent 		NULL, 0,
632a30a9e9SRene Gollent 		{ B_STRING_TYPE }
642a30a9e9SRene Gollent 	},
65346d1496SHumdinger 
66346d1496SHumdinger 	{ 0 }
672a30a9e9SRene Gollent };
682a30a9e9SRene Gollent 
692a30a9e9SRene Gollent 
709ecf9d1cSIngo Weinhold class BTextControl::LabelLayoutItem : public BAbstractLayoutItem {
719ecf9d1cSIngo Weinhold public:
729ecf9d1cSIngo Weinhold 								LabelLayoutItem(BTextControl* parent);
735c47e35eSAlex Wilson 								LabelLayoutItem(BMessage* from);
749ecf9d1cSIngo Weinhold 
759ecf9d1cSIngo Weinhold 	virtual	bool				IsVisible();
769ecf9d1cSIngo Weinhold 	virtual	void				SetVisible(bool visible);
779ecf9d1cSIngo Weinhold 
789ecf9d1cSIngo Weinhold 	virtual	BRect				Frame();
799ecf9d1cSIngo Weinhold 	virtual	void				SetFrame(BRect frame);
809ecf9d1cSIngo Weinhold 
815c47e35eSAlex Wilson 			void				SetParent(BTextControl* parent);
829ecf9d1cSIngo Weinhold 	virtual	BView*				View();
839ecf9d1cSIngo Weinhold 
849ecf9d1cSIngo Weinhold 	virtual	BSize				BaseMinSize();
859ecf9d1cSIngo Weinhold 	virtual	BSize				BaseMaxSize();
869ecf9d1cSIngo Weinhold 	virtual	BSize				BasePreferredSize();
879ecf9d1cSIngo Weinhold 	virtual	BAlignment			BaseAlignment();
889ecf9d1cSIngo Weinhold 
8909d87d91SAxel Dörfler 			BRect				FrameInParent() const;
9009d87d91SAxel Dörfler 
915c47e35eSAlex Wilson 	virtual status_t			Archive(BMessage* into, bool deep = true) const;
925c47e35eSAlex Wilson 	static	BArchivable*		Instantiate(BMessage* from);
9309d87d91SAxel Dörfler 
949ecf9d1cSIngo Weinhold private:
959ecf9d1cSIngo Weinhold 			BTextControl*		fParent;
969ecf9d1cSIngo Weinhold 			BRect				fFrame;
979ecf9d1cSIngo Weinhold };
989ecf9d1cSIngo Weinhold 
999ecf9d1cSIngo Weinhold 
1009ecf9d1cSIngo Weinhold class BTextControl::TextViewLayoutItem : public BAbstractLayoutItem {
1019ecf9d1cSIngo Weinhold public:
1029ecf9d1cSIngo Weinhold 								TextViewLayoutItem(BTextControl* parent);
1035c47e35eSAlex Wilson 								TextViewLayoutItem(BMessage* from);
1049ecf9d1cSIngo Weinhold 
1059ecf9d1cSIngo Weinhold 	virtual	bool				IsVisible();
1069ecf9d1cSIngo Weinhold 	virtual	void				SetVisible(bool visible);
1079ecf9d1cSIngo Weinhold 
1089ecf9d1cSIngo Weinhold 	virtual	BRect				Frame();
1099ecf9d1cSIngo Weinhold 	virtual	void				SetFrame(BRect frame);
1109ecf9d1cSIngo Weinhold 
1115c47e35eSAlex Wilson 			void				SetParent(BTextControl* parent);
1129ecf9d1cSIngo Weinhold 	virtual	BView*				View();
1139ecf9d1cSIngo Weinhold 
1149ecf9d1cSIngo Weinhold 	virtual	BSize				BaseMinSize();
1159ecf9d1cSIngo Weinhold 	virtual	BSize				BaseMaxSize();
1169ecf9d1cSIngo Weinhold 	virtual	BSize				BasePreferredSize();
1179ecf9d1cSIngo Weinhold 	virtual	BAlignment			BaseAlignment();
1189ecf9d1cSIngo Weinhold 
11909d87d91SAxel Dörfler 			BRect				FrameInParent() const;
12009d87d91SAxel Dörfler 
1215c47e35eSAlex Wilson 	virtual status_t			Archive(BMessage* into, bool deep = true) const;
1225c47e35eSAlex Wilson 	static	BArchivable*		Instantiate(BMessage* from);
1239ecf9d1cSIngo Weinhold private:
1249ecf9d1cSIngo Weinhold 			BTextControl*		fParent;
1259ecf9d1cSIngo Weinhold 			BRect				fFrame;
1269ecf9d1cSIngo Weinhold };
1279ecf9d1cSIngo Weinhold 
1289ecf9d1cSIngo Weinhold 
129349c911eSStephan Aßmus struct BTextControl::LayoutData {
130349c911eSStephan Aßmus 	LayoutData(float width, float height)
1315c47e35eSAlex Wilson 		:
1325c47e35eSAlex Wilson 		label_layout_item(NULL),
133349c911eSStephan Aßmus 		text_view_layout_item(NULL),
134349c911eSStephan Aßmus 		previous_width(width),
135349c911eSStephan Aßmus 		previous_height(height),
136349c911eSStephan Aßmus 		valid(false)
137349c911eSStephan Aßmus 	{
138349c911eSStephan Aßmus 	}
139349c911eSStephan Aßmus 
140349c911eSStephan Aßmus 	LabelLayoutItem*	label_layout_item;
141349c911eSStephan Aßmus 	TextViewLayoutItem*	text_view_layout_item;
142349c911eSStephan Aßmus 	float				previous_width;		// used in FrameResized() for
143349c911eSStephan Aßmus 	float				previous_height;	// invalidation
144349c911eSStephan Aßmus 	font_height			font_info;
145349c911eSStephan Aßmus 	float				label_width;
146349c911eSStephan Aßmus 	float				label_height;
147349c911eSStephan Aßmus 	BSize				min;
148349c911eSStephan Aßmus 	BSize				text_view_min;
149349c911eSStephan Aßmus 	bool				valid;
150349c911eSStephan Aßmus };
151349c911eSStephan Aßmus 
152349c911eSStephan Aßmus 
153349c911eSStephan Aßmus static const int32 kFrameMargin = 2;
154349c911eSStephan Aßmus static const int32 kLabelInputSpacing = 3;
155349c911eSStephan Aßmus 
156349c911eSStephan Aßmus 
157b11edca4SJohn Scipione // #pragma mark - BTextControl
158b11edca4SJohn Scipione 
159b11edca4SJohn Scipione 
16052a38012Sejakowatz BTextControl::BTextControl(BRect frame, const char* name, const char* label,
161f4664459SJohn Scipione 	const char* text, BMessage* message, uint32 resizeMask, uint32 flags)
1625c47e35eSAlex Wilson 	:
163f4664459SJohn Scipione 	BControl(frame, name, label, message, resizeMask, flags | B_FRAME_EVENTS)
16452a38012Sejakowatz {
1655c47e35eSAlex Wilson 	_InitData(label);
1665c47e35eSAlex Wilson 	_InitText(text);
1679ecf9d1cSIngo Weinhold 	_ValidateLayout();
1689ecf9d1cSIngo Weinhold }
16952a38012Sejakowatz 
170105644bfSAxel Dörfler 
1719ecf9d1cSIngo Weinhold BTextControl::BTextControl(const char* name, const char* label,
172991c062fSAxel Dörfler 	const char* text, BMessage* message, uint32 flags)
1735c47e35eSAlex Wilson 	:
1745c47e35eSAlex Wilson 	BControl(name, label, message, flags | B_FRAME_EVENTS)
1759ecf9d1cSIngo Weinhold {
1765c47e35eSAlex Wilson 	_InitData(label);
1775c47e35eSAlex Wilson 	_InitText(text);
1789ecf9d1cSIngo Weinhold 	_ValidateLayout();
1799ecf9d1cSIngo Weinhold }
180105644bfSAxel Dörfler 
181ffe72abdSAxel Dörfler 
182991c062fSAxel Dörfler BTextControl::BTextControl(const char* label, const char* text,
183991c062fSAxel Dörfler 	BMessage* message)
1845c47e35eSAlex Wilson 	:
1855c47e35eSAlex Wilson 	BControl(NULL, label, message,
18693ba577cSStephan Aßmus 		B_WILL_DRAW | B_NAVIGABLE | B_FRAME_EVENTS)
1879ecf9d1cSIngo Weinhold {
1885c47e35eSAlex Wilson 	_InitData(label);
1895c47e35eSAlex Wilson 	_InitText(text);
1909ecf9d1cSIngo Weinhold 	_ValidateLayout();
19152a38012Sejakowatz }
192058691d4SStefano Ceccherini 
193058691d4SStefano Ceccherini 
19452a38012Sejakowatz BTextControl::~BTextControl()
19552a38012Sejakowatz {
1969cb2dbe2SMarc Flerackers 	SetModificationMessage(NULL);
19753aaed9fSStephan Aßmus 	delete fLayoutData;
19852a38012Sejakowatz }
199058691d4SStefano Ceccherini 
200058691d4SStefano Ceccherini 
201f4664459SJohn Scipione //	#pragma mark - Archiving
202f4664459SJohn Scipione 
203f4664459SJohn Scipione 
204ffe72abdSAxel Dörfler BTextControl::BTextControl(BMessage* archive)
2055c47e35eSAlex Wilson 	:
2065c47e35eSAlex Wilson 	BControl(BUnarchiver::PrepareArchive(archive))
20752a38012Sejakowatz {
2085c47e35eSAlex Wilson 	BUnarchiver unarchiver(archive);
20952a38012Sejakowatz 
2105c47e35eSAlex Wilson 	_InitData(Label(), archive);
21152a38012Sejakowatz 
2125c47e35eSAlex Wilson 	if (!BUnarchiver::IsArchiveManaged(archive))
2135c47e35eSAlex Wilson 		_InitText(NULL, archive);
21452a38012Sejakowatz 
2155c47e35eSAlex Wilson 	status_t err = B_OK;
216ffe72abdSAxel Dörfler 	if (archive->HasFloat("_divide"))
2175c47e35eSAlex Wilson 		err = archive->FindFloat("_divide", &fDivider);
2189cb2dbe2SMarc Flerackers 
2195c47e35eSAlex Wilson 	if (err == B_OK && archive->HasMessage("_mod_msg")) {
220ffe72abdSAxel Dörfler 		BMessage* message = new BMessage;
2215c47e35eSAlex Wilson 		err = archive->FindMessage("_mod_msg", message);
222ffe72abdSAxel Dörfler 		SetModificationMessage(message);
2239cb2dbe2SMarc Flerackers 	}
2245c47e35eSAlex Wilson 
2255c47e35eSAlex Wilson 	unarchiver.Finish(err);
22652a38012Sejakowatz }
227058691d4SStefano Ceccherini 
228058691d4SStefano Ceccherini 
229058691d4SStefano Ceccherini BArchivable*
230058691d4SStefano Ceccherini BTextControl::Instantiate(BMessage* archive)
23152a38012Sejakowatz {
2329cb2dbe2SMarc Flerackers 	if (validate_instantiation(archive, "BTextControl"))
2339cb2dbe2SMarc Flerackers 		return new BTextControl(archive);
234991c062fSAxel Dörfler 
23552a38012Sejakowatz 	return NULL;
23652a38012Sejakowatz }
237058691d4SStefano Ceccherini 
238058691d4SStefano Ceccherini 
239058691d4SStefano Ceccherini status_t
240058691d4SStefano Ceccherini BTextControl::Archive(BMessage* data, bool deep) const
24152a38012Sejakowatz {
2425c47e35eSAlex Wilson 	BArchiver archiver(data);
243f4664459SJohn Scipione 	status_t result = BControl::Archive(data, deep);
24452a38012Sejakowatz 
245f4664459SJohn Scipione 	alignment labelAlignment;
246f4664459SJohn Scipione 	alignment textAlignment;
247f4664459SJohn Scipione 	if (result == B_OK)
248058691d4SStefano Ceccherini 		GetAlignment(&labelAlignment, &textAlignment);
2499cb2dbe2SMarc Flerackers 
250f4664459SJohn Scipione 	if (result == B_OK)
251f4664459SJohn Scipione 		result = data->AddInt32("_a_label", labelAlignment);
2529cb2dbe2SMarc Flerackers 
253f4664459SJohn Scipione 	if (result == B_OK)
254f4664459SJohn Scipione 		result = data->AddInt32("_a_text", textAlignment);
2559cb2dbe2SMarc Flerackers 
256f4664459SJohn Scipione 	if (result == B_OK)
257f4664459SJohn Scipione 		result = data->AddFloat("_divide", Divider());
258f4664459SJohn Scipione 
259f4664459SJohn Scipione 	if (result == B_OK && ModificationMessage() != NULL)
260f4664459SJohn Scipione 		result = data->AddMessage("_mod_msg", ModificationMessage());
261f4664459SJohn Scipione 
262f4664459SJohn Scipione 	return archiver.Finish(result);
2635c47e35eSAlex Wilson }
2645c47e35eSAlex Wilson 
2655c47e35eSAlex Wilson 
2665c47e35eSAlex Wilson status_t
2675c47e35eSAlex Wilson BTextControl::AllArchived(BMessage* into) const
2685c47e35eSAlex Wilson {
2695c47e35eSAlex Wilson 	BArchiver archiver(into);
2705c47e35eSAlex Wilson 	status_t err = B_OK;
2715c47e35eSAlex Wilson 
2725c47e35eSAlex Wilson 	if (archiver.IsArchived(fLayoutData->text_view_layout_item)) {
2735c47e35eSAlex Wilson 		err = archiver.AddArchivable(kTextViewItemField,
2745c47e35eSAlex Wilson 			fLayoutData->text_view_layout_item);
2755c47e35eSAlex Wilson 	}
2765c47e35eSAlex Wilson 
2775c47e35eSAlex Wilson 	if (err == B_OK && archiver.IsArchived(fLayoutData->label_layout_item)) {
2785c47e35eSAlex Wilson 		err = archiver.AddArchivable(kLabelItemField,
2795c47e35eSAlex Wilson 			fLayoutData->label_layout_item);
2805c47e35eSAlex Wilson 	}
2815c47e35eSAlex Wilson 
2825c47e35eSAlex Wilson 	return err;
2835c47e35eSAlex Wilson }
2845c47e35eSAlex Wilson 
2855c47e35eSAlex Wilson 
2865c47e35eSAlex Wilson status_t
2875c47e35eSAlex Wilson BTextControl::AllUnarchived(const BMessage* from)
2885c47e35eSAlex Wilson {
2895c47e35eSAlex Wilson 	status_t err;
2905c47e35eSAlex Wilson 	if ((err = BControl::AllUnarchived(from)) != B_OK)
2915c47e35eSAlex Wilson 		return err;
2925c47e35eSAlex Wilson 
2935c47e35eSAlex Wilson 	_InitText(NULL, from);
2945c47e35eSAlex Wilson 
2955c47e35eSAlex Wilson 	BUnarchiver unarchiver(from);
2965c47e35eSAlex Wilson 	if (unarchiver.IsInstantiated(kTextViewItemField)) {
2975c47e35eSAlex Wilson 		err = unarchiver.FindObject(kTextViewItemField,
2985c47e35eSAlex Wilson 			BUnarchiver::B_DONT_ASSUME_OWNERSHIP,
2995c47e35eSAlex Wilson 			fLayoutData->text_view_layout_item);
3005c47e35eSAlex Wilson 
3015c47e35eSAlex Wilson 		if (err == B_OK)
3025c47e35eSAlex Wilson 			fLayoutData->text_view_layout_item->SetParent(this);
3035c47e35eSAlex Wilson 		else
3045c47e35eSAlex Wilson 			return err;
3055c47e35eSAlex Wilson 	}
3065c47e35eSAlex Wilson 
3075c47e35eSAlex Wilson 	if (unarchiver.IsInstantiated(kLabelItemField)) {
3085c47e35eSAlex Wilson 		err = unarchiver.FindObject(kLabelItemField,
3095c47e35eSAlex Wilson 			BUnarchiver::B_DONT_ASSUME_OWNERSHIP,
3105c47e35eSAlex Wilson 			fLayoutData->label_layout_item);
3115c47e35eSAlex Wilson 
3125c47e35eSAlex Wilson 		if (err == B_OK)
3135c47e35eSAlex Wilson 			fLayoutData->label_layout_item->SetParent(this);
3145c47e35eSAlex Wilson 	}
3155c47e35eSAlex Wilson 	return err;
31652a38012Sejakowatz }
317058691d4SStefano Ceccherini 
318058691d4SStefano Ceccherini 
319f4664459SJohn Scipione //	#pragma mark - Hook methods
320f4664459SJohn Scipione 
321f4664459SJohn Scipione 
322058691d4SStefano Ceccherini void
323f4664459SJohn Scipione BTextControl::AllAttached()
32452a38012Sejakowatz {
325f4664459SJohn Scipione 	BControl::AllAttached();
32652a38012Sejakowatz }
327058691d4SStefano Ceccherini 
328058691d4SStefano Ceccherini 
329058691d4SStefano Ceccherini void
330f4664459SJohn Scipione BTextControl::AllDetached()
33113d147b1SAdrien Destugues {
332f4664459SJohn Scipione 	BControl::AllDetached();
33352a38012Sejakowatz }
334058691d4SStefano Ceccherini 
335058691d4SStefano Ceccherini 
336058691d4SStefano Ceccherini void
337058691d4SStefano Ceccherini BTextControl::AttachedToWindow()
33852a38012Sejakowatz {
33952a38012Sejakowatz 	BControl::AttachedToWindow();
34052a38012Sejakowatz 
34179c35b39SAxel Dörfler 	_UpdateTextViewColors(IsEnabled());
3423a3f6c1eSAxel Dörfler 	fText->MakeEditable(IsEnabled());
34352a38012Sejakowatz }
344058691d4SStefano Ceccherini 
345058691d4SStefano Ceccherini 
346058691d4SStefano Ceccherini void
347058691d4SStefano Ceccherini BTextControl::DetachedFromWindow()
34852a38012Sejakowatz {
34952a38012Sejakowatz 	BControl::DetachedFromWindow();
35052a38012Sejakowatz }
351058691d4SStefano Ceccherini 
352058691d4SStefano Ceccherini 
353058691d4SStefano Ceccherini void
354f4664459SJohn Scipione BTextControl::Draw(BRect updateRect)
35552a38012Sejakowatz {
356f4664459SJohn Scipione 	bool enabled = IsEnabled();
357f4664459SJohn Scipione 	bool active = fText->IsFocus() && Window()->IsActive();
358f4664459SJohn Scipione 
359f4664459SJohn Scipione 	BRect rect = fText->Frame();
360f4664459SJohn Scipione 	rect.InsetBy(-2, -2);
361f4664459SJohn Scipione 
3627a96554cSlooncraz 	rgb_color base = ViewColor();
363f4664459SJohn Scipione 	uint32 flags = fLook;
364f4664459SJohn Scipione 	if (!enabled)
365f4664459SJohn Scipione 		flags |= BControlLook::B_DISABLED;
366f4664459SJohn Scipione 
367f4664459SJohn Scipione 	if (active)
368f4664459SJohn Scipione 		flags |= BControlLook::B_FOCUSED;
369f4664459SJohn Scipione 
370f4664459SJohn Scipione 	be_control_look->DrawTextControlBorder(this, rect, updateRect, base,
371f4664459SJohn Scipione 		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 
3818b902d94SJohn Scipione 		// erase the is control flag before drawing the label so that the label
3828b902d94SJohn Scipione 		// will get drawn using B_PANEL_TEXT_COLOR
3838b902d94SJohn Scipione 		flags &= ~BControlLook::B_IS_CONTROL;
3848b902d94SJohn Scipione 
385f4664459SJohn Scipione 		be_control_look->DrawLabel(this, Label(), rect, updateRect,
386f4664459SJohn Scipione 			base, flags, BAlignment(fLabelAlign, B_ALIGN_MIDDLE));
387f4664459SJohn Scipione 	}
38852a38012Sejakowatz }
389058691d4SStefano Ceccherini 
390058691d4SStefano Ceccherini 
391058691d4SStefano Ceccherini void
392058691d4SStefano Ceccherini BTextControl::FrameMoved(BPoint newPosition)
39352a38012Sejakowatz {
39452a38012Sejakowatz 	BControl::FrameMoved(newPosition);
39552a38012Sejakowatz }
396058691d4SStefano Ceccherini 
397058691d4SStefano Ceccherini 
398058691d4SStefano Ceccherini void
399ffe72abdSAxel Dörfler BTextControl::FrameResized(float width, float height)
40052a38012Sejakowatz {
40193ba577cSStephan Aßmus 	CALLED();
40293ba577cSStephan Aßmus 
403ffe72abdSAxel Dörfler 	BControl::FrameResized(width, height);
404ffe72abdSAxel Dörfler 
405349c911eSStephan Aßmus 	// TODO: this causes flickering still...
406349c911eSStephan Aßmus 
407ffe72abdSAxel Dörfler 	// changes in width
408ffe72abdSAxel Dörfler 
409ffe72abdSAxel Dörfler 	BRect bounds = Bounds();
410ffe72abdSAxel Dörfler 
411349c911eSStephan Aßmus 	if (bounds.Width() > fLayoutData->previous_width) {
412ffe72abdSAxel Dörfler 		// invalidate the region between the old and the new right border
413ffe72abdSAxel Dörfler 		BRect rect = bounds;
414349c911eSStephan Aßmus 		rect.left += fLayoutData->previous_width - kFrameMargin;
415ffe72abdSAxel Dörfler 		rect.right--;
416ffe72abdSAxel Dörfler 		Invalidate(rect);
417349c911eSStephan Aßmus 	} else if (bounds.Width() < fLayoutData->previous_width) {
418ffe72abdSAxel Dörfler 		// invalidate the region of the new right border
419ffe72abdSAxel Dörfler 		BRect rect = bounds;
420349c911eSStephan Aßmus 		rect.left = rect.right - kFrameMargin;
421ffe72abdSAxel Dörfler 		Invalidate(rect);
422ffe72abdSAxel Dörfler 	}
423ffe72abdSAxel Dörfler 
424ffe72abdSAxel Dörfler 	// changes in height
425ffe72abdSAxel Dörfler 
426349c911eSStephan Aßmus 	if (bounds.Height() > fLayoutData->previous_height) {
427ffe72abdSAxel Dörfler 		// invalidate the region between the old and the new bottom border
428ffe72abdSAxel Dörfler 		BRect rect = bounds;
429349c911eSStephan Aßmus 		rect.top += fLayoutData->previous_height - kFrameMargin;
430ffe72abdSAxel Dörfler 		rect.bottom--;
431ffe72abdSAxel Dörfler 		Invalidate(rect);
432349c911eSStephan Aßmus 		// invalidate label area
433349c911eSStephan Aßmus 		rect = bounds;
434349c911eSStephan Aßmus 		rect.right = fDivider;
435349c911eSStephan Aßmus 		Invalidate(rect);
436349c911eSStephan Aßmus 	} else if (bounds.Height() < fLayoutData->previous_height) {
437ffe72abdSAxel Dörfler 		// invalidate the region of the new bottom border
438ffe72abdSAxel Dörfler 		BRect rect = bounds;
439349c911eSStephan Aßmus 		rect.top = rect.bottom - kFrameMargin;
440349c911eSStephan Aßmus 		Invalidate(rect);
441349c911eSStephan Aßmus 		// invalidate label area
442349c911eSStephan Aßmus 		rect = bounds;
443349c911eSStephan Aßmus 		rect.right = fDivider;
444ffe72abdSAxel Dörfler 		Invalidate(rect);
445ffe72abdSAxel Dörfler 	}
446ffe72abdSAxel Dörfler 
447349c911eSStephan Aßmus 	fLayoutData->previous_width = bounds.Width();
448349c911eSStephan Aßmus 	fLayoutData->previous_height = bounds.Height();
44993ba577cSStephan Aßmus 
45093ba577cSStephan Aßmus 	TRACE("width: %.2f, height: %.2f\n", bounds.Width(), bounds.Height());
45152a38012Sejakowatz }
452058691d4SStefano Ceccherini 
453058691d4SStefano Ceccherini 
454f4664459SJohn Scipione status_t
455f4664459SJohn Scipione BTextControl::Invoke(BMessage* message)
456f4664459SJohn Scipione {
457f4664459SJohn Scipione 	return BControl::Invoke(message);
458f4664459SJohn Scipione }
459f4664459SJohn Scipione 
460f4664459SJohn Scipione 
461f4664459SJohn Scipione void
462f4664459SJohn Scipione BTextControl::LayoutInvalidated(bool descendants)
463f4664459SJohn Scipione {
464f4664459SJohn Scipione 	CALLED();
465f4664459SJohn Scipione 
466f4664459SJohn Scipione 	fLayoutData->valid = false;
467f4664459SJohn Scipione }
468f4664459SJohn Scipione 
469f4664459SJohn Scipione 
470f4664459SJohn Scipione void
471f4664459SJohn Scipione BTextControl::MessageReceived(BMessage* message)
472f4664459SJohn Scipione {
4737a96554cSlooncraz 	if (message->what == B_COLORS_UPDATED) {
4747a96554cSlooncraz 
4757a96554cSlooncraz 		if (message->HasColor(ui_color_name(B_PANEL_BACKGROUND_COLOR))
4767a96554cSlooncraz 			|| message->HasColor(ui_color_name(B_PANEL_TEXT_COLOR))
4777a96554cSlooncraz 			|| message->HasColor(ui_color_name(B_DOCUMENT_BACKGROUND_COLOR))
4787a96554cSlooncraz 			|| message->HasColor(ui_color_name(B_DOCUMENT_TEXT_COLOR))) {
4797a96554cSlooncraz 			_UpdateTextViewColors(IsEnabled());
4807a96554cSlooncraz 		}
4817a96554cSlooncraz 	}
4827a96554cSlooncraz 
483f4664459SJohn Scipione 	if (message->what == B_GET_PROPERTY || message->what == B_SET_PROPERTY) {
484f4664459SJohn Scipione 		BMessage reply(B_REPLY);
485f4664459SJohn Scipione 		bool handled = false;
486f4664459SJohn Scipione 
487f4664459SJohn Scipione 		BMessage specifier;
488f4664459SJohn Scipione 		int32 index;
489f4664459SJohn Scipione 		int32 form;
490f4664459SJohn Scipione 		const char* property;
491f4664459SJohn Scipione 		if (message->GetCurrentSpecifier(&index, &specifier, &form, &property) == B_OK) {
492f4664459SJohn Scipione 			if (strcmp(property, "Value") == 0) {
493f4664459SJohn Scipione 				if (message->what == B_GET_PROPERTY) {
494f4664459SJohn Scipione 					reply.AddString("result", fText->Text());
495f4664459SJohn Scipione 					handled = true;
496f4664459SJohn Scipione 				} else {
497f4664459SJohn Scipione 					const char* value = NULL;
498f4664459SJohn Scipione 					// B_SET_PROPERTY
499f4664459SJohn Scipione 					if (message->FindString("data", &value) == B_OK) {
500f4664459SJohn Scipione 						fText->SetText(value);
501f4664459SJohn Scipione 						reply.AddInt32("error", B_OK);
502f4664459SJohn Scipione 						handled = true;
503f4664459SJohn Scipione 					}
504f4664459SJohn Scipione 				}
505f4664459SJohn Scipione 			}
506f4664459SJohn Scipione 		}
507f4664459SJohn Scipione 
508f4664459SJohn Scipione 		if (handled) {
509f4664459SJohn Scipione 			message->SendReply(&reply);
510f4664459SJohn Scipione 			return;
511f4664459SJohn Scipione 		}
512f4664459SJohn Scipione 	}
513f4664459SJohn Scipione 
514f4664459SJohn Scipione 	BControl::MessageReceived(message);
515f4664459SJohn Scipione }
516f4664459SJohn Scipione 
517f4664459SJohn Scipione 
518f4664459SJohn Scipione void
519f4664459SJohn Scipione BTextControl::MouseDown(BPoint where)
520f4664459SJohn Scipione {
521f4664459SJohn Scipione 	if (!fText->IsFocus())
522f4664459SJohn Scipione 		fText->MakeFocus(true);
523f4664459SJohn Scipione }
524f4664459SJohn Scipione 
525f4664459SJohn Scipione 
526f4664459SJohn Scipione void
527f4664459SJohn Scipione BTextControl::MouseMoved(BPoint where, uint32 transit,
528f4664459SJohn Scipione 	const BMessage* dragMessage)
529f4664459SJohn Scipione {
530f4664459SJohn Scipione 	BControl::MouseMoved(where, transit, dragMessage);
531f4664459SJohn Scipione }
532f4664459SJohn Scipione 
533f4664459SJohn Scipione 
534f4664459SJohn Scipione void
535f4664459SJohn Scipione BTextControl::MouseUp(BPoint where)
536f4664459SJohn Scipione {
537f4664459SJohn Scipione 	BControl::MouseUp(where);
538f4664459SJohn Scipione }
539f4664459SJohn Scipione 
540f4664459SJohn Scipione 
541058691d4SStefano Ceccherini void
542058691d4SStefano Ceccherini BTextControl::WindowActivated(bool active)
54352a38012Sejakowatz {
5446d8d6cadSStephan Aßmus 	if (fText->IsFocus()) {
545dde10e45SStephan Aßmus 		// invalidate to remove/show focus indication
5462c5a8894SStephan Aßmus 		BRect rect = fText->Frame();
5472c5a8894SStephan Aßmus 		rect.InsetBy(-1, -1);
5486d8d6cadSStephan Aßmus 		Invalidate(rect);
549dde10e45SStephan Aßmus 
550dde10e45SStephan Aßmus 		// help out embedded text view which doesn't
551dde10e45SStephan Aßmus 		// get notified of this
552dde10e45SStephan Aßmus 		fText->Invalidate();
5536d8d6cadSStephan Aßmus 	}
55452a38012Sejakowatz }
555058691d4SStefano Ceccherini 
556058691d4SStefano Ceccherini 
557f4664459SJohn Scipione //	#pragma mark - Getters and Setters
558f4664459SJohn Scipione 
559f4664459SJohn Scipione 
560f4664459SJohn Scipione void
561f4664459SJohn Scipione BTextControl::SetText(const char* text)
562f4664459SJohn Scipione {
563f4664459SJohn Scipione 	if (InvokeKind() != B_CONTROL_INVOKED)
564f4664459SJohn Scipione 		return;
565f4664459SJohn Scipione 
566f4664459SJohn Scipione 	CALLED();
567f4664459SJohn Scipione 
568f4664459SJohn Scipione 	fText->SetText(text);
569f4664459SJohn Scipione 
570f4664459SJohn Scipione 	if (fText->IsFocus()) {
571f4664459SJohn Scipione 		fText->SetInitialText();
572f4664459SJohn Scipione 		fText->SelectAll();
573f4664459SJohn Scipione 	}
574f4664459SJohn Scipione 
575f4664459SJohn Scipione 	fText->Invalidate();
576f4664459SJohn Scipione }
577f4664459SJohn Scipione 
578f4664459SJohn Scipione 
579f4664459SJohn Scipione const char*
580f4664459SJohn Scipione BTextControl::Text() const
581f4664459SJohn Scipione {
582f4664459SJohn Scipione 	return fText->Text();
583f4664459SJohn Scipione }
584f4664459SJohn Scipione 
585f4664459SJohn Scipione 
5868bc3ecb0SAxel Dörfler int32
5878bc3ecb0SAxel Dörfler BTextControl::TextLength() const
5888bc3ecb0SAxel Dörfler {
5898bc3ecb0SAxel Dörfler 	return fText->TextLength();
5908bc3ecb0SAxel Dörfler }
5918bc3ecb0SAxel Dörfler 
5928bc3ecb0SAxel Dörfler 
593f4664459SJohn Scipione void
594f4664459SJohn Scipione BTextControl::MarkAsInvalid(bool invalid)
595f4664459SJohn Scipione {
596f4664459SJohn Scipione 	uint32 look = fLook;
597f4664459SJohn Scipione 
598f4664459SJohn Scipione 	if (invalid)
599f4664459SJohn Scipione 		fLook |= BControlLook::B_INVALID;
600f4664459SJohn Scipione 	else
601f4664459SJohn Scipione 		fLook &= ~BControlLook::B_INVALID;
602f4664459SJohn Scipione 
603f4664459SJohn Scipione 	if (look != fLook)
604f4664459SJohn Scipione 		Invalidate();
605f4664459SJohn Scipione }
606f4664459SJohn Scipione 
607f4664459SJohn Scipione 
608f4664459SJohn Scipione void
609f4664459SJohn Scipione BTextControl::SetValue(int32 value)
610f4664459SJohn Scipione {
611f4664459SJohn Scipione 	BControl::SetValue(value);
612f4664459SJohn Scipione }
613f4664459SJohn Scipione 
614f4664459SJohn Scipione 
615f4664459SJohn Scipione BTextView*
616f4664459SJohn Scipione BTextControl::TextView() const
617f4664459SJohn Scipione {
618f4664459SJohn Scipione 	return fText;
619f4664459SJohn Scipione }
620f4664459SJohn Scipione 
621f4664459SJohn Scipione 
622f4664459SJohn Scipione void
623f4664459SJohn Scipione BTextControl::SetModificationMessage(BMessage* message)
624f4664459SJohn Scipione {
625f4664459SJohn Scipione 	delete fModificationMessage;
626f4664459SJohn Scipione 	fModificationMessage = message;
627f4664459SJohn Scipione }
628f4664459SJohn Scipione 
629f4664459SJohn Scipione 
630f4664459SJohn Scipione BMessage*
631f4664459SJohn Scipione BTextControl::ModificationMessage() const
632f4664459SJohn Scipione {
633f4664459SJohn Scipione 	return fModificationMessage;
634f4664459SJohn Scipione }
635f4664459SJohn Scipione 
636f4664459SJohn Scipione 
637f4664459SJohn Scipione void
638f4664459SJohn Scipione BTextControl::SetAlignment(alignment labelAlignment, alignment textAlignment)
639f4664459SJohn Scipione {
640f4664459SJohn Scipione 	fText->SetAlignment(textAlignment);
641f4664459SJohn Scipione 
642f4664459SJohn Scipione 	if (fLabelAlign != labelAlignment) {
643f4664459SJohn Scipione 		fLabelAlign = labelAlignment;
644f4664459SJohn Scipione 		Invalidate();
645f4664459SJohn Scipione 	}
646f4664459SJohn Scipione }
647f4664459SJohn Scipione 
648f4664459SJohn Scipione 
649f4664459SJohn Scipione void
650f4664459SJohn Scipione BTextControl::GetAlignment(alignment* _label, alignment* _text) const
651f4664459SJohn Scipione {
652f4664459SJohn Scipione 	if (_label != NULL)
653f4664459SJohn Scipione 		*_label = fLabelAlign;
654f4664459SJohn Scipione 
655f4664459SJohn Scipione 	if (_text != NULL)
656f4664459SJohn Scipione 		*_text = fText->Alignment();
657f4664459SJohn Scipione }
658f4664459SJohn Scipione 
659f4664459SJohn Scipione 
660f4664459SJohn Scipione void
661f4664459SJohn Scipione BTextControl::SetDivider(float position)
662f4664459SJohn Scipione {
663f4664459SJohn Scipione 	fDivider = floorf(position + 0.5);
664f4664459SJohn Scipione 
665f4664459SJohn Scipione 	_LayoutTextView();
666f4664459SJohn Scipione 
667f4664459SJohn Scipione 	if (Window()) {
668f4664459SJohn Scipione 		fText->Invalidate();
669f4664459SJohn Scipione 		Invalidate();
670f4664459SJohn Scipione 	}
671f4664459SJohn Scipione }
672f4664459SJohn Scipione 
673f4664459SJohn Scipione 
674f4664459SJohn Scipione float
675f4664459SJohn Scipione BTextControl::Divider() const
676f4664459SJohn Scipione {
677f4664459SJohn Scipione 	return fDivider;
678f4664459SJohn Scipione }
679f4664459SJohn Scipione 
680f4664459SJohn Scipione 
681f4664459SJohn Scipione void
682f4664459SJohn Scipione BTextControl::MakeFocus(bool state)
683f4664459SJohn Scipione {
684f4664459SJohn Scipione 	if (state != fText->IsFocus()) {
685f4664459SJohn Scipione 		fText->MakeFocus(state);
686f4664459SJohn Scipione 
687f4664459SJohn Scipione 		if (state)
688f4664459SJohn Scipione 			fText->SelectAll();
689f4664459SJohn Scipione 	}
690f4664459SJohn Scipione }
691f4664459SJohn Scipione 
692f4664459SJohn Scipione 
693f4664459SJohn Scipione void
694f4664459SJohn Scipione BTextControl::SetEnabled(bool enable)
695f4664459SJohn Scipione {
696f4664459SJohn Scipione 	if (IsEnabled() == enable)
697f4664459SJohn Scipione 		return;
698f4664459SJohn Scipione 
699f4664459SJohn Scipione 	if (Window() != NULL) {
700f4664459SJohn Scipione 		fText->MakeEditable(enable);
701f4664459SJohn Scipione 		if (enable)
702f4664459SJohn Scipione 			fText->SetFlags(fText->Flags() | B_NAVIGABLE);
703f4664459SJohn Scipione 		else
704f4664459SJohn Scipione 			fText->SetFlags(fText->Flags() & ~B_NAVIGABLE);
705f4664459SJohn Scipione 
706f4664459SJohn Scipione 		_UpdateTextViewColors(enable);
707f4664459SJohn Scipione 
708f4664459SJohn Scipione 		fText->Invalidate();
709f4664459SJohn Scipione 		Window()->UpdateIfNeeded();
710f4664459SJohn Scipione 	}
711f4664459SJohn Scipione 
712f4664459SJohn Scipione 	BControl::SetEnabled(enable);
713f4664459SJohn Scipione }
714f4664459SJohn Scipione 
715f4664459SJohn Scipione 
716f4664459SJohn Scipione void
717f4664459SJohn Scipione BTextControl::GetPreferredSize(float* _width, float* _height)
718f4664459SJohn Scipione {
719f4664459SJohn Scipione 	CALLED();
720f4664459SJohn Scipione 
721f4664459SJohn Scipione 	_ValidateLayoutData();
722f4664459SJohn Scipione 
723f4664459SJohn Scipione 	if (_width) {
724f4664459SJohn Scipione 		float minWidth = fLayoutData->min.width;
725f4664459SJohn Scipione 		if (Label() == NULL && !(Flags() & B_SUPPORTS_LAYOUT)) {
726f4664459SJohn Scipione 			// Indeed, only if there is no label! BeOS backwards compatible
727f4664459SJohn Scipione 			// behavior:
728f4664459SJohn Scipione 			minWidth = max_c(minWidth, Bounds().Width());
729f4664459SJohn Scipione 		}
730f4664459SJohn Scipione 		*_width = minWidth;
731f4664459SJohn Scipione 	}
732f4664459SJohn Scipione 
733f4664459SJohn Scipione 	if (_height)
734f4664459SJohn Scipione 		*_height = fLayoutData->min.height;
735f4664459SJohn Scipione }
736f4664459SJohn Scipione 
737f4664459SJohn Scipione 
738f4664459SJohn Scipione void
739f4664459SJohn Scipione BTextControl::ResizeToPreferred()
740f4664459SJohn Scipione {
741f4664459SJohn Scipione 	BView::ResizeToPreferred();
742f4664459SJohn Scipione 
743f4664459SJohn Scipione 	fDivider = 0.0;
744f4664459SJohn Scipione 	const char* label = Label();
745f4664459SJohn Scipione 	if (label)
746f4664459SJohn Scipione 		fDivider = ceil(StringWidth(label)) + 2.0;
747f4664459SJohn Scipione 
748f4664459SJohn Scipione 	_LayoutTextView();
749f4664459SJohn Scipione }
750f4664459SJohn Scipione 
751f4664459SJohn Scipione 
752f4664459SJohn Scipione void
753f4664459SJohn Scipione BTextControl::SetFlags(uint32 flags)
754f4664459SJohn Scipione {
755f4664459SJohn Scipione 	// If the textview is navigable, set it to not navigable if needed
756f4664459SJohn Scipione 	// Else if it is not navigable, set it to navigable if needed
757f4664459SJohn Scipione 	if (fText->Flags() & B_NAVIGABLE) {
758f4664459SJohn Scipione 		if (!(flags & B_NAVIGABLE))
759f4664459SJohn Scipione 			fText->SetFlags(fText->Flags() & ~B_NAVIGABLE);
760f4664459SJohn Scipione 
761f4664459SJohn Scipione 	} else {
762f4664459SJohn Scipione 		if (flags & B_NAVIGABLE)
763f4664459SJohn Scipione 			fText->SetFlags(fText->Flags() | B_NAVIGABLE);
764f4664459SJohn Scipione 	}
765f4664459SJohn Scipione 
766f4664459SJohn Scipione 	// Don't make this one navigable
767f4664459SJohn Scipione 	flags &= ~B_NAVIGABLE;
768f4664459SJohn Scipione 
769f4664459SJohn Scipione 	BView::SetFlags(flags);
770f4664459SJohn Scipione }
771f4664459SJohn Scipione 
772f4664459SJohn Scipione 
773f4664459SJohn Scipione //	#pragma mark - Scripting
774f4664459SJohn Scipione 
775f4664459SJohn Scipione 
776f4664459SJohn Scipione BHandler*
777f4664459SJohn Scipione BTextControl::ResolveSpecifier(BMessage* message, int32 index,
778f4664459SJohn Scipione 	BMessage* specifier, int32 what, const char* property)
779f4664459SJohn Scipione {
780f4664459SJohn Scipione 	BPropertyInfo propInfo(sPropertyList);
781f4664459SJohn Scipione 
782f4664459SJohn Scipione 	if (propInfo.FindMatch(message, 0, specifier, what, property) >= B_OK)
783f4664459SJohn Scipione 		return this;
784f4664459SJohn Scipione 
785f4664459SJohn Scipione 	return BControl::ResolveSpecifier(message, index, specifier, what,
786f4664459SJohn Scipione 		property);
787f4664459SJohn Scipione }
788f4664459SJohn Scipione 
789f4664459SJohn Scipione 
790f4664459SJohn Scipione status_t
791f4664459SJohn Scipione BTextControl::GetSupportedSuites(BMessage* data)
792f4664459SJohn Scipione {
793f4664459SJohn Scipione 	return BControl::GetSupportedSuites(data);
794f4664459SJohn Scipione }
795f4664459SJohn Scipione 
796f4664459SJohn Scipione 
797f4664459SJohn Scipione //	#pragma mark - Layout
798f4664459SJohn Scipione 
799f4664459SJohn Scipione 
800349c911eSStephan Aßmus BSize
801349c911eSStephan Aßmus BTextControl::MinSize()
80252a38012Sejakowatz {
803349c911eSStephan Aßmus 	CALLED();
804349c911eSStephan Aßmus 
805349c911eSStephan Aßmus 	_ValidateLayoutData();
806349c911eSStephan Aßmus 	return BLayoutUtils::ComposeSize(ExplicitMinSize(), fLayoutData->min);
807349c911eSStephan Aßmus }
808349c911eSStephan Aßmus 
809349c911eSStephan Aßmus 
810349c911eSStephan Aßmus BSize
811349c911eSStephan Aßmus BTextControl::MaxSize()
812349c911eSStephan Aßmus {
813349c911eSStephan Aßmus 	CALLED();
814349c911eSStephan Aßmus 
815349c911eSStephan Aßmus 	_ValidateLayoutData();
816349c911eSStephan Aßmus 
817349c911eSStephan Aßmus 	BSize max = fLayoutData->min;
818349c911eSStephan Aßmus 	max.width = B_SIZE_UNLIMITED;
819349c911eSStephan Aßmus 
820349c911eSStephan Aßmus 	return BLayoutUtils::ComposeSize(ExplicitMaxSize(), max);
821349c911eSStephan Aßmus }
822349c911eSStephan Aßmus 
823349c911eSStephan Aßmus 
824349c911eSStephan Aßmus BSize
825349c911eSStephan Aßmus BTextControl::PreferredSize()
826349c911eSStephan Aßmus {
827349c911eSStephan Aßmus 	CALLED();
828349c911eSStephan Aßmus 
829349c911eSStephan Aßmus 	_ValidateLayoutData();
830349c911eSStephan Aßmus 	return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), fLayoutData->min);
831349c911eSStephan Aßmus }
832349c911eSStephan Aßmus 
833349c911eSStephan Aßmus 
83446d6e9d9SRene Gollent BAlignment
83546d6e9d9SRene Gollent BTextControl::LayoutAlignment()
83646d6e9d9SRene Gollent {
83746d6e9d9SRene Gollent 	CALLED();
83846d6e9d9SRene Gollent 
83946d6e9d9SRene Gollent 	_ValidateLayoutData();
84046d6e9d9SRene Gollent 	return BLayoutUtils::ComposeAlignment(ExplicitAlignment(),
841be92485fSHumdinger 		BAlignment(B_ALIGN_LEFT, B_ALIGN_VERTICAL_CENTER));
84246d6e9d9SRene Gollent }
84346d6e9d9SRene Gollent 
84446d6e9d9SRene Gollent 
8459ecf9d1cSIngo Weinhold BLayoutItem*
8469ecf9d1cSIngo Weinhold BTextControl::CreateLabelLayoutItem()
8479ecf9d1cSIngo Weinhold {
848349c911eSStephan Aßmus 	if (!fLayoutData->label_layout_item)
849349c911eSStephan Aßmus 		fLayoutData->label_layout_item = new LabelLayoutItem(this);
850b11edca4SJohn Scipione 
851349c911eSStephan Aßmus 	return fLayoutData->label_layout_item;
8529ecf9d1cSIngo Weinhold }
8539ecf9d1cSIngo Weinhold 
8549ecf9d1cSIngo Weinhold 
8559ecf9d1cSIngo Weinhold BLayoutItem*
8569ecf9d1cSIngo Weinhold BTextControl::CreateTextViewLayoutItem()
8579ecf9d1cSIngo Weinhold {
858349c911eSStephan Aßmus 	if (!fLayoutData->text_view_layout_item)
859349c911eSStephan Aßmus 		fLayoutData->text_view_layout_item = new TextViewLayoutItem(this);
860b11edca4SJohn Scipione 
861349c911eSStephan Aßmus 	return fLayoutData->text_view_layout_item;
862349c911eSStephan Aßmus }
863349c911eSStephan Aßmus 
864349c911eSStephan Aßmus 
865349c911eSStephan Aßmus void
866349c911eSStephan Aßmus BTextControl::DoLayout()
867349c911eSStephan Aßmus {
868349c911eSStephan Aßmus 	// Bail out, if we shan't do layout.
869349c911eSStephan Aßmus 	if (!(Flags() & B_SUPPORTS_LAYOUT))
870349c911eSStephan Aßmus 		return;
871349c911eSStephan Aßmus 
872349c911eSStephan Aßmus 	CALLED();
873349c911eSStephan Aßmus 
874349c911eSStephan Aßmus 	// If the user set a layout, we let the base class version call its
875349c911eSStephan Aßmus 	// hook.
876349c911eSStephan Aßmus 	if (GetLayout()) {
877349c911eSStephan Aßmus 		BView::DoLayout();
878349c911eSStephan Aßmus 		return;
879349c911eSStephan Aßmus 	}
880349c911eSStephan Aßmus 
881349c911eSStephan Aßmus 	_ValidateLayoutData();
882349c911eSStephan Aßmus 
883349c911eSStephan Aßmus 	// validate current size
884349c911eSStephan Aßmus 	BSize size(Bounds().Size());
885349c911eSStephan Aßmus 	if (size.width < fLayoutData->min.width)
886349c911eSStephan Aßmus 		size.width = fLayoutData->min.width;
887b11edca4SJohn Scipione 
888349c911eSStephan Aßmus 	if (size.height < fLayoutData->min.height)
889349c911eSStephan Aßmus 		size.height = fLayoutData->min.height;
890349c911eSStephan Aßmus 
89109d87d91SAxel Dörfler 	BRect dirty(fText->Frame());
89209d87d91SAxel Dörfler 	BRect textFrame;
89309d87d91SAxel Dörfler 
894349c911eSStephan Aßmus 	// divider
895349c911eSStephan Aßmus 	float divider = 0;
89609d87d91SAxel Dörfler 	if (fLayoutData->text_view_layout_item != NULL) {
89709d87d91SAxel Dörfler 		if (fLayoutData->label_layout_item != NULL) {
898349c911eSStephan Aßmus 			// We have layout items. They define the divider location.
89909d87d91SAxel Dörfler 			divider = fabs(fLayoutData->text_view_layout_item->Frame().left
90009d87d91SAxel Dörfler 				- fLayoutData->label_layout_item->Frame().left);
90109d87d91SAxel Dörfler 		}
90209d87d91SAxel Dörfler 		textFrame = fLayoutData->text_view_layout_item->FrameInParent();
903349c911eSStephan Aßmus 	} else {
90409d87d91SAxel Dörfler 		if (fLayoutData->label_width > 0) {
90509d87d91SAxel Dörfler 			divider = fLayoutData->label_width
90609d87d91SAxel Dörfler 				+ be_control_look->DefaultLabelSpacing();
90709d87d91SAxel Dörfler 		}
90809d87d91SAxel Dörfler 		textFrame.Set(divider, 0, size.width, size.height);
909349c911eSStephan Aßmus 	}
910349c911eSStephan Aßmus 
911349c911eSStephan Aßmus 	// place the text view and set the divider
91209d87d91SAxel Dörfler 	textFrame.InsetBy(kFrameMargin, kFrameMargin);
913349c911eSStephan Aßmus 	BLayoutUtils::AlignInFrame(fText, textFrame);
914*d9385a9dSJohn Scipione 	fText->SetTextRect(textFrame.OffsetToCopy(B_ORIGIN));
915349c911eSStephan Aßmus 
916349c911eSStephan Aßmus 	fDivider = divider;
917349c911eSStephan Aßmus 
918349c911eSStephan Aßmus 	// invalidate dirty region
919349c911eSStephan Aßmus 	dirty = dirty | fText->Frame();
920349c911eSStephan Aßmus 	dirty.InsetBy(-kFrameMargin, -kFrameMargin);
921349c911eSStephan Aßmus 
922349c911eSStephan Aßmus 	Invalidate(dirty);
923349c911eSStephan Aßmus }
924349c911eSStephan Aßmus 
925349c911eSStephan Aßmus 
926f4664459SJohn Scipione // #pragma mark - protected methods
927f4664459SJohn Scipione 
928f4664459SJohn Scipione 
929be436742SIngo Weinhold status_t
930be436742SIngo Weinhold BTextControl::SetIcon(const BBitmap* icon, uint32 flags)
931be436742SIngo Weinhold {
932be436742SIngo Weinhold 	return BControl::SetIcon(icon, flags);
933be436742SIngo Weinhold }
934be436742SIngo Weinhold 
935be436742SIngo Weinhold 
936f4664459SJohn Scipione // #pragma mark - private methods
937349c911eSStephan Aßmus 
938349c911eSStephan Aßmus 
939349c911eSStephan Aßmus status_t
94039fbf550SOliver Tappe BTextControl::Perform(perform_code code, void* _data)
941349c911eSStephan Aßmus {
94239fbf550SOliver Tappe 	switch (code) {
94339fbf550SOliver Tappe 		case PERFORM_CODE_MIN_SIZE:
94439fbf550SOliver Tappe 			((perform_data_min_size*)_data)->return_value
94539fbf550SOliver Tappe 				= BTextControl::MinSize();
94639fbf550SOliver Tappe 			return B_OK;
947b11edca4SJohn Scipione 
94839fbf550SOliver Tappe 		case PERFORM_CODE_MAX_SIZE:
94939fbf550SOliver Tappe 			((perform_data_max_size*)_data)->return_value
95039fbf550SOliver Tappe 				= BTextControl::MaxSize();
95139fbf550SOliver Tappe 			return B_OK;
952b11edca4SJohn Scipione 
95339fbf550SOliver Tappe 		case PERFORM_CODE_PREFERRED_SIZE:
95439fbf550SOliver Tappe 			((perform_data_preferred_size*)_data)->return_value
95539fbf550SOliver Tappe 				= BTextControl::PreferredSize();
95639fbf550SOliver Tappe 			return B_OK;
957b11edca4SJohn Scipione 
95839fbf550SOliver Tappe 		case PERFORM_CODE_LAYOUT_ALIGNMENT:
95939fbf550SOliver Tappe 			((perform_data_layout_alignment*)_data)->return_value
96039fbf550SOliver Tappe 				= BTextControl::LayoutAlignment();
96139fbf550SOliver Tappe 			return B_OK;
962b11edca4SJohn Scipione 
96339fbf550SOliver Tappe 		case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
96439fbf550SOliver Tappe 			((perform_data_has_height_for_width*)_data)->return_value
96539fbf550SOliver Tappe 				= BTextControl::HasHeightForWidth();
96639fbf550SOliver Tappe 			return B_OK;
967b11edca4SJohn Scipione 
96839fbf550SOliver Tappe 		case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
96939fbf550SOliver Tappe 		{
97039fbf550SOliver Tappe 			perform_data_get_height_for_width* data
97139fbf550SOliver Tappe 				= (perform_data_get_height_for_width*)_data;
97239fbf550SOliver Tappe 			BTextControl::GetHeightForWidth(data->width, &data->min, &data->max,
97339fbf550SOliver Tappe 				&data->preferred);
97439fbf550SOliver Tappe 			return B_OK;
97539fbf550SOliver Tappe 		}
976b11edca4SJohn Scipione 
97739fbf550SOliver Tappe 		case PERFORM_CODE_SET_LAYOUT:
97839fbf550SOliver Tappe 		{
97939fbf550SOliver Tappe 			perform_data_set_layout* data = (perform_data_set_layout*)_data;
98039fbf550SOliver Tappe 			BTextControl::SetLayout(data->layout);
98139fbf550SOliver Tappe 			return B_OK;
98239fbf550SOliver Tappe 		}
983b11edca4SJohn Scipione 
984eee4243dSAlex Wilson 		case PERFORM_CODE_LAYOUT_INVALIDATED:
98539fbf550SOliver Tappe 		{
986eee4243dSAlex Wilson 			perform_data_layout_invalidated* data
987eee4243dSAlex Wilson 				= (perform_data_layout_invalidated*)_data;
988eee4243dSAlex Wilson 			BTextControl::LayoutInvalidated(data->descendants);
98939fbf550SOliver Tappe 			return B_OK;
99039fbf550SOliver Tappe 		}
991b11edca4SJohn Scipione 
99239fbf550SOliver Tappe 		case PERFORM_CODE_DO_LAYOUT:
99339fbf550SOliver Tappe 		{
99439fbf550SOliver Tappe 			BTextControl::DoLayout();
99539fbf550SOliver Tappe 			return B_OK;
99639fbf550SOliver Tappe 		}
997b11edca4SJohn Scipione 
998be436742SIngo Weinhold 		case PERFORM_CODE_SET_ICON:
999be436742SIngo Weinhold 		{
1000be436742SIngo Weinhold 			perform_data_set_icon* data = (perform_data_set_icon*)_data;
1001be436742SIngo Weinhold 			return BTextControl::SetIcon(data->icon, data->flags);
1002be436742SIngo Weinhold 		}
1003b11edca4SJohn Scipione 
10045c47e35eSAlex Wilson 		case PERFORM_CODE_ALL_UNARCHIVED:
10055c47e35eSAlex Wilson 		{
10065c47e35eSAlex Wilson 			perform_data_all_unarchived* data
10075c47e35eSAlex Wilson 				= (perform_data_all_unarchived*)_data;
10085c47e35eSAlex Wilson 			data->return_value = BTextControl::AllUnarchived(data->archive);
10095c47e35eSAlex Wilson 			return B_OK;
10105c47e35eSAlex Wilson 		}
1011b11edca4SJohn Scipione 
10125c47e35eSAlex Wilson 		case PERFORM_CODE_ALL_ARCHIVED:
10135c47e35eSAlex Wilson 		{
10145c47e35eSAlex Wilson 			perform_data_all_archived* data
10155c47e35eSAlex Wilson 				= (perform_data_all_archived*)_data;
10165c47e35eSAlex Wilson 			data->return_value = BTextControl::AllArchived(data->archive);
10175c47e35eSAlex Wilson 			return B_OK;
10185c47e35eSAlex Wilson 		}
101939fbf550SOliver Tappe 	}
102039fbf550SOliver Tappe 
102139fbf550SOliver Tappe 	return BControl::Perform(code, _data);
10229ecf9d1cSIngo Weinhold }
10239ecf9d1cSIngo Weinhold 
10249ecf9d1cSIngo Weinhold 
1025f4664459SJohn Scipione //	#pragma mark - FBC padding
1026f4664459SJohn Scipione 
1027f4664459SJohn Scipione 
10289cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl1() {}
10299cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl2() {}
10309cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl3() {}
10319cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl4() {}
1032058691d4SStefano Ceccherini 
1033058691d4SStefano Ceccherini 
1034058691d4SStefano Ceccherini BTextControl&
1035058691d4SStefano Ceccherini BTextControl::operator=(const BTextControl&)
103652a38012Sejakowatz {
103752a38012Sejakowatz 	return *this;
103852a38012Sejakowatz }
1039058691d4SStefano Ceccherini 
1040058691d4SStefano Ceccherini 
1041058691d4SStefano Ceccherini void
1042f4664459SJohn Scipione BTextControl::_UpdateTextViewColors(bool enable)
10433a3f6c1eSAxel Dörfler {
10447a96554cSlooncraz 	rgb_color textColor = ui_color(B_DOCUMENT_TEXT_COLOR);
10457a96554cSlooncraz 	rgb_color viewColor = ui_color(B_DOCUMENT_BACKGROUND_COLOR);
10463a3f6c1eSAxel Dörfler 	BFont font;
10473a3f6c1eSAxel Dörfler 
1048aae7000dSAxel Dörfler 	fText->GetFontAndColor(0, &font);
10493a3f6c1eSAxel Dörfler 
10507a96554cSlooncraz 	if (!enable) {
10517a96554cSlooncraz 		textColor = disable_color(textColor, ViewColor());
10527a96554cSlooncraz 		viewColor = disable_color(ViewColor(), viewColor);
105312aefeb4SAxel Dörfler 	}
10543a3f6c1eSAxel Dörfler 
10553a3f6c1eSAxel Dörfler 	fText->SetFontAndColor(&font, B_FONT_ALL, &textColor);
10567a96554cSlooncraz 	fText->SetViewColor(viewColor);
10577a96554cSlooncraz 	fText->SetLowColor(viewColor);
10583a3f6c1eSAxel Dörfler }
10593a3f6c1eSAxel Dörfler 
10603a3f6c1eSAxel Dörfler 
10613a3f6c1eSAxel Dörfler void
1062ffe72abdSAxel Dörfler BTextControl::_CommitValue()
10639cb2dbe2SMarc Flerackers {
10649cb2dbe2SMarc Flerackers }
1065058691d4SStefano Ceccherini 
1066058691d4SStefano Ceccherini 
1067058691d4SStefano Ceccherini void
10685c47e35eSAlex Wilson BTextControl::_InitData(const char* label, const BMessage* archive)
10699cb2dbe2SMarc Flerackers {
10709cb2dbe2SMarc Flerackers 	BRect bounds(Bounds());
10719cb2dbe2SMarc Flerackers 
10729cb2dbe2SMarc Flerackers 	fText = NULL;
10739cb2dbe2SMarc Flerackers 	fModificationMessage = NULL;
10749cb2dbe2SMarc Flerackers 	fLabelAlign = B_ALIGN_LEFT;
10759cb2dbe2SMarc Flerackers 	fDivider = 0.0f;
1076349c911eSStephan Aßmus 	fLayoutData = new LayoutData(bounds.Width(), bounds.Height());
10779cb2dbe2SMarc Flerackers 
10789cb2dbe2SMarc Flerackers 	int32 flags = 0;
10799cb2dbe2SMarc Flerackers 
1080918a22d9SDarkWyrm 	BFont font(be_plain_font);
10819cb2dbe2SMarc Flerackers 
1082ffe72abdSAxel Dörfler 	if (!archive || !archive->HasString("_fname"))
1083058691d4SStefano Ceccherini 		flags |= B_FONT_FAMILY_AND_STYLE;
10849cb2dbe2SMarc Flerackers 
1085ffe72abdSAxel Dörfler 	if (!archive || !archive->HasFloat("_fflt"))
1086058691d4SStefano Ceccherini 		flags |= B_FONT_SIZE;
10879cb2dbe2SMarc Flerackers 
10889cb2dbe2SMarc Flerackers 	if (flags != 0)
10899cb2dbe2SMarc Flerackers 		SetFont(&font, flags);
10909cb2dbe2SMarc Flerackers 
1091f4664459SJohn Scipione 	if (label != NULL)
10922e6a5805SStephan Aßmus 		fDivider = floorf(bounds.Width() / 2.0f);
109313d147b1SAdrien Destugues 
109413d147b1SAdrien Destugues 	fLook = 0;
10955c47e35eSAlex Wilson }
10965c47e35eSAlex Wilson 
10975c47e35eSAlex Wilson 
10985c47e35eSAlex Wilson void
10995c47e35eSAlex Wilson BTextControl::_InitText(const char* initialText, const BMessage* archive)
11005c47e35eSAlex Wilson {
1101ffe72abdSAxel Dörfler 	if (archive)
1102b8872c02SStephan Aßmus 		fText = static_cast<BPrivate::_BTextInput_*>(FindView("_input_"));
1103991c062fSAxel Dörfler 
1104991c062fSAxel Dörfler 	if (fText == NULL) {
11055c47e35eSAlex Wilson 		BRect bounds(Bounds());
1106ee2a3473SStephan Aßmus 		BRect frame(fDivider, bounds.top, bounds.right, bounds.bottom);
1107105644bfSAxel Dörfler 		// we are stroking the frame around the text view, which
11082e6a5805SStephan Aßmus 		// is 2 pixels wide
1109349c911eSStephan Aßmus 		frame.InsetBy(kFrameMargin, kFrameMargin);
1110111b4fbcSStefano Ceccherini 		BRect textRect(frame.OffsetToCopy(B_ORIGIN));
11119cb2dbe2SMarc Flerackers 
1112b8872c02SStephan Aßmus 		fText = new BPrivate::_BTextInput_(frame, textRect,
11135c47e35eSAlex Wilson 			B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS
11145c47e35eSAlex Wilson 			| (Flags() & B_NAVIGABLE));
11159cb2dbe2SMarc Flerackers 		AddChild(fText);
11169cb2dbe2SMarc Flerackers 
1117455d1c46SAxel Dörfler 		SetText(initialText);
11189cb2dbe2SMarc Flerackers 		fText->SetAlignment(B_ALIGN_LEFT);
11199cb2dbe2SMarc Flerackers 	}
11205c47e35eSAlex Wilson 
11215c47e35eSAlex Wilson 	// Although this is not strictly initializing the text view,
11225c47e35eSAlex Wilson 	// it cannot be done while fText is NULL, so it resides here.
11235c47e35eSAlex Wilson 	if (archive) {
11245c47e35eSAlex Wilson 		int32 labelAlignment = B_ALIGN_LEFT;
11255c47e35eSAlex Wilson 		int32 textAlignment = B_ALIGN_LEFT;
11265c47e35eSAlex Wilson 
11275c47e35eSAlex Wilson 		status_t err = B_OK;
11285c47e35eSAlex Wilson 		if (archive->HasInt32("_a_label"))
11295c47e35eSAlex Wilson 			err = archive->FindInt32("_a_label", &labelAlignment);
11305c47e35eSAlex Wilson 
11315c47e35eSAlex Wilson 		if (err == B_OK && archive->HasInt32("_a_text"))
11325c47e35eSAlex Wilson 			err = archive->FindInt32("_a_text", &textAlignment);
11335c47e35eSAlex Wilson 
11345c47e35eSAlex Wilson 		SetAlignment((alignment)labelAlignment, (alignment)textAlignment);
11355c47e35eSAlex Wilson 	}
113650960935SClemens Zeidler 
113750960935SClemens Zeidler 	uint32 navigableFlags = Flags() & B_NAVIGABLE;
113850960935SClemens Zeidler 	if (navigableFlags != 0)
113950960935SClemens Zeidler 		BView::SetFlags(Flags() & ~B_NAVIGABLE);
11409cb2dbe2SMarc Flerackers }
11419ecf9d1cSIngo Weinhold 
11429ecf9d1cSIngo Weinhold 
11439ecf9d1cSIngo Weinhold void
11449ecf9d1cSIngo Weinhold BTextControl::_ValidateLayout()
11459ecf9d1cSIngo Weinhold {
114693ba577cSStephan Aßmus 	CALLED();
114793ba577cSStephan Aßmus 
1148349c911eSStephan Aßmus 	_ValidateLayoutData();
11499ecf9d1cSIngo Weinhold 
1150349c911eSStephan Aßmus 	ResizeTo(Bounds().Width(), fLayoutData->min.height);
11519ecf9d1cSIngo Weinhold 
1152a431f44bSStephan Aßmus 	_LayoutTextView();
11539ecf9d1cSIngo Weinhold }
11549ecf9d1cSIngo Weinhold 
11559ecf9d1cSIngo Weinhold 
11569ecf9d1cSIngo Weinhold void
1157a431f44bSStephan Aßmus BTextControl::_LayoutTextView()
1158a431f44bSStephan Aßmus {
115993ba577cSStephan Aßmus 	CALLED();
116093ba577cSStephan Aßmus 
116109d87d91SAxel Dörfler 	BRect frame;
116209d87d91SAxel Dörfler 	if (fLayoutData->text_view_layout_item != NULL) {
116309d87d91SAxel Dörfler 		frame = fLayoutData->text_view_layout_item->FrameInParent();
116409d87d91SAxel Dörfler 	} else {
116509d87d91SAxel Dörfler 		frame = Bounds();
1166a431f44bSStephan Aßmus 		frame.left = fDivider;
116709d87d91SAxel Dörfler 	}
116809d87d91SAxel Dörfler 
1169a431f44bSStephan Aßmus 	// we are stroking the frame around the text view, which
1170a431f44bSStephan Aßmus 	// is 2 pixels wide
117184b7e122SStephan Aßmus 	frame.InsetBy(kFrameMargin, kFrameMargin);
1172a431f44bSStephan Aßmus 	fText->MoveTo(frame.left, frame.top);
1173a431f44bSStephan Aßmus 	fText->ResizeTo(frame.Width(), frame.Height());
117493ba577cSStephan Aßmus 
117593ba577cSStephan Aßmus 	TRACE("width: %.2f, height: %.2f\n", Frame().Width(), Frame().Height());
117693ba577cSStephan Aßmus 	TRACE("fDivider: %.2f\n", fDivider);
117793ba577cSStephan Aßmus 	TRACE("fText frame: (%.2f, %.2f, %.2f, %.2f)\n",
117893ba577cSStephan Aßmus 		frame.left, frame.top, frame.right, frame.bottom);
1179a431f44bSStephan Aßmus }
1180a431f44bSStephan Aßmus 
1181a431f44bSStephan Aßmus 
1182a431f44bSStephan Aßmus void
11839ecf9d1cSIngo Weinhold BTextControl::_UpdateFrame()
11849ecf9d1cSIngo Weinhold {
1185349c911eSStephan Aßmus 	CALLED();
1186349c911eSStephan Aßmus 
118709d87d91SAxel Dörfler 	if (fLayoutData->text_view_layout_item != NULL) {
1188349c911eSStephan Aßmus 		BRect textFrame = fLayoutData->text_view_layout_item->Frame();
118909d87d91SAxel Dörfler 		BRect labelFrame;
119009d87d91SAxel Dörfler 		if (fLayoutData->label_layout_item != NULL)
119109d87d91SAxel Dörfler 			labelFrame = fLayoutData->label_layout_item->Frame();
119209d87d91SAxel Dörfler 
119309d87d91SAxel Dörfler 		BRect frame;
119409d87d91SAxel Dörfler 		if (labelFrame.IsValid()) {
119509d87d91SAxel Dörfler 			frame = textFrame | labelFrame;
1196349c911eSStephan Aßmus 
1197349c911eSStephan Aßmus 			// update divider
119809d87d91SAxel Dörfler 			fDivider = fabs(textFrame.left - labelFrame.left);
119909d87d91SAxel Dörfler 		} else {
120009d87d91SAxel Dörfler 			frame = textFrame;
120109d87d91SAxel Dörfler 			fDivider = 0;
120209d87d91SAxel Dörfler 		}
1203349c911eSStephan Aßmus 
1204b11edca4SJohn Scipione 		// update our frame
120509d87d91SAxel Dörfler 		MoveTo(frame.left, frame.top);
1206b11edca4SJohn Scipione 		BSize oldSize(Bounds().Size());
120709d87d91SAxel Dörfler 		ResizeTo(frame.Width(), frame.Height());
1208b11edca4SJohn Scipione 		BSize newSize(Bounds().Size());
1209349c911eSStephan Aßmus 
1210349c911eSStephan Aßmus 		// If the size changes, ResizeTo() will trigger a relayout, otherwise
1211349c911eSStephan Aßmus 		// we need to do that explicitly.
1212349c911eSStephan Aßmus 		if (newSize != oldSize)
1213349c911eSStephan Aßmus 			Relayout();
12149ecf9d1cSIngo Weinhold 	}
12159ecf9d1cSIngo Weinhold }
12169ecf9d1cSIngo Weinhold 
12179ecf9d1cSIngo Weinhold 
1218349c911eSStephan Aßmus void
1219349c911eSStephan Aßmus BTextControl::_ValidateLayoutData()
1220349c911eSStephan Aßmus {
1221349c911eSStephan Aßmus 	CALLED();
1222349c911eSStephan Aßmus 
1223349c911eSStephan Aßmus 	if (fLayoutData->valid)
1224349c911eSStephan Aßmus 		return;
1225349c911eSStephan Aßmus 
1226349c911eSStephan Aßmus 	// cache font height
1227349c911eSStephan Aßmus 	font_height& fh = fLayoutData->font_info;
1228349c911eSStephan Aßmus 	GetFontHeight(&fh);
1229349c911eSStephan Aßmus 
123060370b9aSJohn Scipione 	const char* label = Label();
123160370b9aSJohn Scipione 	if (label != NULL) {
123260370b9aSJohn Scipione 		fLayoutData->label_width = ceilf(StringWidth(label));
1233349c911eSStephan Aßmus 		fLayoutData->label_height = ceilf(fh.ascent) + ceilf(fh.descent);
1234349c911eSStephan Aßmus 	} else {
1235349c911eSStephan Aßmus 		fLayoutData->label_width = 0;
1236349c911eSStephan Aßmus 		fLayoutData->label_height = 0;
1237349c911eSStephan Aßmus 	}
1238349c911eSStephan Aßmus 
1239349c911eSStephan Aßmus 	// compute the minimal divider
1240349c911eSStephan Aßmus 	float divider = 0;
124109d87d91SAxel Dörfler 	if (fLayoutData->label_width > 0) {
124209d87d91SAxel Dörfler 		divider = fLayoutData->label_width
124309d87d91SAxel Dörfler 			+ be_control_look->DefaultLabelSpacing();
124409d87d91SAxel Dörfler 	}
1245349c911eSStephan Aßmus 
1246349c911eSStephan Aßmus 	// If we shan't do real layout, we let the current divider take influence.
1247349c911eSStephan Aßmus 	if (!(Flags() & B_SUPPORTS_LAYOUT))
1248349c911eSStephan Aßmus 		divider = max_c(divider, fDivider);
1249349c911eSStephan Aßmus 
1250349c911eSStephan Aßmus 	// get the minimal (== preferred) text view size
1251349c911eSStephan Aßmus 	fLayoutData->text_view_min = fText->MinSize();
1252349c911eSStephan Aßmus 
1253349c911eSStephan Aßmus 	TRACE("text view min width: %.2f\n", fLayoutData->text_view_min.width);
1254349c911eSStephan Aßmus 
1255349c911eSStephan Aßmus 	// compute our minimal (== preferred) size
1256349c911eSStephan Aßmus 	BSize min(fLayoutData->text_view_min);
1257349c911eSStephan Aßmus 	min.width += 2 * kFrameMargin;
1258349c911eSStephan Aßmus 	min.height += 2 * kFrameMargin;
1259349c911eSStephan Aßmus 
1260349c911eSStephan Aßmus 	if (divider > 0)
1261349c911eSStephan Aßmus 		min.width += divider;
1262b11edca4SJohn Scipione 
1263349c911eSStephan Aßmus 	if (fLayoutData->label_height > min.height)
1264349c911eSStephan Aßmus 		min.height = fLayoutData->label_height;
1265349c911eSStephan Aßmus 
1266349c911eSStephan Aßmus 	fLayoutData->min = min;
1267349c911eSStephan Aßmus 
1268349c911eSStephan Aßmus 	fLayoutData->valid = true;
1269c944d11fSStephan Aßmus 	ResetLayoutInvalidation();
1270349c911eSStephan Aßmus 
1271349c911eSStephan Aßmus 	TRACE("width: %.2f, height: %.2f\n", min.width, min.height);
1272349c911eSStephan Aßmus }
1273349c911eSStephan Aßmus 
1274349c911eSStephan Aßmus 
1275b11edca4SJohn Scipione // #pragma mark - BTextControl::LabelLayoutItem
12769ecf9d1cSIngo Weinhold 
12779ecf9d1cSIngo Weinhold 
12789ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::LabelLayoutItem(BTextControl* parent)
12795c47e35eSAlex Wilson 	:
12805c47e35eSAlex Wilson 	fParent(parent),
12819ecf9d1cSIngo Weinhold 	fFrame()
12829ecf9d1cSIngo Weinhold {
12839ecf9d1cSIngo Weinhold }
12849ecf9d1cSIngo Weinhold 
12859ecf9d1cSIngo Weinhold 
12865c47e35eSAlex Wilson BTextControl::LabelLayoutItem::LabelLayoutItem(BMessage* from)
12875c47e35eSAlex Wilson 	:
12885c47e35eSAlex Wilson 	BAbstractLayoutItem(from),
12895c47e35eSAlex Wilson 	fParent(NULL),
12905c47e35eSAlex Wilson 	fFrame()
12915c47e35eSAlex Wilson {
12925c47e35eSAlex Wilson 	from->FindRect(kFrameField, &fFrame);
12935c47e35eSAlex Wilson }
12945c47e35eSAlex Wilson 
12955c47e35eSAlex Wilson 
12969ecf9d1cSIngo Weinhold bool
12979ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::IsVisible()
12989ecf9d1cSIngo Weinhold {
12999ecf9d1cSIngo Weinhold 	return !fParent->IsHidden(fParent);
13009ecf9d1cSIngo Weinhold }
13019ecf9d1cSIngo Weinhold 
13029ecf9d1cSIngo Weinhold 
13039ecf9d1cSIngo Weinhold void
13049ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::SetVisible(bool visible)
13059ecf9d1cSIngo Weinhold {
13069ecf9d1cSIngo Weinhold 	// not allowed
13079ecf9d1cSIngo Weinhold }
13089ecf9d1cSIngo Weinhold 
13099ecf9d1cSIngo Weinhold 
13109ecf9d1cSIngo Weinhold BRect
13119ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::Frame()
13129ecf9d1cSIngo Weinhold {
13139ecf9d1cSIngo Weinhold 	return fFrame;
13149ecf9d1cSIngo Weinhold }
13159ecf9d1cSIngo Weinhold 
13169ecf9d1cSIngo Weinhold 
13179ecf9d1cSIngo Weinhold void
13189ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::SetFrame(BRect frame)
13199ecf9d1cSIngo Weinhold {
13209ecf9d1cSIngo Weinhold 	fFrame = frame;
13219ecf9d1cSIngo Weinhold 	fParent->_UpdateFrame();
13229ecf9d1cSIngo Weinhold }
13239ecf9d1cSIngo Weinhold 
13249ecf9d1cSIngo Weinhold 
13255c47e35eSAlex Wilson void
13265c47e35eSAlex Wilson BTextControl::LabelLayoutItem::SetParent(BTextControl* parent)
13275c47e35eSAlex Wilson {
13285c47e35eSAlex Wilson 	fParent = parent;
13295c47e35eSAlex Wilson }
13305c47e35eSAlex Wilson 
13315c47e35eSAlex Wilson 
13329ecf9d1cSIngo Weinhold BView*
13339ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::View()
13349ecf9d1cSIngo Weinhold {
13359ecf9d1cSIngo Weinhold 	return fParent;
13369ecf9d1cSIngo Weinhold }
13379ecf9d1cSIngo Weinhold 
13389ecf9d1cSIngo Weinhold 
13399ecf9d1cSIngo Weinhold BSize
13409ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BaseMinSize()
13419ecf9d1cSIngo Weinhold {
1342349c911eSStephan Aßmus 	fParent->_ValidateLayoutData();
1343349c911eSStephan Aßmus 
1344349c911eSStephan Aßmus 	if (!fParent->Label())
13459ecf9d1cSIngo Weinhold 		return BSize(-1, -1);
13469ecf9d1cSIngo Weinhold 
134709d87d91SAxel Dörfler 	return BSize(fParent->fLayoutData->label_width
134809d87d91SAxel Dörfler 			+ be_control_look->DefaultLabelSpacing(),
1349349c911eSStephan Aßmus 		fParent->fLayoutData->label_height);
13509ecf9d1cSIngo Weinhold }
13519ecf9d1cSIngo Weinhold 
13529ecf9d1cSIngo Weinhold 
13539ecf9d1cSIngo Weinhold BSize
13549ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BaseMaxSize()
13559ecf9d1cSIngo Weinhold {
13569ecf9d1cSIngo Weinhold 	return BaseMinSize();
13579ecf9d1cSIngo Weinhold }
13589ecf9d1cSIngo Weinhold 
13599ecf9d1cSIngo Weinhold 
13609ecf9d1cSIngo Weinhold BSize
13619ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BasePreferredSize()
13629ecf9d1cSIngo Weinhold {
13639ecf9d1cSIngo Weinhold 	return BaseMinSize();
13649ecf9d1cSIngo Weinhold }
13659ecf9d1cSIngo Weinhold 
13669ecf9d1cSIngo Weinhold 
13679ecf9d1cSIngo Weinhold BAlignment
13689ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BaseAlignment()
13699ecf9d1cSIngo Weinhold {
13709ecf9d1cSIngo Weinhold 	return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
13719ecf9d1cSIngo Weinhold }
13729ecf9d1cSIngo Weinhold 
13739ecf9d1cSIngo Weinhold 
137409d87d91SAxel Dörfler BRect
137509d87d91SAxel Dörfler BTextControl::LabelLayoutItem::FrameInParent() const
137609d87d91SAxel Dörfler {
137709d87d91SAxel Dörfler 	return fFrame.OffsetByCopy(-fParent->Frame().left, -fParent->Frame().top);
137809d87d91SAxel Dörfler }
137909d87d91SAxel Dörfler 
138009d87d91SAxel Dörfler 
13815c47e35eSAlex Wilson status_t
13825c47e35eSAlex Wilson BTextControl::LabelLayoutItem::Archive(BMessage* into, bool deep) const
13835c47e35eSAlex Wilson {
13845c47e35eSAlex Wilson 	BArchiver archiver(into);
13855c47e35eSAlex Wilson 	status_t err = BAbstractLayoutItem::Archive(into, deep);
13865c47e35eSAlex Wilson 	if (err == B_OK)
13875c47e35eSAlex Wilson 		err = into->AddRect(kFrameField, fFrame);
13885c47e35eSAlex Wilson 
13895c47e35eSAlex Wilson 	return archiver.Finish(err);
13905c47e35eSAlex Wilson }
13915c47e35eSAlex Wilson 
13925c47e35eSAlex Wilson 
13935c47e35eSAlex Wilson BArchivable*
13945c47e35eSAlex Wilson BTextControl::LabelLayoutItem::Instantiate(BMessage* from)
13955c47e35eSAlex Wilson {
13965c47e35eSAlex Wilson 	if (validate_instantiation(from, "BTextControl::LabelLayoutItem"))
13975c47e35eSAlex Wilson 		return new LabelLayoutItem(from);
13985c47e35eSAlex Wilson 	return NULL;
13995c47e35eSAlex Wilson }
14005c47e35eSAlex Wilson 
14015c47e35eSAlex Wilson 
1402b11edca4SJohn Scipione // #pragma mark - BTextControl::TextViewLayoutItem
14039ecf9d1cSIngo Weinhold 
14049ecf9d1cSIngo Weinhold 
14059ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::TextViewLayoutItem(BTextControl* parent)
14065c47e35eSAlex Wilson 	:
14075c47e35eSAlex Wilson 	fParent(parent),
14089ecf9d1cSIngo Weinhold 	fFrame()
14099ecf9d1cSIngo Weinhold {
1410349c911eSStephan Aßmus 	// by default the part right of the divider shall have an unlimited maximum
1411349c911eSStephan Aßmus 	// width
1412349c911eSStephan Aßmus 	SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
14139ecf9d1cSIngo Weinhold }
14149ecf9d1cSIngo Weinhold 
14159ecf9d1cSIngo Weinhold 
14165c47e35eSAlex Wilson BTextControl::TextViewLayoutItem::TextViewLayoutItem(BMessage* from)
14175c47e35eSAlex Wilson 	:
14185c47e35eSAlex Wilson 	BAbstractLayoutItem(from),
14195c47e35eSAlex Wilson 	fParent(NULL),
14205c47e35eSAlex Wilson 	fFrame()
14215c47e35eSAlex Wilson {
14225c47e35eSAlex Wilson 	from->FindRect(kFrameField, &fFrame);
14235c47e35eSAlex Wilson }
14245c47e35eSAlex Wilson 
14255c47e35eSAlex Wilson 
14269ecf9d1cSIngo Weinhold bool
14279ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::IsVisible()
14289ecf9d1cSIngo Weinhold {
14299ecf9d1cSIngo Weinhold 	return !fParent->IsHidden(fParent);
14309ecf9d1cSIngo Weinhold }
14319ecf9d1cSIngo Weinhold 
14329ecf9d1cSIngo Weinhold 
14339ecf9d1cSIngo Weinhold void
14349ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::SetVisible(bool visible)
14359ecf9d1cSIngo Weinhold {
14369ecf9d1cSIngo Weinhold 	// not allowed
14379ecf9d1cSIngo Weinhold }
14389ecf9d1cSIngo Weinhold 
14399ecf9d1cSIngo Weinhold 
14409ecf9d1cSIngo Weinhold BRect
14419ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::Frame()
14429ecf9d1cSIngo Weinhold {
14439ecf9d1cSIngo Weinhold 	return fFrame;
14449ecf9d1cSIngo Weinhold }
14459ecf9d1cSIngo Weinhold 
14469ecf9d1cSIngo Weinhold 
14479ecf9d1cSIngo Weinhold void
14489ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::SetFrame(BRect frame)
14499ecf9d1cSIngo Weinhold {
14509ecf9d1cSIngo Weinhold 	fFrame = frame;
14519ecf9d1cSIngo Weinhold 	fParent->_UpdateFrame();
14529ecf9d1cSIngo Weinhold }
14539ecf9d1cSIngo Weinhold 
14549ecf9d1cSIngo Weinhold 
14555c47e35eSAlex Wilson void
14565c47e35eSAlex Wilson BTextControl::TextViewLayoutItem::SetParent(BTextControl* parent)
14575c47e35eSAlex Wilson {
14585c47e35eSAlex Wilson 	fParent = parent;
14595c47e35eSAlex Wilson }
14605c47e35eSAlex Wilson 
14615c47e35eSAlex Wilson 
14629ecf9d1cSIngo Weinhold BView*
14639ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::View()
14649ecf9d1cSIngo Weinhold {
14659ecf9d1cSIngo Weinhold 	return fParent;
14669ecf9d1cSIngo Weinhold }
14679ecf9d1cSIngo Weinhold 
14689ecf9d1cSIngo Weinhold 
14699ecf9d1cSIngo Weinhold BSize
14709ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BaseMinSize()
14719ecf9d1cSIngo Weinhold {
1472349c911eSStephan Aßmus 	fParent->_ValidateLayoutData();
14739ecf9d1cSIngo Weinhold 
1474349c911eSStephan Aßmus 	BSize size = fParent->fLayoutData->text_view_min;
1475349c911eSStephan Aßmus 	size.width += 2 * kFrameMargin;
1476349c911eSStephan Aßmus 	size.height += 2 * kFrameMargin;
14779ecf9d1cSIngo Weinhold 
14789ecf9d1cSIngo Weinhold 	return size;
14799ecf9d1cSIngo Weinhold }
14809ecf9d1cSIngo Weinhold 
14819ecf9d1cSIngo Weinhold 
14829ecf9d1cSIngo Weinhold BSize
14839ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BaseMaxSize()
14849ecf9d1cSIngo Weinhold {
14859ecf9d1cSIngo Weinhold 	BSize size(BaseMinSize());
14869ecf9d1cSIngo Weinhold 	size.width = B_SIZE_UNLIMITED;
1487b11edca4SJohn Scipione 
14889ecf9d1cSIngo Weinhold 	return size;
14899ecf9d1cSIngo Weinhold }
14909ecf9d1cSIngo Weinhold 
14919ecf9d1cSIngo Weinhold 
14929ecf9d1cSIngo Weinhold BSize
14939ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BasePreferredSize()
14949ecf9d1cSIngo Weinhold {
14959ecf9d1cSIngo Weinhold 	BSize size(BaseMinSize());
14969ecf9d1cSIngo Weinhold 	// puh, no idea...
14979ecf9d1cSIngo Weinhold 	size.width = 100;
1498b11edca4SJohn Scipione 
14999ecf9d1cSIngo Weinhold 	return size;
15009ecf9d1cSIngo Weinhold }
15019ecf9d1cSIngo Weinhold 
15029ecf9d1cSIngo Weinhold 
15039ecf9d1cSIngo Weinhold BAlignment
15049ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BaseAlignment()
15059ecf9d1cSIngo Weinhold {
15069ecf9d1cSIngo Weinhold 	return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
15079ecf9d1cSIngo Weinhold }
15089ecf9d1cSIngo Weinhold 
15095c47e35eSAlex Wilson 
151009d87d91SAxel Dörfler BRect
151109d87d91SAxel Dörfler BTextControl::TextViewLayoutItem::FrameInParent() const
151209d87d91SAxel Dörfler {
151309d87d91SAxel Dörfler 	return fFrame.OffsetByCopy(-fParent->Frame().left, -fParent->Frame().top);
151409d87d91SAxel Dörfler }
151509d87d91SAxel Dörfler 
151609d87d91SAxel Dörfler 
15175c47e35eSAlex Wilson status_t
15185c47e35eSAlex Wilson BTextControl::TextViewLayoutItem::Archive(BMessage* into, bool deep) const
15195c47e35eSAlex Wilson {
15205c47e35eSAlex Wilson 	BArchiver archiver(into);
15215c47e35eSAlex Wilson 	status_t err = BAbstractLayoutItem::Archive(into, deep);
15225c47e35eSAlex Wilson 	if (err == B_OK)
15235c47e35eSAlex Wilson 		err = into->AddRect(kFrameField, fFrame);
15245c47e35eSAlex Wilson 
15255c47e35eSAlex Wilson 	return archiver.Finish(err);
15265c47e35eSAlex Wilson }
15275c47e35eSAlex Wilson 
15285c47e35eSAlex Wilson 
15295c47e35eSAlex Wilson BArchivable*
15305c47e35eSAlex Wilson BTextControl::TextViewLayoutItem::Instantiate(BMessage* from)
15315c47e35eSAlex Wilson {
15325c47e35eSAlex Wilson 	if (validate_instantiation(from, "BTextControl::TextViewLayoutItem"))
15335c47e35eSAlex Wilson 		return new TextViewLayoutItem(from);
1534b11edca4SJohn Scipione 
15355c47e35eSAlex Wilson 	return NULL;
15365c47e35eSAlex Wilson }
15375c47e35eSAlex Wilson 
15385c47e35eSAlex Wilson 
1539466f2b8fSRene Gollent extern "C" void
15408adaa6c5SJerome Duval B_IF_GCC_2(InvalidateLayout__12BTextControlb,
15418adaa6c5SJerome Duval 	_ZN12BTextControl16InvalidateLayoutEb)(BView* view, bool descendants)
1542466f2b8fSRene Gollent {
1543f6c8d242SRene Gollent 	perform_data_layout_invalidated data;
1544f6c8d242SRene Gollent 	data.descendants = descendants;
1545f6c8d242SRene Gollent 
1546f6c8d242SRene Gollent 	view->Perform(PERFORM_CODE_LAYOUT_INVALIDATED, &data);
1547466f2b8fSRene Gollent }
1548