xref: /haiku/src/kits/interface/TextControl.cpp (revision 1bdc2a52032e19f602b65e92e4ee5665fcd6d9f6)
1105644bfSAxel Dörfler /*
2991c062fSAxel Dörfler  * Copyright 2001-2008, Haiku Inc.
3105644bfSAxel Dörfler  * Distributed under the terms of the MIT License.
4105644bfSAxel Dörfler  *
5105644bfSAxel Dörfler  * Authors:
6105644bfSAxel Dörfler  *		Frans van Nispen (xlr8@tref.nl)
7105644bfSAxel Dörfler  *		Stephan Aßmus <superstippi@gmx.de>
89ecf9d1cSIngo Weinhold  *		Ingo Weinhold <bonefish@cs.tu-berlin.de>
9105644bfSAxel Dörfler  */
10105644bfSAxel Dörfler 
11991c062fSAxel Dörfler /*!	BTextControl displays text that can act like a control. */
12105644bfSAxel Dörfler 
13105644bfSAxel Dörfler 
1452a38012Sejakowatz #include <stdio.h>
1552a38012Sejakowatz 
169ecf9d1cSIngo Weinhold #include <AbstractLayoutItem.h>
179ecf9d1cSIngo Weinhold #include <LayoutUtils.h>
18058691d4SStefano Ceccherini #include <Message.h>
19455d1c46SAxel Dörfler #include <Region.h>
2052a38012Sejakowatz #include <TextControl.h>
2152a38012Sejakowatz #include <Window.h>
2252a38012Sejakowatz 
2352a38012Sejakowatz #include "TextInput.h"
2452a38012Sejakowatz 
2552a38012Sejakowatz 
269ecf9d1cSIngo Weinhold class BTextControl::LabelLayoutItem : public BAbstractLayoutItem {
279ecf9d1cSIngo Weinhold public:
289ecf9d1cSIngo Weinhold 								LabelLayoutItem(BTextControl* parent);
299ecf9d1cSIngo Weinhold 
309ecf9d1cSIngo Weinhold 	virtual	bool				IsVisible();
319ecf9d1cSIngo Weinhold 	virtual	void				SetVisible(bool visible);
329ecf9d1cSIngo Weinhold 
339ecf9d1cSIngo Weinhold 	virtual	BRect				Frame();
349ecf9d1cSIngo Weinhold 	virtual	void				SetFrame(BRect frame);
359ecf9d1cSIngo Weinhold 
369ecf9d1cSIngo Weinhold 	virtual	BView*				View();
379ecf9d1cSIngo Weinhold 
389ecf9d1cSIngo Weinhold 	virtual	BSize				BaseMinSize();
399ecf9d1cSIngo Weinhold 	virtual	BSize				BaseMaxSize();
409ecf9d1cSIngo Weinhold 	virtual	BSize				BasePreferredSize();
419ecf9d1cSIngo Weinhold 	virtual	BAlignment			BaseAlignment();
429ecf9d1cSIngo Weinhold 
439ecf9d1cSIngo Weinhold private:
449ecf9d1cSIngo Weinhold 			BTextControl*		fParent;
459ecf9d1cSIngo Weinhold 			BRect				fFrame;
469ecf9d1cSIngo Weinhold };
479ecf9d1cSIngo Weinhold 
489ecf9d1cSIngo Weinhold 
499ecf9d1cSIngo Weinhold class BTextControl::TextViewLayoutItem : public BAbstractLayoutItem {
509ecf9d1cSIngo Weinhold public:
519ecf9d1cSIngo Weinhold 								TextViewLayoutItem(BTextControl* parent);
529ecf9d1cSIngo Weinhold 
539ecf9d1cSIngo Weinhold 	virtual	bool				IsVisible();
549ecf9d1cSIngo Weinhold 	virtual	void				SetVisible(bool visible);
559ecf9d1cSIngo Weinhold 
569ecf9d1cSIngo Weinhold 	virtual	BRect				Frame();
579ecf9d1cSIngo Weinhold 	virtual	void				SetFrame(BRect frame);
589ecf9d1cSIngo Weinhold 
599ecf9d1cSIngo Weinhold 	virtual	BView*				View();
609ecf9d1cSIngo Weinhold 
619ecf9d1cSIngo Weinhold 	virtual	BSize				BaseMinSize();
629ecf9d1cSIngo Weinhold 	virtual	BSize				BaseMaxSize();
639ecf9d1cSIngo Weinhold 	virtual	BSize				BasePreferredSize();
649ecf9d1cSIngo Weinhold 	virtual	BAlignment			BaseAlignment();
659ecf9d1cSIngo Weinhold 
669ecf9d1cSIngo Weinhold private:
679ecf9d1cSIngo Weinhold 			BTextControl*		fParent;
689ecf9d1cSIngo Weinhold 			BRect				fFrame;
699ecf9d1cSIngo Weinhold };
709ecf9d1cSIngo Weinhold 
719ecf9d1cSIngo Weinhold 
729ecf9d1cSIngo Weinhold // #pragma mark -
739ecf9d1cSIngo Weinhold 
749ecf9d1cSIngo Weinhold 
7552a38012Sejakowatz BTextControl::BTextControl(BRect frame, const char* name, const char* label,
76991c062fSAxel Dörfler 		const char* text, BMessage* message, uint32 mask, uint32 flags)
779cb2dbe2SMarc Flerackers 	: BControl(frame, name, label, message, mask, flags | B_FRAME_EVENTS)
7852a38012Sejakowatz {
79ffe72abdSAxel Dörfler 	_InitData(label, text);
809ecf9d1cSIngo Weinhold 	_ValidateLayout();
819ecf9d1cSIngo Weinhold }
8252a38012Sejakowatz 
83105644bfSAxel Dörfler 
849ecf9d1cSIngo Weinhold BTextControl::BTextControl(const char* name, const char* label,
85991c062fSAxel Dörfler 		const char* text, BMessage* message, uint32 flags)
869ecf9d1cSIngo Weinhold 	: BControl(BRect(0, 0, -1, -1), name, label, message, B_FOLLOW_NONE,
879ecf9d1cSIngo Weinhold 		flags | B_FRAME_EVENTS | B_SUPPORTS_LAYOUT)
889ecf9d1cSIngo Weinhold {
899ecf9d1cSIngo Weinhold 	_InitData(label, text);
909ecf9d1cSIngo Weinhold 	_ValidateLayout();
919ecf9d1cSIngo Weinhold }
92105644bfSAxel Dörfler 
93ffe72abdSAxel Dörfler 
94991c062fSAxel Dörfler BTextControl::BTextControl(const char* label, const char* text,
95991c062fSAxel Dörfler 		BMessage* message)
969ecf9d1cSIngo Weinhold 	: BControl(BRect(0, 0, -1, -1), NULL, label, message, B_FOLLOW_NONE,
979ecf9d1cSIngo Weinhold 		B_WILL_DRAW | B_NAVIGABLE | B_FRAME_EVENTS | B_SUPPORTS_LAYOUT)
989ecf9d1cSIngo Weinhold {
999ecf9d1cSIngo Weinhold 	_InitData(label, text);
1009ecf9d1cSIngo Weinhold 	_ValidateLayout();
10152a38012Sejakowatz }
102058691d4SStefano Ceccherini 
103058691d4SStefano Ceccherini 
10452a38012Sejakowatz BTextControl::~BTextControl()
10552a38012Sejakowatz {
1069cb2dbe2SMarc Flerackers 	SetModificationMessage(NULL);
10752a38012Sejakowatz }
108058691d4SStefano Ceccherini 
109058691d4SStefano Ceccherini 
110ffe72abdSAxel Dörfler BTextControl::BTextControl(BMessage* archive)
111ffe72abdSAxel Dörfler 	: BControl(archive)
11252a38012Sejakowatz {
113ffe72abdSAxel Dörfler 	_InitData(Label(), NULL, archive);
11452a38012Sejakowatz 
115ffe72abdSAxel Dörfler 	int32 labelAlignment = B_ALIGN_LEFT;
116ffe72abdSAxel Dörfler 	int32 textAlignment = B_ALIGN_LEFT;
11752a38012Sejakowatz 
118ffe72abdSAxel Dörfler 	if (archive->HasInt32("_a_label"))
119ffe72abdSAxel Dörfler 		archive->FindInt32("_a_label", &labelAlignment);
12052a38012Sejakowatz 
121ffe72abdSAxel Dörfler 	if (archive->HasInt32("_a_text"))
122ffe72abdSAxel Dörfler 		archive->FindInt32("_a_text", &textAlignment);
12352a38012Sejakowatz 
124ffe72abdSAxel Dörfler 	SetAlignment((alignment)labelAlignment, (alignment)textAlignment);
1259cb2dbe2SMarc Flerackers 
126ffe72abdSAxel Dörfler 	if (archive->HasFloat("_divide"))
127ed1c257aSKarsten Heimrich 		archive->FindFloat("_divide", &fDivider);
1289cb2dbe2SMarc Flerackers 
129ffe72abdSAxel Dörfler 	if (archive->HasMessage("_mod_msg")) {
130ffe72abdSAxel Dörfler 		BMessage* message = new BMessage;
131ffe72abdSAxel Dörfler 		archive->FindMessage("_mod_msg", message);
132ffe72abdSAxel Dörfler 		SetModificationMessage(message);
1339cb2dbe2SMarc Flerackers 	}
13452a38012Sejakowatz }
135058691d4SStefano Ceccherini 
136058691d4SStefano Ceccherini 
137058691d4SStefano Ceccherini BArchivable*
138058691d4SStefano Ceccherini BTextControl::Instantiate(BMessage* archive)
13952a38012Sejakowatz {
1409cb2dbe2SMarc Flerackers 	if (validate_instantiation(archive, "BTextControl"))
1419cb2dbe2SMarc Flerackers 		return new BTextControl(archive);
142991c062fSAxel Dörfler 
14352a38012Sejakowatz 	return NULL;
14452a38012Sejakowatz }
145058691d4SStefano Ceccherini 
146058691d4SStefano Ceccherini 
147058691d4SStefano Ceccherini status_t
148058691d4SStefano Ceccherini BTextControl::Archive(BMessage *data, bool deep) const
14952a38012Sejakowatz {
1503a543720SJérôme Duval 	status_t ret = BControl::Archive(data, deep);
151058691d4SStefano Ceccherini 	alignment labelAlignment, textAlignment;
15252a38012Sejakowatz 
153058691d4SStefano Ceccherini 	GetAlignment(&labelAlignment, &textAlignment);
1549cb2dbe2SMarc Flerackers 
15511d7ecebSJérôme Duval 	if (ret == B_OK)
15611d7ecebSJérôme Duval 		ret = data->AddInt32("_a_label", labelAlignment);
15711d7ecebSJérôme Duval 	if (ret == B_OK)
15811d7ecebSJérôme Duval 		ret = data->AddInt32("_a_text", textAlignment);
15911d7ecebSJérôme Duval 	if (ret == B_OK)
16011d7ecebSJérôme Duval 		ret = data->AddFloat("_divide", Divider());
1619cb2dbe2SMarc Flerackers 
16211d7ecebSJérôme Duval 	if (ModificationMessage() && (ret == B_OK))
16311d7ecebSJérôme Duval 		ret = data->AddMessage("_mod_msg", ModificationMessage());
1649cb2dbe2SMarc Flerackers 
16511d7ecebSJérôme Duval 	return ret;
16652a38012Sejakowatz }
167058691d4SStefano Ceccherini 
168058691d4SStefano Ceccherini 
169058691d4SStefano Ceccherini void
170058691d4SStefano Ceccherini BTextControl::SetText(const char *text)
17152a38012Sejakowatz {
1729cb2dbe2SMarc Flerackers 	if (InvokeKind() != B_CONTROL_INVOKED)
1739cb2dbe2SMarc Flerackers 		return;
1749cb2dbe2SMarc Flerackers 
17552a38012Sejakowatz 	fText->SetText(text);
1769cb2dbe2SMarc Flerackers 
1779cb2dbe2SMarc Flerackers 	if (IsFocus())
1789cb2dbe2SMarc Flerackers 		fText->SetInitialText();
1799cb2dbe2SMarc Flerackers 
1809cb2dbe2SMarc Flerackers 	fText->Invalidate();
18152a38012Sejakowatz }
182058691d4SStefano Ceccherini 
183058691d4SStefano Ceccherini 
184058691d4SStefano Ceccherini const char *
185058691d4SStefano Ceccherini BTextControl::Text() const
18652a38012Sejakowatz {
18752a38012Sejakowatz 	return fText->Text();
18852a38012Sejakowatz }
189058691d4SStefano Ceccherini 
190058691d4SStefano Ceccherini 
191058691d4SStefano Ceccherini void
192058691d4SStefano Ceccherini BTextControl::SetValue(int32 value)
19352a38012Sejakowatz {
1949cb2dbe2SMarc Flerackers 	BControl::SetValue(value);
19552a38012Sejakowatz }
196058691d4SStefano Ceccherini 
197058691d4SStefano Ceccherini 
198058691d4SStefano Ceccherini status_t
199058691d4SStefano Ceccherini BTextControl::Invoke(BMessage *message)
20052a38012Sejakowatz {
201058691d4SStefano Ceccherini 	return BControl::Invoke(message);
20252a38012Sejakowatz }
203058691d4SStefano Ceccherini 
204058691d4SStefano Ceccherini 
205058691d4SStefano Ceccherini BTextView *
206058691d4SStefano Ceccherini BTextControl::TextView() const
20752a38012Sejakowatz {
2089cb2dbe2SMarc Flerackers 	return fText;
20952a38012Sejakowatz }
210058691d4SStefano Ceccherini 
211058691d4SStefano Ceccherini 
212058691d4SStefano Ceccherini void
213058691d4SStefano Ceccherini BTextControl::SetModificationMessage(BMessage *message)
21452a38012Sejakowatz {
2159cb2dbe2SMarc Flerackers 	delete fModificationMessage;
21652a38012Sejakowatz 	fModificationMessage = message;
21752a38012Sejakowatz }
218058691d4SStefano Ceccherini 
219058691d4SStefano Ceccherini 
220058691d4SStefano Ceccherini BMessage *
221058691d4SStefano Ceccherini BTextControl::ModificationMessage() const
22252a38012Sejakowatz {
22352a38012Sejakowatz 	return fModificationMessage;
22452a38012Sejakowatz }
225058691d4SStefano Ceccherini 
226058691d4SStefano Ceccherini 
227058691d4SStefano Ceccherini void
228058691d4SStefano Ceccherini BTextControl::SetAlignment(alignment labelAlignment, alignment textAlignment)
22952a38012Sejakowatz {
230058691d4SStefano Ceccherini 	fText->SetAlignment(textAlignment);
2319cb2dbe2SMarc Flerackers 	fText->AlignTextRect();
2329cb2dbe2SMarc Flerackers 
233058691d4SStefano Ceccherini 	if (fLabelAlign != labelAlignment) {
234058691d4SStefano Ceccherini 		fLabelAlign = labelAlignment;
2359cb2dbe2SMarc Flerackers 		Invalidate();
2369cb2dbe2SMarc Flerackers 	}
23752a38012Sejakowatz }
238058691d4SStefano Ceccherini 
239058691d4SStefano Ceccherini 
240058691d4SStefano Ceccherini void
241c432fbbbSAxel Dörfler BTextControl::GetAlignment(alignment* _label, alignment* _text) const
24252a38012Sejakowatz {
243c432fbbbSAxel Dörfler 	if (_label)
244c432fbbbSAxel Dörfler 		*_label = fLabelAlign;
245c432fbbbSAxel Dörfler 	if (_text)
246c432fbbbSAxel Dörfler 		*_text = fText->Alignment();
24752a38012Sejakowatz }
2489cb2dbe2SMarc Flerackers 
249058691d4SStefano Ceccherini 
250058691d4SStefano Ceccherini void
251058691d4SStefano Ceccherini BTextControl::SetDivider(float dividingLine)
252058691d4SStefano Ceccherini {
253a431f44bSStephan Aßmus 	fDivider = floorf(dividingLine + 0.5);
2542e6a5805SStephan Aßmus 
255a431f44bSStephan Aßmus 	_LayoutTextView();
25652a38012Sejakowatz 
257058691d4SStefano Ceccherini 	if (Window()) {
25852a38012Sejakowatz 		fText->Invalidate();
25952a38012Sejakowatz 		Invalidate();
26052a38012Sejakowatz 	}
2619cb2dbe2SMarc Flerackers }
262058691d4SStefano Ceccherini 
263058691d4SStefano Ceccherini 
264058691d4SStefano Ceccherini float
265058691d4SStefano Ceccherini BTextControl::Divider() const
26652a38012Sejakowatz {
26752a38012Sejakowatz 	return fDivider;
26852a38012Sejakowatz }
269058691d4SStefano Ceccherini 
270058691d4SStefano Ceccherini 
271058691d4SStefano Ceccherini void
272058691d4SStefano Ceccherini BTextControl::Draw(BRect updateRect)
27352a38012Sejakowatz {
274c432fbbbSAxel Dörfler 	rgb_color noTint = ui_color(B_PANEL_BACKGROUND_COLOR);
275c432fbbbSAxel Dörfler 	rgb_color lighten1 = tint_color(noTint, B_LIGHTEN_1_TINT);
276c432fbbbSAxel Dörfler 	rgb_color lighten2 = tint_color(noTint, B_LIGHTEN_2_TINT);
277c432fbbbSAxel Dörfler 	rgb_color lightenMax = tint_color(noTint, B_LIGHTEN_MAX_TINT);
278c432fbbbSAxel Dörfler 	rgb_color darken1 = tint_color(noTint, B_DARKEN_1_TINT);
279c432fbbbSAxel Dörfler 	rgb_color darken2 = tint_color(noTint, B_DARKEN_2_TINT);
280c432fbbbSAxel Dörfler 	rgb_color darken4 = tint_color(noTint, B_DARKEN_4_TINT);
281c432fbbbSAxel Dörfler 	rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
2829cb2dbe2SMarc Flerackers 
2839cb2dbe2SMarc Flerackers 	bool enabled = IsEnabled();
2849cb2dbe2SMarc Flerackers 	bool active = false;
2859cb2dbe2SMarc Flerackers 
2869cb2dbe2SMarc Flerackers 	if (fText->IsFocus() && Window()->IsActive())
2879cb2dbe2SMarc Flerackers 		active = true;
2889cb2dbe2SMarc Flerackers 
289455d1c46SAxel Dörfler 	// outer bevel
290455d1c46SAxel Dörfler 
291a431f44bSStephan Aßmus 	BRect rect = fText->Frame();
292a431f44bSStephan Aßmus 	rect.InsetBy(-2, -2);
293455d1c46SAxel Dörfler 
294455d1c46SAxel Dörfler 	if (enabled)
295455d1c46SAxel Dörfler 		SetHighColor(darken1);
296455d1c46SAxel Dörfler 	else
297455d1c46SAxel Dörfler 		SetHighColor(noTint);
298455d1c46SAxel Dörfler 
299455d1c46SAxel Dörfler 	StrokeLine(rect.LeftBottom(), rect.LeftTop());
300455d1c46SAxel Dörfler 	StrokeLine(rect.RightTop());
301455d1c46SAxel Dörfler 
302455d1c46SAxel Dörfler 	if (enabled)
303455d1c46SAxel Dörfler 		SetHighColor(lighten2);
304455d1c46SAxel Dörfler 	else
305455d1c46SAxel Dörfler 		SetHighColor(lighten1);
306455d1c46SAxel Dörfler 
307455d1c46SAxel Dörfler 	StrokeLine(BPoint(rect.left + 1.0f, rect.bottom), rect.RightBottom());
308455d1c46SAxel Dörfler 	StrokeLine(BPoint(rect.right, rect.top + 1.0f), rect.RightBottom());
309455d1c46SAxel Dörfler 
310455d1c46SAxel Dörfler 	// inner bevel
311455d1c46SAxel Dörfler 
312455d1c46SAxel Dörfler 	rect.InsetBy(1.0f, 1.0f);
3139cb2dbe2SMarc Flerackers 
314058691d4SStefano Ceccherini 	if (active) {
315105644bfSAxel Dörfler 		SetHighColor(navigationColor);
3169cb2dbe2SMarc Flerackers 		StrokeRect(rect);
317058691d4SStefano Ceccherini 	} else {
3189cb2dbe2SMarc Flerackers 		if (enabled)
3199cb2dbe2SMarc Flerackers 			SetHighColor(darken4);
3209cb2dbe2SMarc Flerackers 		else
3219cb2dbe2SMarc Flerackers 			SetHighColor(darken2);
3229cb2dbe2SMarc Flerackers 
3239cb2dbe2SMarc Flerackers 		StrokeLine(rect.LeftTop(), rect.LeftBottom());
3249cb2dbe2SMarc Flerackers 		StrokeLine(rect.LeftTop(), rect.RightTop());
3259cb2dbe2SMarc Flerackers 
326105644bfSAxel Dörfler 		SetHighColor(noTint);
3279cb2dbe2SMarc Flerackers 		StrokeLine(BPoint(rect.left + 1.0f, rect.bottom), rect.RightBottom());
3289cb2dbe2SMarc Flerackers 		StrokeLine(BPoint(rect.right, rect.top + 1.0f));
3299cb2dbe2SMarc Flerackers 	}
3309cb2dbe2SMarc Flerackers 
3317a25fcafSStefano Ceccherini 	// label
3327a25fcafSStefano Ceccherini 
333058691d4SStefano Ceccherini 	if (Label()) {
334a68292ddSStephan Aßmus 		font_height fontHeight;
335a68292ddSStephan Aßmus 		GetFontHeight(&fontHeight);
3369cb2dbe2SMarc Flerackers 
337a68292ddSStephan Aßmus 		float y = Bounds().top + (Bounds().Height() + 1 - fontHeight.ascent
338a68292ddSStephan Aßmus 			- fontHeight.descent) / 2 + fontHeight.ascent;
33952a38012Sejakowatz 		float x;
3409cb2dbe2SMarc Flerackers 
3417a25fcafSStefano Ceccherini 		float labelWidth = StringWidth(Label());
342058691d4SStefano Ceccherini 		switch (fLabelAlign) {
34352a38012Sejakowatz 			case B_ALIGN_RIGHT:
344b8872c02SStephan Aßmus 				x = fDivider - labelWidth - 3.0;
34552a38012Sejakowatz 				break;
34652a38012Sejakowatz 
34752a38012Sejakowatz 			case B_ALIGN_CENTER:
348b8872c02SStephan Aßmus 				x = fDivider - labelWidth / 2.0;
34952a38012Sejakowatz 				break;
35052a38012Sejakowatz 
35152a38012Sejakowatz 			default:
352b8872c02SStephan Aßmus 				x = 0.0;
35352a38012Sejakowatz 				break;
35452a38012Sejakowatz 		}
35552a38012Sejakowatz 
3562c5a8894SStephan Aßmus 		BRect labelArea(x, Bounds().top, x + labelWidth, Bounds().bottom);
3577a25fcafSStefano Ceccherini 		if (x < fDivider && updateRect.Intersects(labelArea)) {
3582c5a8894SStephan Aßmus 			labelArea.right = fText->Frame().left - 3;
3597a25fcafSStefano Ceccherini 
3607a25fcafSStefano Ceccherini 			BRegion clipRegion(labelArea);
3617a25fcafSStefano Ceccherini 			ConstrainClippingRegion(&clipRegion);
362c432fbbbSAxel Dörfler 			SetHighColor(IsEnabled() ? ui_color(B_CONTROL_TEXT_COLOR)
363fa815db3SAxel Dörfler 				: tint_color(noTint, B_DISABLED_LABEL_TINT));
36452a38012Sejakowatz 			DrawString(Label(), BPoint(x, y));
36552a38012Sejakowatz 		}
36652a38012Sejakowatz 	}
3677a25fcafSStefano Ceccherini }
368058691d4SStefano Ceccherini 
369058691d4SStefano Ceccherini 
370058691d4SStefano Ceccherini void
371058691d4SStefano Ceccherini BTextControl::MouseDown(BPoint where)
37252a38012Sejakowatz {
373058691d4SStefano Ceccherini 	if (!fText->IsFocus()) {
3749cb2dbe2SMarc Flerackers 		fText->MakeFocus(true);
37552a38012Sejakowatz 	}
37652a38012Sejakowatz }
377058691d4SStefano Ceccherini 
378058691d4SStefano Ceccherini 
379058691d4SStefano Ceccherini void
380058691d4SStefano Ceccherini BTextControl::AttachedToWindow()
38152a38012Sejakowatz {
38252a38012Sejakowatz 	BControl::AttachedToWindow();
38352a38012Sejakowatz 
38479c35b39SAxel Dörfler 	_UpdateTextViewColors(IsEnabled());
3853a3f6c1eSAxel Dörfler 	fText->MakeEditable(IsEnabled());
38652a38012Sejakowatz }
387058691d4SStefano Ceccherini 
388058691d4SStefano Ceccherini 
389058691d4SStefano Ceccherini void
390058691d4SStefano Ceccherini BTextControl::MakeFocus(bool state)
39152a38012Sejakowatz {
3926d8d6cadSStephan Aßmus 	if (state != fText->IsFocus()) {
39352a38012Sejakowatz 		fText->MakeFocus(state);
3949cb2dbe2SMarc Flerackers 
3959cb2dbe2SMarc Flerackers 		if (state)
3969cb2dbe2SMarc Flerackers 			fText->SelectAll();
39752a38012Sejakowatz 	}
3986d8d6cadSStephan Aßmus }
399058691d4SStefano Ceccherini 
400058691d4SStefano Ceccherini 
401058691d4SStefano Ceccherini void
40279c35b39SAxel Dörfler BTextControl::SetEnabled(bool enabled)
40352a38012Sejakowatz {
40479c35b39SAxel Dörfler 	if (IsEnabled() == enabled)
4059cb2dbe2SMarc Flerackers 		return;
4069cb2dbe2SMarc Flerackers 
407058691d4SStefano Ceccherini 	if (Window()) {
40879c35b39SAxel Dörfler 		fText->MakeEditable(enabled);
4099cb2dbe2SMarc Flerackers 
41079c35b39SAxel Dörfler 		_UpdateTextViewColors(enabled);
4119cb2dbe2SMarc Flerackers 
4129cb2dbe2SMarc Flerackers 		fText->Invalidate();
4139cb2dbe2SMarc Flerackers 		Window()->UpdateIfNeeded();
4149cb2dbe2SMarc Flerackers 	}
4159cb2dbe2SMarc Flerackers 
41679c35b39SAxel Dörfler 	BControl::SetEnabled(enabled);
41752a38012Sejakowatz }
418058691d4SStefano Ceccherini 
419058691d4SStefano Ceccherini 
420058691d4SStefano Ceccherini void
421105644bfSAxel Dörfler BTextControl::GetPreferredSize(float *_width, float *_height)
42252a38012Sejakowatz {
423105644bfSAxel Dörfler 	if (_height) {
424105644bfSAxel Dörfler 		// we need enough space for the label and the child text view
425105644bfSAxel Dörfler 		font_height fontHeight;
426105644bfSAxel Dörfler 		GetFontHeight(&fontHeight);
427105644bfSAxel Dörfler 		float labelHeight = ceil(fontHeight.ascent + fontHeight.descent
428105644bfSAxel Dörfler 			+ fontHeight.leading);
429b8872c02SStephan Aßmus 		float textHeight = ceilf(fText->LineHeight(0) + 1.0) + 4.0;
43052a38012Sejakowatz 
431105644bfSAxel Dörfler 		*_height = max_c(labelHeight, textHeight);
432105644bfSAxel Dörfler 	}
433105644bfSAxel Dörfler 
434105644bfSAxel Dörfler 	if (_width) {
435*1bdc2a52SKarsten Heimrich 		*_width = Bounds().Width();
436*1bdc2a52SKarsten Heimrich 		const char* label = Label();
437*1bdc2a52SKarsten Heimrich 		if (label) {
438*1bdc2a52SKarsten Heimrich 			float width = ceilf(StringWidth(label));
439*1bdc2a52SKarsten Heimrich 			*_width = (width * 1.3) + width + 4.0;
440*1bdc2a52SKarsten Heimrich 		}
441105644bfSAxel Dörfler 	}
44252a38012Sejakowatz }
443058691d4SStefano Ceccherini 
444058691d4SStefano Ceccherini 
445058691d4SStefano Ceccherini void
446058691d4SStefano Ceccherini BTextControl::ResizeToPreferred()
44752a38012Sejakowatz {
448105644bfSAxel Dörfler 	BView::ResizeToPreferred();
449*1bdc2a52SKarsten Heimrich 
450*1bdc2a52SKarsten Heimrich 	fDivider = 0.0;
451*1bdc2a52SKarsten Heimrich 	const char* label = Label();
452*1bdc2a52SKarsten Heimrich 	if (label)
453*1bdc2a52SKarsten Heimrich 		fDivider = ceil(StringWidth(label)) + 2.0;
454*1bdc2a52SKarsten Heimrich 
455*1bdc2a52SKarsten Heimrich 	_LayoutTextView();
45652a38012Sejakowatz }
457058691d4SStefano Ceccherini 
458058691d4SStefano Ceccherini 
459058691d4SStefano Ceccherini void
460058691d4SStefano Ceccherini BTextControl::SetFlags(uint32 flags)
46152a38012Sejakowatz {
462058691d4SStefano Ceccherini 	if (!fSkipSetFlags) {
4639cb2dbe2SMarc Flerackers 		// If the textview is navigable, set it to not navigable if needed
4649cb2dbe2SMarc Flerackers 		// Else if it is not navigable, set it to navigable if needed
465058691d4SStefano Ceccherini 		if (fText->Flags() & B_NAVIGABLE) {
4669cb2dbe2SMarc Flerackers 			if (!(flags & B_NAVIGABLE))
4679cb2dbe2SMarc Flerackers 				fText->SetFlags(fText->Flags() & ~B_NAVIGABLE);
468058691d4SStefano Ceccherini 
469058691d4SStefano Ceccherini 		} else {
4709cb2dbe2SMarc Flerackers 			if (flags & B_NAVIGABLE)
4719cb2dbe2SMarc Flerackers 				fText->SetFlags(fText->Flags() | B_NAVIGABLE);
4729cb2dbe2SMarc Flerackers 		}
4739cb2dbe2SMarc Flerackers 
4749cb2dbe2SMarc Flerackers 		// Don't make this one navigable
4759cb2dbe2SMarc Flerackers 		flags &= ~B_NAVIGABLE;
4769cb2dbe2SMarc Flerackers 	}
4779cb2dbe2SMarc Flerackers 
47852a38012Sejakowatz 	BView::SetFlags(flags);
47952a38012Sejakowatz }
480058691d4SStefano Ceccherini 
481058691d4SStefano Ceccherini 
482058691d4SStefano Ceccherini void
483058691d4SStefano Ceccherini BTextControl::MessageReceived(BMessage *msg)
48452a38012Sejakowatz {
485058691d4SStefano Ceccherini 	switch(msg->what) {
4869cb2dbe2SMarc Flerackers 		case B_SET_PROPERTY:
4879cb2dbe2SMarc Flerackers 		case B_GET_PROPERTY:
4889cb2dbe2SMarc Flerackers 			// TODO
48952a38012Sejakowatz 			break;
49052a38012Sejakowatz 		default:
49152a38012Sejakowatz 			BControl::MessageReceived(msg);
49252a38012Sejakowatz 			break;
49352a38012Sejakowatz 	}
49452a38012Sejakowatz }
495058691d4SStefano Ceccherini 
496058691d4SStefano Ceccherini 
497058691d4SStefano Ceccherini BHandler *
498058691d4SStefano Ceccherini BTextControl::ResolveSpecifier(BMessage *msg, int32 index,
49952a38012Sejakowatz 										 BMessage *specifier, int32 form,
50052a38012Sejakowatz 										 const char *property)
50152a38012Sejakowatz {
5029cb2dbe2SMarc Flerackers 	/*
5039cb2dbe2SMarc Flerackers 	BPropertyInfo propInfo(prop_list);
5049cb2dbe2SMarc Flerackers 	BHandler *target = NULL;
5059cb2dbe2SMarc Flerackers 
5069cb2dbe2SMarc Flerackers 	if (propInfo.FindMatch(message, 0, specifier, what, property) < B_OK)
5079cb2dbe2SMarc Flerackers 		return BControl::ResolveSpecifier(message, index, specifier, what,
5089cb2dbe2SMarc Flerackers 			property);
5099cb2dbe2SMarc Flerackers 	else
5109cb2dbe2SMarc Flerackers 		return this;
5119cb2dbe2SMarc Flerackers 	*/
5129cb2dbe2SMarc Flerackers 	return BControl::ResolveSpecifier(msg, index, specifier, form, property);
51352a38012Sejakowatz }
514058691d4SStefano Ceccherini 
515058691d4SStefano Ceccherini 
516058691d4SStefano Ceccherini status_t
517058691d4SStefano Ceccherini BTextControl::GetSupportedSuites(BMessage *data)
51852a38012Sejakowatz {
5199cb2dbe2SMarc Flerackers 	return BControl::GetSupportedSuites(data);
52052a38012Sejakowatz }
521058691d4SStefano Ceccherini 
522058691d4SStefano Ceccherini 
523058691d4SStefano Ceccherini void
524058691d4SStefano Ceccherini BTextControl::MouseUp(BPoint pt)
52552a38012Sejakowatz {
52652a38012Sejakowatz 	BControl::MouseUp(pt);
52752a38012Sejakowatz }
528058691d4SStefano Ceccherini 
529058691d4SStefano Ceccherini 
530058691d4SStefano Ceccherini void
531058691d4SStefano Ceccherini BTextControl::MouseMoved(BPoint pt, uint32 code, const BMessage *msg)
53252a38012Sejakowatz {
53352a38012Sejakowatz 	BControl::MouseMoved(pt, code, msg);
53452a38012Sejakowatz }
535058691d4SStefano Ceccherini 
536058691d4SStefano Ceccherini 
537058691d4SStefano Ceccherini void
538058691d4SStefano Ceccherini BTextControl::DetachedFromWindow()
53952a38012Sejakowatz {
54052a38012Sejakowatz 	BControl::DetachedFromWindow();
54152a38012Sejakowatz }
542058691d4SStefano Ceccherini 
543058691d4SStefano Ceccherini 
544058691d4SStefano Ceccherini void
545058691d4SStefano Ceccherini BTextControl::AllAttached()
54652a38012Sejakowatz {
54752a38012Sejakowatz 	BControl::AllAttached();
54852a38012Sejakowatz }
549058691d4SStefano Ceccherini 
550058691d4SStefano Ceccherini 
551058691d4SStefano Ceccherini void
552058691d4SStefano Ceccherini BTextControl::AllDetached()
55352a38012Sejakowatz {
55452a38012Sejakowatz 	BControl::AllDetached();
55552a38012Sejakowatz }
556058691d4SStefano Ceccherini 
557058691d4SStefano Ceccherini 
558058691d4SStefano Ceccherini void
559058691d4SStefano Ceccherini BTextControl::FrameMoved(BPoint newPosition)
56052a38012Sejakowatz {
56152a38012Sejakowatz 	BControl::FrameMoved(newPosition);
56252a38012Sejakowatz }
563058691d4SStefano Ceccherini 
564058691d4SStefano Ceccherini 
565058691d4SStefano Ceccherini void
566ffe72abdSAxel Dörfler BTextControl::FrameResized(float width, float height)
56752a38012Sejakowatz {
568ffe72abdSAxel Dörfler 	BControl::FrameResized(width, height);
569ffe72abdSAxel Dörfler 
570ffe72abdSAxel Dörfler 	// changes in width
571ffe72abdSAxel Dörfler 
572ffe72abdSAxel Dörfler 	BRect bounds = Bounds();
573ffe72abdSAxel Dörfler 	const float border = 2.0f;
574ffe72abdSAxel Dörfler 
575ffe72abdSAxel Dörfler 	if (bounds.Width() > fPreviousWidth) {
576ffe72abdSAxel Dörfler 		// invalidate the region between the old and the new right border
577ffe72abdSAxel Dörfler 		BRect rect = bounds;
578ffe72abdSAxel Dörfler 		rect.left += fPreviousWidth - border;
579ffe72abdSAxel Dörfler 		rect.right--;
580ffe72abdSAxel Dörfler 		Invalidate(rect);
581ffe72abdSAxel Dörfler 	} else if (bounds.Width() < fPreviousWidth) {
582ffe72abdSAxel Dörfler 		// invalidate the region of the new right border
583ffe72abdSAxel Dörfler 		BRect rect = bounds;
584ffe72abdSAxel Dörfler 		rect.left = rect.right - border;
585ffe72abdSAxel Dörfler 		Invalidate(rect);
586ffe72abdSAxel Dörfler 	}
587ffe72abdSAxel Dörfler 
588ffe72abdSAxel Dörfler 	// changes in height
589ffe72abdSAxel Dörfler 
590ffe72abdSAxel Dörfler 	if (bounds.Height() > fPreviousHeight) {
591ffe72abdSAxel Dörfler 		// invalidate the region between the old and the new bottom border
592ffe72abdSAxel Dörfler 		BRect rect = bounds;
593ffe72abdSAxel Dörfler 		rect.top += fPreviousHeight - border;
594ffe72abdSAxel Dörfler 		rect.bottom--;
595ffe72abdSAxel Dörfler 		Invalidate(rect);
596ffe72abdSAxel Dörfler 	} else if (bounds.Height() < fPreviousHeight) {
597ffe72abdSAxel Dörfler 		// invalidate the region of the new bottom border
598ffe72abdSAxel Dörfler 		BRect rect = bounds;
599ffe72abdSAxel Dörfler 		rect.top = rect.bottom - border;
600ffe72abdSAxel Dörfler 		Invalidate(rect);
601ffe72abdSAxel Dörfler 	}
602ffe72abdSAxel Dörfler 
603ffe72abdSAxel Dörfler 	fPreviousWidth = uint16(bounds.Width());
604ffe72abdSAxel Dörfler 	fPreviousHeight = uint16(bounds.Height());
60552a38012Sejakowatz }
606058691d4SStefano Ceccherini 
607058691d4SStefano Ceccherini 
608058691d4SStefano Ceccherini void
609058691d4SStefano Ceccherini BTextControl::WindowActivated(bool active)
61052a38012Sejakowatz {
6116d8d6cadSStephan Aßmus 	if (fText->IsFocus()) {
612dde10e45SStephan Aßmus 		// invalidate to remove/show focus indication
6132c5a8894SStephan Aßmus 		BRect rect = fText->Frame();
6142c5a8894SStephan Aßmus 		rect.InsetBy(-1, -1);
6156d8d6cadSStephan Aßmus 		Invalidate(rect);
616dde10e45SStephan Aßmus 
617dde10e45SStephan Aßmus 		// help out embedded text view which doesn't
618dde10e45SStephan Aßmus 		// get notified of this
619dde10e45SStephan Aßmus 		fText->Invalidate();
6206d8d6cadSStephan Aßmus 	}
62152a38012Sejakowatz }
622058691d4SStefano Ceccherini 
623058691d4SStefano Ceccherini 
624058691d4SStefano Ceccherini status_t
625058691d4SStefano Ceccherini BTextControl::Perform(perform_code d, void *arg)
62652a38012Sejakowatz {
62752a38012Sejakowatz 	return BControl::Perform(d, arg);
62852a38012Sejakowatz }
629058691d4SStefano Ceccherini 
630058691d4SStefano Ceccherini 
6319ecf9d1cSIngo Weinhold BLayoutItem*
6329ecf9d1cSIngo Weinhold BTextControl::CreateLabelLayoutItem()
6339ecf9d1cSIngo Weinhold {
6349ecf9d1cSIngo Weinhold 	if (!fLabelLayoutItem)
6359ecf9d1cSIngo Weinhold 		fLabelLayoutItem = new LabelLayoutItem(this);
6369ecf9d1cSIngo Weinhold 	return fLabelLayoutItem;
6379ecf9d1cSIngo Weinhold }
6389ecf9d1cSIngo Weinhold 
6399ecf9d1cSIngo Weinhold 
6409ecf9d1cSIngo Weinhold BLayoutItem*
6419ecf9d1cSIngo Weinhold BTextControl::CreateTextViewLayoutItem()
6429ecf9d1cSIngo Weinhold {
6439ecf9d1cSIngo Weinhold 	if (!fTextViewLayoutItem)
6449ecf9d1cSIngo Weinhold 		fTextViewLayoutItem = new TextViewLayoutItem(this);
6459ecf9d1cSIngo Weinhold 	return fTextViewLayoutItem;
6469ecf9d1cSIngo Weinhold }
6479ecf9d1cSIngo Weinhold 
6489ecf9d1cSIngo Weinhold 
6499cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl1() {}
6509cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl2() {}
6519cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl3() {}
6529cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl4() {}
653058691d4SStefano Ceccherini 
654058691d4SStefano Ceccherini 
655058691d4SStefano Ceccherini BTextControl &
656058691d4SStefano Ceccherini BTextControl::operator=(const BTextControl&)
65752a38012Sejakowatz {
65852a38012Sejakowatz 	return *this;
65952a38012Sejakowatz }
660058691d4SStefano Ceccherini 
661058691d4SStefano Ceccherini 
662058691d4SStefano Ceccherini void
66379c35b39SAxel Dörfler BTextControl::_UpdateTextViewColors(bool enabled)
6643a3f6c1eSAxel Dörfler {
6653a3f6c1eSAxel Dörfler 	rgb_color textColor;
666aae7000dSAxel Dörfler 	rgb_color color;
6673a3f6c1eSAxel Dörfler 	BFont font;
6683a3f6c1eSAxel Dörfler 
669aae7000dSAxel Dörfler 	fText->GetFontAndColor(0, &font);
6703a3f6c1eSAxel Dörfler 
6713a3f6c1eSAxel Dörfler 	if (enabled)
672aae7000dSAxel Dörfler 		textColor = ui_color(B_DOCUMENT_TEXT_COLOR);
67312aefeb4SAxel Dörfler 	else {
67412aefeb4SAxel Dörfler 		textColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
67512aefeb4SAxel Dörfler 			B_DISABLED_LABEL_TINT);
67612aefeb4SAxel Dörfler 	}
6773a3f6c1eSAxel Dörfler 
6783a3f6c1eSAxel Dörfler 	fText->SetFontAndColor(&font, B_FONT_ALL, &textColor);
6793a3f6c1eSAxel Dörfler 
6803a3f6c1eSAxel Dörfler 	if (enabled) {
681aae7000dSAxel Dörfler 		color = ui_color(B_DOCUMENT_BACKGROUND_COLOR);
6823a3f6c1eSAxel Dörfler 	} else {
6833a3f6c1eSAxel Dörfler 		color = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
6843a3f6c1eSAxel Dörfler 			B_LIGHTEN_2_TINT);
6853a3f6c1eSAxel Dörfler 	}
6863a3f6c1eSAxel Dörfler 
6873a3f6c1eSAxel Dörfler 	fText->SetViewColor(color);
6883a3f6c1eSAxel Dörfler 	fText->SetLowColor(color);
6893a3f6c1eSAxel Dörfler }
6903a3f6c1eSAxel Dörfler 
6913a3f6c1eSAxel Dörfler 
6923a3f6c1eSAxel Dörfler void
693ffe72abdSAxel Dörfler BTextControl::_CommitValue()
6949cb2dbe2SMarc Flerackers {
6959cb2dbe2SMarc Flerackers }
696058691d4SStefano Ceccherini 
697058691d4SStefano Ceccherini 
698058691d4SStefano Ceccherini void
699ffe72abdSAxel Dörfler BTextControl::_InitData(const char* label, const char* initialText,
700ffe72abdSAxel Dörfler 	BMessage* archive)
7019cb2dbe2SMarc Flerackers {
7029cb2dbe2SMarc Flerackers 	BRect bounds(Bounds());
7039cb2dbe2SMarc Flerackers 
7049cb2dbe2SMarc Flerackers 	fText = NULL;
7059cb2dbe2SMarc Flerackers 	fModificationMessage = NULL;
7069cb2dbe2SMarc Flerackers 	fLabelAlign = B_ALIGN_LEFT;
7079cb2dbe2SMarc Flerackers 	fDivider = 0.0f;
708ffe72abdSAxel Dörfler 	fPreviousWidth = bounds.Width();
709ffe72abdSAxel Dörfler 	fPreviousHeight = bounds.Height();
7109ecf9d1cSIngo Weinhold 	fLabelLayoutItem = NULL;
7119ecf9d1cSIngo Weinhold 	fTextViewLayoutItem = NULL;
7129cb2dbe2SMarc Flerackers 	fSkipSetFlags = false;
7139cb2dbe2SMarc Flerackers 
7149cb2dbe2SMarc Flerackers 	int32 flags = 0;
7159cb2dbe2SMarc Flerackers 
716918a22d9SDarkWyrm 	BFont font(be_plain_font);
7179cb2dbe2SMarc Flerackers 
718ffe72abdSAxel Dörfler 	if (!archive || !archive->HasString("_fname"))
719058691d4SStefano Ceccherini 		flags |= B_FONT_FAMILY_AND_STYLE;
7209cb2dbe2SMarc Flerackers 
721ffe72abdSAxel Dörfler 	if (!archive || !archive->HasFloat("_fflt"))
722058691d4SStefano Ceccherini 		flags |= B_FONT_SIZE;
7239cb2dbe2SMarc Flerackers 
7249cb2dbe2SMarc Flerackers 	if (flags != 0)
7259cb2dbe2SMarc Flerackers 		SetFont(&font, flags);
7269cb2dbe2SMarc Flerackers 
7279cb2dbe2SMarc Flerackers 	if (label)
7282e6a5805SStephan Aßmus 		fDivider = floorf(bounds.Width() / 2.0f);
7299cb2dbe2SMarc Flerackers 
730105644bfSAxel Dörfler 	uint32 navigableFlags = Flags() & B_NAVIGABLE;
731105644bfSAxel Dörfler 	if (navigableFlags != 0) {
7329cb2dbe2SMarc Flerackers 		fSkipSetFlags = true;
7339cb2dbe2SMarc Flerackers 		SetFlags(Flags() & ~B_NAVIGABLE);
7349cb2dbe2SMarc Flerackers 		fSkipSetFlags = false;
7359cb2dbe2SMarc Flerackers 	}
7369cb2dbe2SMarc Flerackers 
737ffe72abdSAxel Dörfler 	if (archive)
738b8872c02SStephan Aßmus 		fText = static_cast<BPrivate::_BTextInput_*>(FindView("_input_"));
739991c062fSAxel Dörfler 
740991c062fSAxel Dörfler 	if (fText == NULL) {
741ee2a3473SStephan Aßmus 		BRect frame(fDivider, bounds.top, bounds.right, bounds.bottom);
742105644bfSAxel Dörfler 		// we are stroking the frame around the text view, which
7432e6a5805SStephan Aßmus 		// is 2 pixels wide
74447b3e74eSStefano Ceccherini 		frame.InsetBy(2.0, 3.0);
745111b4fbcSStefano Ceccherini 		BRect textRect(frame.OffsetToCopy(B_ORIGIN));
7469cb2dbe2SMarc Flerackers 
747b8872c02SStephan Aßmus 		fText = new BPrivate::_BTextInput_(frame, textRect,
7487a70a2d6SStephan Aßmus 			B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
749105644bfSAxel Dörfler 			B_WILL_DRAW | B_FRAME_EVENTS | navigableFlags);
7509cb2dbe2SMarc Flerackers 		AddChild(fText);
7519cb2dbe2SMarc Flerackers 
752455d1c46SAxel Dörfler 		SetText(initialText);
7539cb2dbe2SMarc Flerackers 		fText->SetAlignment(B_ALIGN_LEFT);
7549cb2dbe2SMarc Flerackers 		fText->AlignTextRect();
7559cb2dbe2SMarc Flerackers 	}
7569cb2dbe2SMarc Flerackers }
7579ecf9d1cSIngo Weinhold 
7589ecf9d1cSIngo Weinhold 
7599ecf9d1cSIngo Weinhold void
7609ecf9d1cSIngo Weinhold BTextControl::_ValidateLayout()
7619ecf9d1cSIngo Weinhold {
762*1bdc2a52SKarsten Heimrich 	float width, height;
763*1bdc2a52SKarsten Heimrich 	BTextControl::GetPreferredSize(&width, &height);
7649ecf9d1cSIngo Weinhold 
765*1bdc2a52SKarsten Heimrich 	ResizeTo(width, height);
7669ecf9d1cSIngo Weinhold 
767a431f44bSStephan Aßmus 	_LayoutTextView();
7689ecf9d1cSIngo Weinhold 
7699ecf9d1cSIngo Weinhold 	fPreviousHeight = Bounds().Height();
7709ecf9d1cSIngo Weinhold }
7719ecf9d1cSIngo Weinhold 
7729ecf9d1cSIngo Weinhold 
7739ecf9d1cSIngo Weinhold void
774a431f44bSStephan Aßmus BTextControl::_LayoutTextView()
775a431f44bSStephan Aßmus {
776a431f44bSStephan Aßmus 	BRect frame = Bounds();
777a431f44bSStephan Aßmus 	frame.left = fDivider;
778a431f44bSStephan Aßmus 	// we are stroking the frame around the text view, which
779a431f44bSStephan Aßmus 	// is 2 pixels wide
780a431f44bSStephan Aßmus 	frame.InsetBy(2.0, 2.0);
781a431f44bSStephan Aßmus 	fText->MoveTo(frame.left, frame.top);
782a431f44bSStephan Aßmus 	fText->ResizeTo(frame.Width(), frame.Height());
783b8872c02SStephan Aßmus 	fText->AlignTextRect();
784a431f44bSStephan Aßmus }
785a431f44bSStephan Aßmus 
786a431f44bSStephan Aßmus 
787a431f44bSStephan Aßmus void
7889ecf9d1cSIngo Weinhold BTextControl::_UpdateFrame()
7899ecf9d1cSIngo Weinhold {
7909ecf9d1cSIngo Weinhold 	if (fLabelLayoutItem && fTextViewLayoutItem) {
7919ecf9d1cSIngo Weinhold 		BRect labelFrame = fLabelLayoutItem->Frame();
7929ecf9d1cSIngo Weinhold 		BRect textFrame = fTextViewLayoutItem->Frame();
7939ecf9d1cSIngo Weinhold 		MoveTo(labelFrame.left, labelFrame.top);
7949ecf9d1cSIngo Weinhold 		ResizeTo(textFrame.left + textFrame.Width() - labelFrame.left,
7959ecf9d1cSIngo Weinhold 			textFrame.top + textFrame.Height() - labelFrame.top);
7969ecf9d1cSIngo Weinhold 		SetDivider(textFrame.left - labelFrame.left);
7979ecf9d1cSIngo Weinhold 	}
7989ecf9d1cSIngo Weinhold }
7999ecf9d1cSIngo Weinhold 
8009ecf9d1cSIngo Weinhold 
8019ecf9d1cSIngo Weinhold // #pragma mark -
8029ecf9d1cSIngo Weinhold 
8039ecf9d1cSIngo Weinhold 
8049ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::LabelLayoutItem(BTextControl* parent)
8059ecf9d1cSIngo Weinhold 	: fParent(parent),
8069ecf9d1cSIngo Weinhold 	  fFrame()
8079ecf9d1cSIngo Weinhold {
8089ecf9d1cSIngo Weinhold }
8099ecf9d1cSIngo Weinhold 
8109ecf9d1cSIngo Weinhold 
8119ecf9d1cSIngo Weinhold bool
8129ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::IsVisible()
8139ecf9d1cSIngo Weinhold {
8149ecf9d1cSIngo Weinhold 	return !fParent->IsHidden(fParent);
8159ecf9d1cSIngo Weinhold }
8169ecf9d1cSIngo Weinhold 
8179ecf9d1cSIngo Weinhold 
8189ecf9d1cSIngo Weinhold void
8199ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::SetVisible(bool visible)
8209ecf9d1cSIngo Weinhold {
8219ecf9d1cSIngo Weinhold 	// not allowed
8229ecf9d1cSIngo Weinhold }
8239ecf9d1cSIngo Weinhold 
8249ecf9d1cSIngo Weinhold 
8259ecf9d1cSIngo Weinhold BRect
8269ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::Frame()
8279ecf9d1cSIngo Weinhold {
8289ecf9d1cSIngo Weinhold 	return fFrame;
8299ecf9d1cSIngo Weinhold }
8309ecf9d1cSIngo Weinhold 
8319ecf9d1cSIngo Weinhold 
8329ecf9d1cSIngo Weinhold void
8339ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::SetFrame(BRect frame)
8349ecf9d1cSIngo Weinhold {
8359ecf9d1cSIngo Weinhold 	fFrame = frame;
8369ecf9d1cSIngo Weinhold 	fParent->_UpdateFrame();
8379ecf9d1cSIngo Weinhold }
8389ecf9d1cSIngo Weinhold 
8399ecf9d1cSIngo Weinhold 
8409ecf9d1cSIngo Weinhold BView*
8419ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::View()
8429ecf9d1cSIngo Weinhold {
8439ecf9d1cSIngo Weinhold 	return fParent;
8449ecf9d1cSIngo Weinhold }
8459ecf9d1cSIngo Weinhold 
8469ecf9d1cSIngo Weinhold 
8479ecf9d1cSIngo Weinhold BSize
8489ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BaseMinSize()
8499ecf9d1cSIngo Weinhold {
8509ecf9d1cSIngo Weinhold // TODO: Cache the info. Might be too expensive for this call.
8519ecf9d1cSIngo Weinhold 	const char* label = fParent->Label();
8529ecf9d1cSIngo Weinhold 	if (!label)
8539ecf9d1cSIngo Weinhold 		return BSize(-1, -1);
8549ecf9d1cSIngo Weinhold 
8559ecf9d1cSIngo Weinhold 	BSize size;
8569ecf9d1cSIngo Weinhold 	fParent->GetPreferredSize(NULL, &size.height);
8579ecf9d1cSIngo Weinhold 
8589ecf9d1cSIngo Weinhold 	size.width = fParent->StringWidth(label) + 2 * 3 - 1;
8599ecf9d1cSIngo Weinhold 
8609ecf9d1cSIngo Weinhold 	return size;
8619ecf9d1cSIngo Weinhold }
8629ecf9d1cSIngo Weinhold 
8639ecf9d1cSIngo Weinhold 
8649ecf9d1cSIngo Weinhold BSize
8659ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BaseMaxSize()
8669ecf9d1cSIngo Weinhold {
8679ecf9d1cSIngo Weinhold 	return BaseMinSize();
8689ecf9d1cSIngo Weinhold }
8699ecf9d1cSIngo Weinhold 
8709ecf9d1cSIngo Weinhold 
8719ecf9d1cSIngo Weinhold BSize
8729ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BasePreferredSize()
8739ecf9d1cSIngo Weinhold {
8749ecf9d1cSIngo Weinhold 	return BaseMinSize();
8759ecf9d1cSIngo Weinhold }
8769ecf9d1cSIngo Weinhold 
8779ecf9d1cSIngo Weinhold 
8789ecf9d1cSIngo Weinhold BAlignment
8799ecf9d1cSIngo Weinhold BTextControl::LabelLayoutItem::BaseAlignment()
8809ecf9d1cSIngo Weinhold {
8819ecf9d1cSIngo Weinhold 	return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
8829ecf9d1cSIngo Weinhold }
8839ecf9d1cSIngo Weinhold 
8849ecf9d1cSIngo Weinhold 
8859ecf9d1cSIngo Weinhold // #pragma mark -
8869ecf9d1cSIngo Weinhold 
8879ecf9d1cSIngo Weinhold 
8889ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::TextViewLayoutItem(BTextControl* parent)
8899ecf9d1cSIngo Weinhold 	: fParent(parent),
8909ecf9d1cSIngo Weinhold 	  fFrame()
8919ecf9d1cSIngo Weinhold {
8929ecf9d1cSIngo Weinhold }
8939ecf9d1cSIngo Weinhold 
8949ecf9d1cSIngo Weinhold 
8959ecf9d1cSIngo Weinhold bool
8969ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::IsVisible()
8979ecf9d1cSIngo Weinhold {
8989ecf9d1cSIngo Weinhold 	return !fParent->IsHidden(fParent);
8999ecf9d1cSIngo Weinhold }
9009ecf9d1cSIngo Weinhold 
9019ecf9d1cSIngo Weinhold 
9029ecf9d1cSIngo Weinhold void
9039ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::SetVisible(bool visible)
9049ecf9d1cSIngo Weinhold {
9059ecf9d1cSIngo Weinhold 	// not allowed
9069ecf9d1cSIngo Weinhold }
9079ecf9d1cSIngo Weinhold 
9089ecf9d1cSIngo Weinhold 
9099ecf9d1cSIngo Weinhold BRect
9109ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::Frame()
9119ecf9d1cSIngo Weinhold {
9129ecf9d1cSIngo Weinhold 	return fFrame;
9139ecf9d1cSIngo Weinhold }
9149ecf9d1cSIngo Weinhold 
9159ecf9d1cSIngo Weinhold 
9169ecf9d1cSIngo Weinhold void
9179ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::SetFrame(BRect frame)
9189ecf9d1cSIngo Weinhold {
9199ecf9d1cSIngo Weinhold 	fFrame = frame;
9209ecf9d1cSIngo Weinhold 	fParent->_UpdateFrame();
9219ecf9d1cSIngo Weinhold }
9229ecf9d1cSIngo Weinhold 
9239ecf9d1cSIngo Weinhold 
9249ecf9d1cSIngo Weinhold BView*
9259ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::View()
9269ecf9d1cSIngo Weinhold {
9279ecf9d1cSIngo Weinhold 	return fParent;
9289ecf9d1cSIngo Weinhold }
9299ecf9d1cSIngo Weinhold 
9309ecf9d1cSIngo Weinhold 
9319ecf9d1cSIngo Weinhold BSize
9329ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BaseMinSize()
9339ecf9d1cSIngo Weinhold {
9349ecf9d1cSIngo Weinhold // TODO: Cache the info. Might be too expensive for this call.
9359ecf9d1cSIngo Weinhold 	BSize size;
9369ecf9d1cSIngo Weinhold 	fParent->GetPreferredSize(NULL, &size.height);
9379ecf9d1cSIngo Weinhold 
9389ecf9d1cSIngo Weinhold 	// mmh, some arbitrary minimal width
9399ecf9d1cSIngo Weinhold 	size.width = 30;
9409ecf9d1cSIngo Weinhold 
9419ecf9d1cSIngo Weinhold 	return size;
9429ecf9d1cSIngo Weinhold }
9439ecf9d1cSIngo Weinhold 
9449ecf9d1cSIngo Weinhold 
9459ecf9d1cSIngo Weinhold BSize
9469ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BaseMaxSize()
9479ecf9d1cSIngo Weinhold {
9489ecf9d1cSIngo Weinhold 	BSize size(BaseMinSize());
9499ecf9d1cSIngo Weinhold 	size.width = B_SIZE_UNLIMITED;
9509ecf9d1cSIngo Weinhold 	return size;
9519ecf9d1cSIngo Weinhold }
9529ecf9d1cSIngo Weinhold 
9539ecf9d1cSIngo Weinhold 
9549ecf9d1cSIngo Weinhold BSize
9559ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BasePreferredSize()
9569ecf9d1cSIngo Weinhold {
9579ecf9d1cSIngo Weinhold 	BSize size(BaseMinSize());
9589ecf9d1cSIngo Weinhold 	// puh, no idea...
9599ecf9d1cSIngo Weinhold 	size.width = 100;
9609ecf9d1cSIngo Weinhold 	return size;
9619ecf9d1cSIngo Weinhold }
9629ecf9d1cSIngo Weinhold 
9639ecf9d1cSIngo Weinhold 
9649ecf9d1cSIngo Weinhold BAlignment
9659ecf9d1cSIngo Weinhold BTextControl::TextViewLayoutItem::BaseAlignment()
9669ecf9d1cSIngo Weinhold {
9679ecf9d1cSIngo Weinhold 	return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
9689ecf9d1cSIngo Weinhold }
9699ecf9d1cSIngo Weinhold 
970