xref: /haiku/src/kits/interface/TextControl.cpp (revision 11d7ecebd0255943e4b27c2fe94174c30d00385d)
1105644bfSAxel Dörfler /*
2105644bfSAxel Dörfler  * Copyright 2001-2005, 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>
8105644bfSAxel Dörfler  */
9105644bfSAxel Dörfler 
10105644bfSAxel Dörfler /**	BTextControl displays text that can act like a control. */
11105644bfSAxel Dörfler 
12105644bfSAxel Dörfler 
1352a38012Sejakowatz #include <stdio.h>
1452a38012Sejakowatz 
15058691d4SStefano Ceccherini #include <Message.h>
16455d1c46SAxel Dörfler #include <Region.h>
1752a38012Sejakowatz #include <TextControl.h>
1852a38012Sejakowatz #include <Window.h>
1952a38012Sejakowatz 
2052a38012Sejakowatz #include "TextInput.h"
2152a38012Sejakowatz 
2252a38012Sejakowatz 
2352a38012Sejakowatz BTextControl::BTextControl(BRect frame, const char *name, const char *label,
2452a38012Sejakowatz 						   const char *text, BMessage *message, uint32 mask,
2552a38012Sejakowatz 						   uint32 flags)
269cb2dbe2SMarc Flerackers 	: BControl(frame, name, label, message, mask, flags | B_FRAME_EVENTS)
2752a38012Sejakowatz {
28ffe72abdSAxel Dörfler 	_InitData(label, text);
2952a38012Sejakowatz 
30105644bfSAxel Dörfler 	float height;
31ee001e26SAxel Dörfler 	BTextControl::GetPreferredSize(NULL, &height);
32105644bfSAxel Dörfler 
33105644bfSAxel Dörfler 	ResizeTo(Bounds().Width(), height);
34105644bfSAxel Dörfler 
35455d1c46SAxel Dörfler 	float lineHeight = ceil(fText->LineHeight(0));
36105644bfSAxel Dörfler 	fText->ResizeTo(fText->Bounds().Width(), lineHeight);
37105644bfSAxel Dörfler 	fText->MoveTo(fText->Frame().left, (height - lineHeight) / 2);
38ffe72abdSAxel Dörfler 
39ffe72abdSAxel Dörfler 	fPreviousHeight = Bounds().Height();
4052a38012Sejakowatz }
41058691d4SStefano Ceccherini 
42058691d4SStefano Ceccherini 
4352a38012Sejakowatz BTextControl::~BTextControl()
4452a38012Sejakowatz {
459cb2dbe2SMarc Flerackers 	SetModificationMessage(NULL);
4652a38012Sejakowatz }
47058691d4SStefano Ceccherini 
48058691d4SStefano Ceccherini 
49ffe72abdSAxel Dörfler BTextControl::BTextControl(BMessage* archive)
50ffe72abdSAxel Dörfler 	: BControl(archive)
5152a38012Sejakowatz {
52ffe72abdSAxel Dörfler 	_InitData(Label(), NULL, archive);
5352a38012Sejakowatz 
54ffe72abdSAxel Dörfler 	int32 labelAlignment = B_ALIGN_LEFT;
55ffe72abdSAxel Dörfler 	int32 textAlignment = B_ALIGN_LEFT;
5652a38012Sejakowatz 
57ffe72abdSAxel Dörfler 	if (archive->HasInt32("_a_label"))
58ffe72abdSAxel Dörfler 		archive->FindInt32("_a_label", &labelAlignment);
5952a38012Sejakowatz 
60ffe72abdSAxel Dörfler 	if (archive->HasInt32("_a_text"))
61ffe72abdSAxel Dörfler 		archive->FindInt32("_a_text", &textAlignment);
6252a38012Sejakowatz 
63ffe72abdSAxel Dörfler 	SetAlignment((alignment)labelAlignment, (alignment)textAlignment);
649cb2dbe2SMarc Flerackers 
65ffe72abdSAxel Dörfler 	if (archive->HasFloat("_divide"))
66ffe72abdSAxel Dörfler 		archive->FindFloat("_a_text", &fDivider);
679cb2dbe2SMarc Flerackers 
68ffe72abdSAxel Dörfler 	if (archive->HasMessage("_mod_msg")) {
69ffe72abdSAxel Dörfler 		BMessage* message = new BMessage;
70ffe72abdSAxel Dörfler 		archive->FindMessage("_mod_msg", message);
71ffe72abdSAxel Dörfler 		SetModificationMessage(message);
729cb2dbe2SMarc Flerackers 	}
7352a38012Sejakowatz }
74058691d4SStefano Ceccherini 
75058691d4SStefano Ceccherini 
76058691d4SStefano Ceccherini BArchivable *
77058691d4SStefano Ceccherini BTextControl::Instantiate(BMessage *archive)
7852a38012Sejakowatz {
799cb2dbe2SMarc Flerackers 	if (validate_instantiation(archive, "BTextControl"))
809cb2dbe2SMarc Flerackers 		return new BTextControl(archive);
819cb2dbe2SMarc Flerackers 	else
8252a38012Sejakowatz 		return NULL;
8352a38012Sejakowatz }
84058691d4SStefano Ceccherini 
85058691d4SStefano Ceccherini 
86058691d4SStefano Ceccherini status_t
87058691d4SStefano Ceccherini BTextControl::Archive(BMessage *data, bool deep) const
8852a38012Sejakowatz {
89*11d7ecebSJérôme Duval 	status_t ret = BView::Archive(data, deep);
90058691d4SStefano Ceccherini 	alignment labelAlignment, textAlignment;
9152a38012Sejakowatz 
92058691d4SStefano Ceccherini 	GetAlignment(&labelAlignment, &textAlignment);
939cb2dbe2SMarc Flerackers 
94*11d7ecebSJérôme Duval 	if (ret == B_OK)
95*11d7ecebSJérôme Duval 		ret = data->AddInt32("_a_label", labelAlignment);
96*11d7ecebSJérôme Duval 	if (ret == B_OK)
97*11d7ecebSJérôme Duval 		ret = data->AddInt32("_a_text", textAlignment);
98*11d7ecebSJérôme Duval 	if (ret == B_OK)
99*11d7ecebSJérôme Duval 		ret = data->AddFloat("_divide", Divider());
1009cb2dbe2SMarc Flerackers 
101*11d7ecebSJérôme Duval 	if (ModificationMessage() && (ret == B_OK))
102*11d7ecebSJérôme Duval 		ret = data->AddMessage("_mod_msg", ModificationMessage());
1039cb2dbe2SMarc Flerackers 
104*11d7ecebSJérôme Duval 	return ret;
10552a38012Sejakowatz }
106058691d4SStefano Ceccherini 
107058691d4SStefano Ceccherini 
108058691d4SStefano Ceccherini void
109058691d4SStefano Ceccherini BTextControl::SetText(const char *text)
11052a38012Sejakowatz {
1119cb2dbe2SMarc Flerackers 	if (InvokeKind() != B_CONTROL_INVOKED)
1129cb2dbe2SMarc Flerackers 		return;
1139cb2dbe2SMarc Flerackers 
11452a38012Sejakowatz 	fText->SetText(text);
1159cb2dbe2SMarc Flerackers 
1169cb2dbe2SMarc Flerackers 	if (IsFocus())
1179cb2dbe2SMarc Flerackers 		fText->SetInitialText();
1189cb2dbe2SMarc Flerackers 
1199cb2dbe2SMarc Flerackers 	fText->Invalidate();
12052a38012Sejakowatz }
121058691d4SStefano Ceccherini 
122058691d4SStefano Ceccherini 
123058691d4SStefano Ceccherini const char *
124058691d4SStefano Ceccherini BTextControl::Text() const
12552a38012Sejakowatz {
12652a38012Sejakowatz 	return fText->Text();
12752a38012Sejakowatz }
128058691d4SStefano Ceccherini 
129058691d4SStefano Ceccherini 
130058691d4SStefano Ceccherini void
131058691d4SStefano Ceccherini BTextControl::SetValue(int32 value)
13252a38012Sejakowatz {
1339cb2dbe2SMarc Flerackers 	BControl::SetValue(value);
13452a38012Sejakowatz }
135058691d4SStefano Ceccherini 
136058691d4SStefano Ceccherini 
137058691d4SStefano Ceccherini status_t
138058691d4SStefano Ceccherini BTextControl::Invoke(BMessage *message)
13952a38012Sejakowatz {
140058691d4SStefano Ceccherini 	return BControl::Invoke(message);
14152a38012Sejakowatz }
142058691d4SStefano Ceccherini 
143058691d4SStefano Ceccherini 
144058691d4SStefano Ceccherini BTextView *
145058691d4SStefano Ceccherini BTextControl::TextView() const
14652a38012Sejakowatz {
1479cb2dbe2SMarc Flerackers 	return fText;
14852a38012Sejakowatz }
149058691d4SStefano Ceccherini 
150058691d4SStefano Ceccherini 
151058691d4SStefano Ceccherini void
152058691d4SStefano Ceccherini BTextControl::SetModificationMessage(BMessage *message)
15352a38012Sejakowatz {
1549cb2dbe2SMarc Flerackers 	delete fModificationMessage;
15552a38012Sejakowatz 	fModificationMessage = message;
15652a38012Sejakowatz }
157058691d4SStefano Ceccherini 
158058691d4SStefano Ceccherini 
159058691d4SStefano Ceccherini BMessage *
160058691d4SStefano Ceccherini BTextControl::ModificationMessage() const
16152a38012Sejakowatz {
16252a38012Sejakowatz 	return fModificationMessage;
16352a38012Sejakowatz }
164058691d4SStefano Ceccherini 
165058691d4SStefano Ceccherini 
166058691d4SStefano Ceccherini void
167058691d4SStefano Ceccherini BTextControl::SetAlignment(alignment labelAlignment, alignment textAlignment)
16852a38012Sejakowatz {
169058691d4SStefano Ceccherini 	fText->SetAlignment(textAlignment);
1709cb2dbe2SMarc Flerackers 	fText->AlignTextRect();
1719cb2dbe2SMarc Flerackers 
172058691d4SStefano Ceccherini 	if (fLabelAlign != labelAlignment) {
173058691d4SStefano Ceccherini 		fLabelAlign = labelAlignment;
1749cb2dbe2SMarc Flerackers 		Invalidate();
1759cb2dbe2SMarc Flerackers 	}
17652a38012Sejakowatz }
177058691d4SStefano Ceccherini 
178058691d4SStefano Ceccherini 
179058691d4SStefano Ceccherini void
180c432fbbbSAxel Dörfler BTextControl::GetAlignment(alignment* _label, alignment* _text) const
18152a38012Sejakowatz {
182c432fbbbSAxel Dörfler 	if (_label)
183c432fbbbSAxel Dörfler 		*_label = fLabelAlign;
184c432fbbbSAxel Dörfler 	if (_text)
185c432fbbbSAxel Dörfler 		*_text = fText->Alignment();
18652a38012Sejakowatz }
1879cb2dbe2SMarc Flerackers 
188058691d4SStefano Ceccherini 
189058691d4SStefano Ceccherini void
190058691d4SStefano Ceccherini BTextControl::SetDivider(float dividingLine)
191058691d4SStefano Ceccherini {
1922e6a5805SStephan Aßmus 	dividingLine = floorf(dividingLine + 0.5);
1932e6a5805SStephan Aßmus 
194058691d4SStefano Ceccherini 	float dx = fDivider - dividingLine;
195058691d4SStefano Ceccherini 
196058691d4SStefano Ceccherini 	fDivider = dividingLine;
19752a38012Sejakowatz 
1989cb2dbe2SMarc Flerackers 	fText->MoveBy(-dx, 0.0f);
1999cb2dbe2SMarc Flerackers 	fText->ResizeBy(dx, 0.0f);
20052a38012Sejakowatz 
201058691d4SStefano Ceccherini 	if (Window()) {
20252a38012Sejakowatz 		fText->Invalidate();
20352a38012Sejakowatz 		Invalidate();
20452a38012Sejakowatz 	}
2059cb2dbe2SMarc Flerackers }
206058691d4SStefano Ceccherini 
207058691d4SStefano Ceccherini 
208058691d4SStefano Ceccherini float
209058691d4SStefano Ceccherini BTextControl::Divider() const
21052a38012Sejakowatz {
21152a38012Sejakowatz 	return fDivider;
21252a38012Sejakowatz }
213058691d4SStefano Ceccherini 
214058691d4SStefano Ceccherini 
215058691d4SStefano Ceccherini void
216058691d4SStefano Ceccherini BTextControl::Draw(BRect updateRect)
21752a38012Sejakowatz {
218c432fbbbSAxel Dörfler 	rgb_color noTint = ui_color(B_PANEL_BACKGROUND_COLOR);
219c432fbbbSAxel Dörfler 	rgb_color lighten1 = tint_color(noTint, B_LIGHTEN_1_TINT);
220c432fbbbSAxel Dörfler 	rgb_color lighten2 = tint_color(noTint, B_LIGHTEN_2_TINT);
221c432fbbbSAxel Dörfler 	rgb_color lightenMax = tint_color(noTint, B_LIGHTEN_MAX_TINT);
222c432fbbbSAxel Dörfler 	rgb_color darken1 = tint_color(noTint, B_DARKEN_1_TINT);
223c432fbbbSAxel Dörfler 	rgb_color darken2 = tint_color(noTint, B_DARKEN_2_TINT);
224c432fbbbSAxel Dörfler 	rgb_color darken4 = tint_color(noTint, B_DARKEN_4_TINT);
225c432fbbbSAxel Dörfler 	rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
2269cb2dbe2SMarc Flerackers 
2279cb2dbe2SMarc Flerackers 	bool enabled = IsEnabled();
2289cb2dbe2SMarc Flerackers 	bool active = false;
2299cb2dbe2SMarc Flerackers 
2309cb2dbe2SMarc Flerackers 	if (fText->IsFocus() && Window()->IsActive())
2319cb2dbe2SMarc Flerackers 		active = true;
2329cb2dbe2SMarc Flerackers 
233455d1c46SAxel Dörfler 	// outer bevel
234455d1c46SAxel Dörfler 
235455d1c46SAxel Dörfler 	BRect rect = Bounds();
236455d1c46SAxel Dörfler 	rect.left = fDivider;
237455d1c46SAxel Dörfler 
238455d1c46SAxel Dörfler 	if (enabled)
239455d1c46SAxel Dörfler 		SetHighColor(darken1);
240455d1c46SAxel Dörfler 	else
241455d1c46SAxel Dörfler 		SetHighColor(noTint);
242455d1c46SAxel Dörfler 
243455d1c46SAxel Dörfler 	StrokeLine(rect.LeftBottom(), rect.LeftTop());
244455d1c46SAxel Dörfler 	StrokeLine(rect.RightTop());
245455d1c46SAxel Dörfler 
246455d1c46SAxel Dörfler 	if (enabled)
247455d1c46SAxel Dörfler 		SetHighColor(lighten2);
248455d1c46SAxel Dörfler 	else
249455d1c46SAxel Dörfler 		SetHighColor(lighten1);
250455d1c46SAxel Dörfler 
251455d1c46SAxel Dörfler 	StrokeLine(BPoint(rect.left + 1.0f, rect.bottom), rect.RightBottom());
252455d1c46SAxel Dörfler 	StrokeLine(BPoint(rect.right, rect.top + 1.0f), rect.RightBottom());
253455d1c46SAxel Dörfler 
254455d1c46SAxel Dörfler 	// inner bevel
255455d1c46SAxel Dörfler 
256455d1c46SAxel Dörfler 	rect.InsetBy(1.0f, 1.0f);
2579cb2dbe2SMarc Flerackers 
258058691d4SStefano Ceccherini 	if (active) {
259105644bfSAxel Dörfler 		SetHighColor(navigationColor);
2609cb2dbe2SMarc Flerackers 		StrokeRect(rect);
261058691d4SStefano Ceccherini 	} else {
2629cb2dbe2SMarc Flerackers 		if (enabled)
2639cb2dbe2SMarc Flerackers 			SetHighColor(darken4);
2649cb2dbe2SMarc Flerackers 		else
2659cb2dbe2SMarc Flerackers 			SetHighColor(darken2);
2669cb2dbe2SMarc Flerackers 
2679cb2dbe2SMarc Flerackers 		StrokeLine(rect.LeftTop(), rect.LeftBottom());
2689cb2dbe2SMarc Flerackers 		StrokeLine(rect.LeftTop(), rect.RightTop());
2699cb2dbe2SMarc Flerackers 
270105644bfSAxel Dörfler 		SetHighColor(noTint);
2719cb2dbe2SMarc Flerackers 		StrokeLine(BPoint(rect.left + 1.0f, rect.bottom), rect.RightBottom());
2729cb2dbe2SMarc Flerackers 		StrokeLine(BPoint(rect.right, rect.top + 1.0f));
2739cb2dbe2SMarc Flerackers 	}
2749cb2dbe2SMarc Flerackers 
275455d1c46SAxel Dörfler 	// area around text view
2769cb2dbe2SMarc Flerackers 
277455d1c46SAxel Dörfler 	SetHighColor(fText->ViewColor());
278455d1c46SAxel Dörfler 	rect.InsetBy(1, 1);
279455d1c46SAxel Dörfler 	BRegion region(rect);
280455d1c46SAxel Dörfler 	BRegion updateRegion(updateRect);
281455d1c46SAxel Dörfler 		// why is there no IntersectWith(BRect &) version?
282455d1c46SAxel Dörfler 	region.IntersectWith(&updateRegion);
283111b4fbcSStefano Ceccherini 	region.Exclude(fText->Frame());
2840efe29e0SStefano Ceccherini 	FillRegion(&region);
28552a38012Sejakowatz 
2867a25fcafSStefano Ceccherini 	// label
2877a25fcafSStefano Ceccherini 
288058691d4SStefano Ceccherini 	if (Label()) {
289105644bfSAxel Dörfler 		font_height fontHeight;
290105644bfSAxel Dörfler 		GetFontHeight(&fontHeight);
2919cb2dbe2SMarc Flerackers 
292105644bfSAxel Dörfler 		float y = fontHeight.ascent + fText->Frame().top + 1;
29352a38012Sejakowatz 		float x;
2949cb2dbe2SMarc Flerackers 
2957a25fcafSStefano Ceccherini 		float labelWidth = StringWidth(Label());
296058691d4SStefano Ceccherini 		switch (fLabelAlign) {
29752a38012Sejakowatz 			case B_ALIGN_RIGHT:
2987a25fcafSStefano Ceccherini 				x = fDivider - labelWidth - 3.0f;
29952a38012Sejakowatz 				break;
30052a38012Sejakowatz 
30152a38012Sejakowatz 			case B_ALIGN_CENTER:
3027a25fcafSStefano Ceccherini 				x = fDivider - labelWidth / 2.0f;
30352a38012Sejakowatz 				break;
30452a38012Sejakowatz 
30552a38012Sejakowatz 			default:
30652a38012Sejakowatz 				x = 3.0f;
30752a38012Sejakowatz 				break;
30852a38012Sejakowatz 		}
30952a38012Sejakowatz 
3107a25fcafSStefano Ceccherini 		BRect labelArea(x, fText->Frame().top, x + labelWidth,
3117a25fcafSStefano Ceccherini 				ceilf(fontHeight.ascent + fontHeight.descent) + 1);
3127a25fcafSStefano Ceccherini 		if (x < fDivider && updateRect.Intersects(labelArea)) {
3137a25fcafSStefano Ceccherini 			labelArea.right = fDivider;
3147a25fcafSStefano Ceccherini 
3157a25fcafSStefano Ceccherini 			BRegion clipRegion(labelArea);
3167a25fcafSStefano Ceccherini 			ConstrainClippingRegion(&clipRegion);
317c432fbbbSAxel Dörfler 			SetHighColor(IsEnabled() ? ui_color(B_CONTROL_TEXT_COLOR)
318fa815db3SAxel Dörfler 				: tint_color(noTint, B_DISABLED_LABEL_TINT));
31952a38012Sejakowatz 			DrawString(Label(), BPoint(x, y));
32052a38012Sejakowatz 		}
32152a38012Sejakowatz 	}
3227a25fcafSStefano Ceccherini }
323058691d4SStefano Ceccherini 
324058691d4SStefano Ceccherini 
325058691d4SStefano Ceccherini void
326058691d4SStefano Ceccherini BTextControl::MouseDown(BPoint where)
32752a38012Sejakowatz {
328058691d4SStefano Ceccherini 	if (!fText->IsFocus()) {
3299cb2dbe2SMarc Flerackers 		fText->MakeFocus(true);
3309cb2dbe2SMarc Flerackers 		fText->SelectAll();
33152a38012Sejakowatz 	}
33252a38012Sejakowatz }
333058691d4SStefano Ceccherini 
334058691d4SStefano Ceccherini 
335058691d4SStefano Ceccherini void
336058691d4SStefano Ceccherini BTextControl::AttachedToWindow()
33752a38012Sejakowatz {
33852a38012Sejakowatz 	BControl::AttachedToWindow();
33952a38012Sejakowatz 
34079c35b39SAxel Dörfler 	_UpdateTextViewColors(IsEnabled());
3413a3f6c1eSAxel Dörfler 	fText->MakeEditable(IsEnabled());
34252a38012Sejakowatz }
343058691d4SStefano Ceccherini 
344058691d4SStefano Ceccherini 
345058691d4SStefano Ceccherini void
346058691d4SStefano Ceccherini BTextControl::MakeFocus(bool state)
34752a38012Sejakowatz {
3486d8d6cadSStephan Aßmus 	if (state != fText->IsFocus()) {
34952a38012Sejakowatz 		fText->MakeFocus(state);
3509cb2dbe2SMarc Flerackers 
3519cb2dbe2SMarc Flerackers 		if (state)
3529cb2dbe2SMarc Flerackers 			fText->SelectAll();
35352a38012Sejakowatz 	}
3546d8d6cadSStephan Aßmus }
355058691d4SStefano Ceccherini 
356058691d4SStefano Ceccherini 
357058691d4SStefano Ceccherini void
35879c35b39SAxel Dörfler BTextControl::SetEnabled(bool enabled)
35952a38012Sejakowatz {
36079c35b39SAxel Dörfler 	if (IsEnabled() == enabled)
3619cb2dbe2SMarc Flerackers 		return;
3629cb2dbe2SMarc Flerackers 
363058691d4SStefano Ceccherini 	if (Window()) {
36479c35b39SAxel Dörfler 		fText->MakeEditable(enabled);
3659cb2dbe2SMarc Flerackers 
36679c35b39SAxel Dörfler 		_UpdateTextViewColors(enabled);
3679cb2dbe2SMarc Flerackers 
3689cb2dbe2SMarc Flerackers 		fText->Invalidate();
3699cb2dbe2SMarc Flerackers 		Window()->UpdateIfNeeded();
3709cb2dbe2SMarc Flerackers 	}
3719cb2dbe2SMarc Flerackers 
37279c35b39SAxel Dörfler 	BControl::SetEnabled(enabled);
37352a38012Sejakowatz }
374058691d4SStefano Ceccherini 
375058691d4SStefano Ceccherini 
376058691d4SStefano Ceccherini void
377105644bfSAxel Dörfler BTextControl::GetPreferredSize(float *_width, float *_height)
37852a38012Sejakowatz {
379105644bfSAxel Dörfler 	if (_height) {
380105644bfSAxel Dörfler 		// we need enough space for the label and the child text view
381105644bfSAxel Dörfler 		font_height fontHeight;
382105644bfSAxel Dörfler 		GetFontHeight(&fontHeight);
383105644bfSAxel Dörfler 		float labelHeight = ceil(fontHeight.ascent + fontHeight.descent
384105644bfSAxel Dörfler 			+ fontHeight.leading);
385105644bfSAxel Dörfler 		float textHeight = fText->LineHeight(0) + 4.0;
38652a38012Sejakowatz 
387105644bfSAxel Dörfler 		*_height = max_c(labelHeight, textHeight);
388105644bfSAxel Dörfler 	}
389105644bfSAxel Dörfler 
390105644bfSAxel Dörfler 	if (_width) {
39152a38012Sejakowatz 		// TODO: this one I need to find out
392105644bfSAxel Dörfler 		float width = 20.0f + ceilf(StringWidth(Label()));
393105644bfSAxel Dörfler 		if (width < Bounds().Width())
394105644bfSAxel Dörfler 			width = Bounds().Width();
395105644bfSAxel Dörfler 		*_width = width;
396105644bfSAxel Dörfler 	}
39752a38012Sejakowatz }
398058691d4SStefano Ceccherini 
399058691d4SStefano Ceccherini 
400058691d4SStefano Ceccherini void
401058691d4SStefano Ceccherini BTextControl::ResizeToPreferred()
40252a38012Sejakowatz {
403105644bfSAxel Dörfler 	// TODO: change divider?
404105644bfSAxel Dörfler 	BView::ResizeToPreferred();
40552a38012Sejakowatz }
406058691d4SStefano Ceccherini 
407058691d4SStefano Ceccherini 
408058691d4SStefano Ceccherini void
409058691d4SStefano Ceccherini BTextControl::SetFlags(uint32 flags)
41052a38012Sejakowatz {
411058691d4SStefano Ceccherini 	if (!fSkipSetFlags) {
4129cb2dbe2SMarc Flerackers 		// If the textview is navigable, set it to not navigable if needed
4139cb2dbe2SMarc Flerackers 		// Else if it is not navigable, set it to navigable if needed
414058691d4SStefano Ceccherini 		if (fText->Flags() & B_NAVIGABLE) {
4159cb2dbe2SMarc Flerackers 			if (!(flags & B_NAVIGABLE))
4169cb2dbe2SMarc Flerackers 				fText->SetFlags(fText->Flags() & ~B_NAVIGABLE);
417058691d4SStefano Ceccherini 
418058691d4SStefano Ceccherini 		} else {
4199cb2dbe2SMarc Flerackers 			if (flags & B_NAVIGABLE)
4209cb2dbe2SMarc Flerackers 				fText->SetFlags(fText->Flags() | B_NAVIGABLE);
4219cb2dbe2SMarc Flerackers 		}
4229cb2dbe2SMarc Flerackers 
4239cb2dbe2SMarc Flerackers 		// Don't make this one navigable
4249cb2dbe2SMarc Flerackers 		flags &= ~B_NAVIGABLE;
4259cb2dbe2SMarc Flerackers 	}
4269cb2dbe2SMarc Flerackers 
42752a38012Sejakowatz 	BView::SetFlags(flags);
42852a38012Sejakowatz }
429058691d4SStefano Ceccherini 
430058691d4SStefano Ceccherini 
431058691d4SStefano Ceccherini void
432058691d4SStefano Ceccherini BTextControl::MessageReceived(BMessage *msg)
43352a38012Sejakowatz {
434058691d4SStefano Ceccherini 	switch(msg->what) {
4359cb2dbe2SMarc Flerackers 		case B_SET_PROPERTY:
4369cb2dbe2SMarc Flerackers 		case B_GET_PROPERTY:
4379cb2dbe2SMarc Flerackers 			// TODO
43852a38012Sejakowatz 			break;
43952a38012Sejakowatz 		default:
44052a38012Sejakowatz 			BControl::MessageReceived(msg);
44152a38012Sejakowatz 			break;
44252a38012Sejakowatz 	}
44352a38012Sejakowatz }
444058691d4SStefano Ceccherini 
445058691d4SStefano Ceccherini 
446058691d4SStefano Ceccherini BHandler *
447058691d4SStefano Ceccherini BTextControl::ResolveSpecifier(BMessage *msg, int32 index,
44852a38012Sejakowatz 										 BMessage *specifier, int32 form,
44952a38012Sejakowatz 										 const char *property)
45052a38012Sejakowatz {
4519cb2dbe2SMarc Flerackers 	/*
4529cb2dbe2SMarc Flerackers 	BPropertyInfo propInfo(prop_list);
4539cb2dbe2SMarc Flerackers 	BHandler *target = NULL;
4549cb2dbe2SMarc Flerackers 
4559cb2dbe2SMarc Flerackers 	if (propInfo.FindMatch(message, 0, specifier, what, property) < B_OK)
4569cb2dbe2SMarc Flerackers 		return BControl::ResolveSpecifier(message, index, specifier, what,
4579cb2dbe2SMarc Flerackers 			property);
4589cb2dbe2SMarc Flerackers 	else
4599cb2dbe2SMarc Flerackers 		return this;
4609cb2dbe2SMarc Flerackers 	*/
4619cb2dbe2SMarc Flerackers 	return BControl::ResolveSpecifier(msg, index, specifier, form, property);
46252a38012Sejakowatz }
463058691d4SStefano Ceccherini 
464058691d4SStefano Ceccherini 
465058691d4SStefano Ceccherini status_t
466058691d4SStefano Ceccherini BTextControl::GetSupportedSuites(BMessage *data)
46752a38012Sejakowatz {
4689cb2dbe2SMarc Flerackers 	return BControl::GetSupportedSuites(data);
46952a38012Sejakowatz }
470058691d4SStefano Ceccherini 
471058691d4SStefano Ceccherini 
472058691d4SStefano Ceccherini void
473058691d4SStefano Ceccherini BTextControl::MouseUp(BPoint pt)
47452a38012Sejakowatz {
47552a38012Sejakowatz 	BControl::MouseUp(pt);
47652a38012Sejakowatz }
477058691d4SStefano Ceccherini 
478058691d4SStefano Ceccherini 
479058691d4SStefano Ceccherini void
480058691d4SStefano Ceccherini BTextControl::MouseMoved(BPoint pt, uint32 code, const BMessage *msg)
48152a38012Sejakowatz {
48252a38012Sejakowatz 	BControl::MouseMoved(pt, code, msg);
48352a38012Sejakowatz }
484058691d4SStefano Ceccherini 
485058691d4SStefano Ceccherini 
486058691d4SStefano Ceccherini void
487058691d4SStefano Ceccherini BTextControl::DetachedFromWindow()
48852a38012Sejakowatz {
48952a38012Sejakowatz 	BControl::DetachedFromWindow();
49052a38012Sejakowatz }
491058691d4SStefano Ceccherini 
492058691d4SStefano Ceccherini 
493058691d4SStefano Ceccherini void
494058691d4SStefano Ceccherini BTextControl::AllAttached()
49552a38012Sejakowatz {
49652a38012Sejakowatz 	BControl::AllAttached();
49752a38012Sejakowatz }
498058691d4SStefano Ceccherini 
499058691d4SStefano Ceccherini 
500058691d4SStefano Ceccherini void
501058691d4SStefano Ceccherini BTextControl::AllDetached()
50252a38012Sejakowatz {
50352a38012Sejakowatz 	BControl::AllDetached();
50452a38012Sejakowatz }
505058691d4SStefano Ceccherini 
506058691d4SStefano Ceccherini 
507058691d4SStefano Ceccherini void
508058691d4SStefano Ceccherini BTextControl::FrameMoved(BPoint newPosition)
50952a38012Sejakowatz {
51052a38012Sejakowatz 	BControl::FrameMoved(newPosition);
51152a38012Sejakowatz }
512058691d4SStefano Ceccherini 
513058691d4SStefano Ceccherini 
514058691d4SStefano Ceccherini void
515ffe72abdSAxel Dörfler BTextControl::FrameResized(float width, float height)
51652a38012Sejakowatz {
517ffe72abdSAxel Dörfler 	BControl::FrameResized(width, height);
518ffe72abdSAxel Dörfler 
519ffe72abdSAxel Dörfler 	// changes in width
520ffe72abdSAxel Dörfler 
521ffe72abdSAxel Dörfler 	BRect bounds = Bounds();
522ffe72abdSAxel Dörfler 	const float border = 2.0f;
523ffe72abdSAxel Dörfler 
524ffe72abdSAxel Dörfler 	if (bounds.Width() > fPreviousWidth) {
525ffe72abdSAxel Dörfler 		// invalidate the region between the old and the new right border
526ffe72abdSAxel Dörfler 		BRect rect = bounds;
527ffe72abdSAxel Dörfler 		rect.left += fPreviousWidth - border;
528ffe72abdSAxel Dörfler 		rect.right--;
529ffe72abdSAxel Dörfler 		Invalidate(rect);
530ffe72abdSAxel Dörfler 	} else if (bounds.Width() < fPreviousWidth) {
531ffe72abdSAxel Dörfler 		// invalidate the region of the new right border
532ffe72abdSAxel Dörfler 		BRect rect = bounds;
533ffe72abdSAxel Dörfler 		rect.left = rect.right - border;
534ffe72abdSAxel Dörfler 		Invalidate(rect);
535ffe72abdSAxel Dörfler 	}
536ffe72abdSAxel Dörfler 
537ffe72abdSAxel Dörfler 	// changes in height
538ffe72abdSAxel Dörfler 
539ffe72abdSAxel Dörfler 	if (bounds.Height() > fPreviousHeight) {
540ffe72abdSAxel Dörfler 		// invalidate the region between the old and the new bottom border
541ffe72abdSAxel Dörfler 		BRect rect = bounds;
542ffe72abdSAxel Dörfler 		rect.top += fPreviousHeight - border;
543ffe72abdSAxel Dörfler 		rect.bottom--;
544ffe72abdSAxel Dörfler 		Invalidate(rect);
545ffe72abdSAxel Dörfler 	} else if (bounds.Height() < fPreviousHeight) {
546ffe72abdSAxel Dörfler 		// invalidate the region of the new bottom border
547ffe72abdSAxel Dörfler 		BRect rect = bounds;
548ffe72abdSAxel Dörfler 		rect.top = rect.bottom - border;
549ffe72abdSAxel Dörfler 		Invalidate(rect);
550ffe72abdSAxel Dörfler 	}
551ffe72abdSAxel Dörfler 
552ffe72abdSAxel Dörfler 	fPreviousWidth = uint16(bounds.Width());
553ffe72abdSAxel Dörfler 	fPreviousHeight = uint16(bounds.Height());
55452a38012Sejakowatz }
555058691d4SStefano Ceccherini 
556058691d4SStefano Ceccherini 
557058691d4SStefano Ceccherini void
558058691d4SStefano Ceccherini BTextControl::WindowActivated(bool active)
55952a38012Sejakowatz {
5606d8d6cadSStephan Aßmus 	if (fText->IsFocus()) {
561dde10e45SStephan Aßmus 		// invalidate to remove/show focus indication
562dde10e45SStephan Aßmus 		BRect rect = Bounds();
563dde10e45SStephan Aßmus 		rect.left = fDivider;
5646d8d6cadSStephan Aßmus 		Invalidate(rect);
565dde10e45SStephan Aßmus 
566dde10e45SStephan Aßmus 		// help out embedded text view which doesn't
567dde10e45SStephan Aßmus 		// get notified of this
568dde10e45SStephan Aßmus 		fText->Invalidate();
5696d8d6cadSStephan Aßmus 	}
57052a38012Sejakowatz }
571058691d4SStefano Ceccherini 
572058691d4SStefano Ceccherini 
573058691d4SStefano Ceccherini status_t
574058691d4SStefano Ceccherini BTextControl::Perform(perform_code d, void *arg)
57552a38012Sejakowatz {
57652a38012Sejakowatz 	return BControl::Perform(d, arg);
57752a38012Sejakowatz }
578058691d4SStefano Ceccherini 
579058691d4SStefano Ceccherini 
5809cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl1() {}
5819cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl2() {}
5829cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl3() {}
5839cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl4() {}
584058691d4SStefano Ceccherini 
585058691d4SStefano Ceccherini 
586058691d4SStefano Ceccherini BTextControl &
587058691d4SStefano Ceccherini BTextControl::operator=(const BTextControl&)
58852a38012Sejakowatz {
58952a38012Sejakowatz 	return *this;
59052a38012Sejakowatz }
591058691d4SStefano Ceccherini 
592058691d4SStefano Ceccherini 
593058691d4SStefano Ceccherini void
59479c35b39SAxel Dörfler BTextControl::_UpdateTextViewColors(bool enabled)
5953a3f6c1eSAxel Dörfler {
5963a3f6c1eSAxel Dörfler 	rgb_color textColor;
597aae7000dSAxel Dörfler 	rgb_color color;
5983a3f6c1eSAxel Dörfler 	BFont font;
5993a3f6c1eSAxel Dörfler 
600aae7000dSAxel Dörfler 	fText->GetFontAndColor(0, &font);
6013a3f6c1eSAxel Dörfler 
6023a3f6c1eSAxel Dörfler 	if (enabled)
603aae7000dSAxel Dörfler 		textColor = ui_color(B_DOCUMENT_TEXT_COLOR);
60412aefeb4SAxel Dörfler 	else {
60512aefeb4SAxel Dörfler 		textColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
60612aefeb4SAxel Dörfler 			B_DISABLED_LABEL_TINT);
60712aefeb4SAxel Dörfler 	}
6083a3f6c1eSAxel Dörfler 
6093a3f6c1eSAxel Dörfler 	fText->SetFontAndColor(&font, B_FONT_ALL, &textColor);
6103a3f6c1eSAxel Dörfler 
6113a3f6c1eSAxel Dörfler 	if (enabled) {
612aae7000dSAxel Dörfler 		color = ui_color(B_DOCUMENT_BACKGROUND_COLOR);
6133a3f6c1eSAxel Dörfler 	} else {
6143a3f6c1eSAxel Dörfler 		color = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
6153a3f6c1eSAxel Dörfler 			B_LIGHTEN_2_TINT);
6163a3f6c1eSAxel Dörfler 	}
6173a3f6c1eSAxel Dörfler 
6183a3f6c1eSAxel Dörfler 	fText->SetViewColor(color);
6193a3f6c1eSAxel Dörfler 	fText->SetLowColor(color);
6203a3f6c1eSAxel Dörfler }
6213a3f6c1eSAxel Dörfler 
6223a3f6c1eSAxel Dörfler 
6233a3f6c1eSAxel Dörfler void
624ffe72abdSAxel Dörfler BTextControl::_CommitValue()
6259cb2dbe2SMarc Flerackers {
6269cb2dbe2SMarc Flerackers }
627058691d4SStefano Ceccherini 
628058691d4SStefano Ceccherini 
629058691d4SStefano Ceccherini void
630ffe72abdSAxel Dörfler BTextControl::_InitData(const char* label, const char* initialText,
631ffe72abdSAxel Dörfler 	BMessage* archive)
6329cb2dbe2SMarc Flerackers {
6339cb2dbe2SMarc Flerackers 	BRect bounds(Bounds());
6349cb2dbe2SMarc Flerackers 
6359cb2dbe2SMarc Flerackers 	fText = NULL;
6369cb2dbe2SMarc Flerackers 	fModificationMessage = NULL;
6379cb2dbe2SMarc Flerackers 	fLabelAlign = B_ALIGN_LEFT;
6389cb2dbe2SMarc Flerackers 	fDivider = 0.0f;
639ffe72abdSAxel Dörfler 	fPreviousWidth = bounds.Width();
640ffe72abdSAxel Dörfler 	fPreviousHeight = bounds.Height();
6419cb2dbe2SMarc Flerackers 	fSkipSetFlags = false;
6429cb2dbe2SMarc Flerackers 
6439cb2dbe2SMarc Flerackers 	int32 flags = 0;
6449cb2dbe2SMarc Flerackers 
645918a22d9SDarkWyrm 	BFont font(be_plain_font);
6469cb2dbe2SMarc Flerackers 
647ffe72abdSAxel Dörfler 	if (!archive || !archive->HasString("_fname"))
648058691d4SStefano Ceccherini 		flags |= B_FONT_FAMILY_AND_STYLE;
6499cb2dbe2SMarc Flerackers 
650ffe72abdSAxel Dörfler 	if (!archive || !archive->HasFloat("_fflt"))
651058691d4SStefano Ceccherini 		flags |= B_FONT_SIZE;
6529cb2dbe2SMarc Flerackers 
6539cb2dbe2SMarc Flerackers 	if (flags != 0)
6549cb2dbe2SMarc Flerackers 		SetFont(&font, flags);
6559cb2dbe2SMarc Flerackers 
6569cb2dbe2SMarc Flerackers 	if (label)
6572e6a5805SStephan Aßmus 		fDivider = floorf(bounds.Width() / 2.0f);
6589cb2dbe2SMarc Flerackers 
659105644bfSAxel Dörfler 	uint32 navigableFlags = Flags() & B_NAVIGABLE;
660105644bfSAxel Dörfler 	if (navigableFlags != 0) {
6619cb2dbe2SMarc Flerackers 		fSkipSetFlags = true;
6629cb2dbe2SMarc Flerackers 		SetFlags(Flags() & ~B_NAVIGABLE);
6639cb2dbe2SMarc Flerackers 		fSkipSetFlags = false;
6649cb2dbe2SMarc Flerackers 	}
6659cb2dbe2SMarc Flerackers 
666ffe72abdSAxel Dörfler 	if (archive)
667058691d4SStefano Ceccherini 		fText = static_cast<_BTextInput_ *>(FindView("_input_"));
668058691d4SStefano Ceccherini 	else {
6692e6a5805SStephan Aßmus 		BRect frame(fDivider, bounds.top,
6702e6a5805SStephan Aßmus 					bounds.right, bounds.bottom);
671105644bfSAxel Dörfler 		// we are stroking the frame around the text view, which
6722e6a5805SStephan Aßmus 		// is 2 pixels wide
673455d1c46SAxel Dörfler 		frame.InsetBy(4.0, 3.0);
674111b4fbcSStefano Ceccherini 		BRect textRect(frame.OffsetToCopy(B_ORIGIN));
6759cb2dbe2SMarc Flerackers 
6769cb2dbe2SMarc Flerackers 		fText = new _BTextInput_(frame, textRect,
6777a70a2d6SStephan Aßmus 			B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
678105644bfSAxel Dörfler 			B_WILL_DRAW | B_FRAME_EVENTS | navigableFlags);
6799cb2dbe2SMarc Flerackers 		AddChild(fText);
6809cb2dbe2SMarc Flerackers 
681455d1c46SAxel Dörfler 		SetText(initialText);
6829cb2dbe2SMarc Flerackers 		fText->SetAlignment(B_ALIGN_LEFT);
6839cb2dbe2SMarc Flerackers 		fText->AlignTextRect();
6849cb2dbe2SMarc Flerackers 	}
6859cb2dbe2SMarc Flerackers }
686