xref: /haiku/src/kits/interface/TextControl.cpp (revision 3a543720c49eb65f6c5404d1e804337deb3fbb1e)
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*3a543720SJérôme Duval 	status_t ret = BControl::Archive(data, deep);
90058691d4SStefano Ceccherini 	alignment labelAlignment, textAlignment;
9152a38012Sejakowatz 
92058691d4SStefano Ceccherini 	GetAlignment(&labelAlignment, &textAlignment);
939cb2dbe2SMarc Flerackers 
9411d7ecebSJérôme Duval 	if (ret == B_OK)
9511d7ecebSJérôme Duval 		ret = data->AddInt32("_a_label", labelAlignment);
9611d7ecebSJérôme Duval 	if (ret == B_OK)
9711d7ecebSJérôme Duval 		ret = data->AddInt32("_a_text", textAlignment);
9811d7ecebSJérôme Duval 	if (ret == B_OK)
9911d7ecebSJérôme Duval 		ret = data->AddFloat("_divide", Divider());
1009cb2dbe2SMarc Flerackers 
10111d7ecebSJérôme Duval 	if (ModificationMessage() && (ret == B_OK))
10211d7ecebSJérôme Duval 		ret = data->AddMessage("_mod_msg", ModificationMessage());
1039cb2dbe2SMarc Flerackers 
10411d7ecebSJé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 
2757a25fcafSStefano Ceccherini 	// label
2767a25fcafSStefano Ceccherini 
277058691d4SStefano Ceccherini 	if (Label()) {
278105644bfSAxel Dörfler 		font_height fontHeight;
279105644bfSAxel Dörfler 		GetFontHeight(&fontHeight);
2809cb2dbe2SMarc Flerackers 
281105644bfSAxel Dörfler 		float y = fontHeight.ascent + fText->Frame().top + 1;
28252a38012Sejakowatz 		float x;
2839cb2dbe2SMarc Flerackers 
2847a25fcafSStefano Ceccherini 		float labelWidth = StringWidth(Label());
285058691d4SStefano Ceccherini 		switch (fLabelAlign) {
28652a38012Sejakowatz 			case B_ALIGN_RIGHT:
2877a25fcafSStefano Ceccherini 				x = fDivider - labelWidth - 3.0f;
28852a38012Sejakowatz 				break;
28952a38012Sejakowatz 
29052a38012Sejakowatz 			case B_ALIGN_CENTER:
2917a25fcafSStefano Ceccherini 				x = fDivider - labelWidth / 2.0f;
29252a38012Sejakowatz 				break;
29352a38012Sejakowatz 
29452a38012Sejakowatz 			default:
29552a38012Sejakowatz 				x = 3.0f;
29652a38012Sejakowatz 				break;
29752a38012Sejakowatz 		}
29852a38012Sejakowatz 
2997a25fcafSStefano Ceccherini 		BRect labelArea(x, fText->Frame().top, x + labelWidth,
3007a25fcafSStefano Ceccherini 				ceilf(fontHeight.ascent + fontHeight.descent) + 1);
3017a25fcafSStefano Ceccherini 		if (x < fDivider && updateRect.Intersects(labelArea)) {
3027a25fcafSStefano Ceccherini 			labelArea.right = fDivider;
3037a25fcafSStefano Ceccherini 
3047a25fcafSStefano Ceccherini 			BRegion clipRegion(labelArea);
3057a25fcafSStefano Ceccherini 			ConstrainClippingRegion(&clipRegion);
306c432fbbbSAxel Dörfler 			SetHighColor(IsEnabled() ? ui_color(B_CONTROL_TEXT_COLOR)
307fa815db3SAxel Dörfler 				: tint_color(noTint, B_DISABLED_LABEL_TINT));
30852a38012Sejakowatz 			DrawString(Label(), BPoint(x, y));
30952a38012Sejakowatz 		}
31052a38012Sejakowatz 	}
3117a25fcafSStefano Ceccherini }
312058691d4SStefano Ceccherini 
313058691d4SStefano Ceccherini 
314058691d4SStefano Ceccherini void
315058691d4SStefano Ceccherini BTextControl::MouseDown(BPoint where)
31652a38012Sejakowatz {
317058691d4SStefano Ceccherini 	if (!fText->IsFocus()) {
3189cb2dbe2SMarc Flerackers 		fText->MakeFocus(true);
3199cb2dbe2SMarc Flerackers 		fText->SelectAll();
32052a38012Sejakowatz 	}
32152a38012Sejakowatz }
322058691d4SStefano Ceccherini 
323058691d4SStefano Ceccherini 
324058691d4SStefano Ceccherini void
325058691d4SStefano Ceccherini BTextControl::AttachedToWindow()
32652a38012Sejakowatz {
32752a38012Sejakowatz 	BControl::AttachedToWindow();
32852a38012Sejakowatz 
32979c35b39SAxel Dörfler 	_UpdateTextViewColors(IsEnabled());
3303a3f6c1eSAxel Dörfler 	fText->MakeEditable(IsEnabled());
33152a38012Sejakowatz }
332058691d4SStefano Ceccherini 
333058691d4SStefano Ceccherini 
334058691d4SStefano Ceccherini void
335058691d4SStefano Ceccherini BTextControl::MakeFocus(bool state)
33652a38012Sejakowatz {
3376d8d6cadSStephan Aßmus 	if (state != fText->IsFocus()) {
33852a38012Sejakowatz 		fText->MakeFocus(state);
3399cb2dbe2SMarc Flerackers 
3409cb2dbe2SMarc Flerackers 		if (state)
3419cb2dbe2SMarc Flerackers 			fText->SelectAll();
34252a38012Sejakowatz 	}
3436d8d6cadSStephan Aßmus }
344058691d4SStefano Ceccherini 
345058691d4SStefano Ceccherini 
346058691d4SStefano Ceccherini void
34779c35b39SAxel Dörfler BTextControl::SetEnabled(bool enabled)
34852a38012Sejakowatz {
34979c35b39SAxel Dörfler 	if (IsEnabled() == enabled)
3509cb2dbe2SMarc Flerackers 		return;
3519cb2dbe2SMarc Flerackers 
352058691d4SStefano Ceccherini 	if (Window()) {
35379c35b39SAxel Dörfler 		fText->MakeEditable(enabled);
3549cb2dbe2SMarc Flerackers 
35579c35b39SAxel Dörfler 		_UpdateTextViewColors(enabled);
3569cb2dbe2SMarc Flerackers 
3579cb2dbe2SMarc Flerackers 		fText->Invalidate();
3589cb2dbe2SMarc Flerackers 		Window()->UpdateIfNeeded();
3599cb2dbe2SMarc Flerackers 	}
3609cb2dbe2SMarc Flerackers 
36179c35b39SAxel Dörfler 	BControl::SetEnabled(enabled);
36252a38012Sejakowatz }
363058691d4SStefano Ceccherini 
364058691d4SStefano Ceccherini 
365058691d4SStefano Ceccherini void
366105644bfSAxel Dörfler BTextControl::GetPreferredSize(float *_width, float *_height)
36752a38012Sejakowatz {
368105644bfSAxel Dörfler 	if (_height) {
369105644bfSAxel Dörfler 		// we need enough space for the label and the child text view
370105644bfSAxel Dörfler 		font_height fontHeight;
371105644bfSAxel Dörfler 		GetFontHeight(&fontHeight);
372105644bfSAxel Dörfler 		float labelHeight = ceil(fontHeight.ascent + fontHeight.descent
373105644bfSAxel Dörfler 			+ fontHeight.leading);
374105644bfSAxel Dörfler 		float textHeight = fText->LineHeight(0) + 4.0;
37552a38012Sejakowatz 
376105644bfSAxel Dörfler 		*_height = max_c(labelHeight, textHeight);
377105644bfSAxel Dörfler 	}
378105644bfSAxel Dörfler 
379105644bfSAxel Dörfler 	if (_width) {
38052a38012Sejakowatz 		// TODO: this one I need to find out
381105644bfSAxel Dörfler 		float width = 20.0f + ceilf(StringWidth(Label()));
382105644bfSAxel Dörfler 		if (width < Bounds().Width())
383105644bfSAxel Dörfler 			width = Bounds().Width();
384105644bfSAxel Dörfler 		*_width = width;
385105644bfSAxel Dörfler 	}
38652a38012Sejakowatz }
387058691d4SStefano Ceccherini 
388058691d4SStefano Ceccherini 
389058691d4SStefano Ceccherini void
390058691d4SStefano Ceccherini BTextControl::ResizeToPreferred()
39152a38012Sejakowatz {
392105644bfSAxel Dörfler 	// TODO: change divider?
393105644bfSAxel Dörfler 	BView::ResizeToPreferred();
39452a38012Sejakowatz }
395058691d4SStefano Ceccherini 
396058691d4SStefano Ceccherini 
397058691d4SStefano Ceccherini void
398058691d4SStefano Ceccherini BTextControl::SetFlags(uint32 flags)
39952a38012Sejakowatz {
400058691d4SStefano Ceccherini 	if (!fSkipSetFlags) {
4019cb2dbe2SMarc Flerackers 		// If the textview is navigable, set it to not navigable if needed
4029cb2dbe2SMarc Flerackers 		// Else if it is not navigable, set it to navigable if needed
403058691d4SStefano Ceccherini 		if (fText->Flags() & B_NAVIGABLE) {
4049cb2dbe2SMarc Flerackers 			if (!(flags & B_NAVIGABLE))
4059cb2dbe2SMarc Flerackers 				fText->SetFlags(fText->Flags() & ~B_NAVIGABLE);
406058691d4SStefano Ceccherini 
407058691d4SStefano Ceccherini 		} else {
4089cb2dbe2SMarc Flerackers 			if (flags & B_NAVIGABLE)
4099cb2dbe2SMarc Flerackers 				fText->SetFlags(fText->Flags() | B_NAVIGABLE);
4109cb2dbe2SMarc Flerackers 		}
4119cb2dbe2SMarc Flerackers 
4129cb2dbe2SMarc Flerackers 		// Don't make this one navigable
4139cb2dbe2SMarc Flerackers 		flags &= ~B_NAVIGABLE;
4149cb2dbe2SMarc Flerackers 	}
4159cb2dbe2SMarc Flerackers 
41652a38012Sejakowatz 	BView::SetFlags(flags);
41752a38012Sejakowatz }
418058691d4SStefano Ceccherini 
419058691d4SStefano Ceccherini 
420058691d4SStefano Ceccherini void
421058691d4SStefano Ceccherini BTextControl::MessageReceived(BMessage *msg)
42252a38012Sejakowatz {
423058691d4SStefano Ceccherini 	switch(msg->what) {
4249cb2dbe2SMarc Flerackers 		case B_SET_PROPERTY:
4259cb2dbe2SMarc Flerackers 		case B_GET_PROPERTY:
4269cb2dbe2SMarc Flerackers 			// TODO
42752a38012Sejakowatz 			break;
42852a38012Sejakowatz 		default:
42952a38012Sejakowatz 			BControl::MessageReceived(msg);
43052a38012Sejakowatz 			break;
43152a38012Sejakowatz 	}
43252a38012Sejakowatz }
433058691d4SStefano Ceccherini 
434058691d4SStefano Ceccherini 
435058691d4SStefano Ceccherini BHandler *
436058691d4SStefano Ceccherini BTextControl::ResolveSpecifier(BMessage *msg, int32 index,
43752a38012Sejakowatz 										 BMessage *specifier, int32 form,
43852a38012Sejakowatz 										 const char *property)
43952a38012Sejakowatz {
4409cb2dbe2SMarc Flerackers 	/*
4419cb2dbe2SMarc Flerackers 	BPropertyInfo propInfo(prop_list);
4429cb2dbe2SMarc Flerackers 	BHandler *target = NULL;
4439cb2dbe2SMarc Flerackers 
4449cb2dbe2SMarc Flerackers 	if (propInfo.FindMatch(message, 0, specifier, what, property) < B_OK)
4459cb2dbe2SMarc Flerackers 		return BControl::ResolveSpecifier(message, index, specifier, what,
4469cb2dbe2SMarc Flerackers 			property);
4479cb2dbe2SMarc Flerackers 	else
4489cb2dbe2SMarc Flerackers 		return this;
4499cb2dbe2SMarc Flerackers 	*/
4509cb2dbe2SMarc Flerackers 	return BControl::ResolveSpecifier(msg, index, specifier, form, property);
45152a38012Sejakowatz }
452058691d4SStefano Ceccherini 
453058691d4SStefano Ceccherini 
454058691d4SStefano Ceccherini status_t
455058691d4SStefano Ceccherini BTextControl::GetSupportedSuites(BMessage *data)
45652a38012Sejakowatz {
4579cb2dbe2SMarc Flerackers 	return BControl::GetSupportedSuites(data);
45852a38012Sejakowatz }
459058691d4SStefano Ceccherini 
460058691d4SStefano Ceccherini 
461058691d4SStefano Ceccherini void
462058691d4SStefano Ceccherini BTextControl::MouseUp(BPoint pt)
46352a38012Sejakowatz {
46452a38012Sejakowatz 	BControl::MouseUp(pt);
46552a38012Sejakowatz }
466058691d4SStefano Ceccherini 
467058691d4SStefano Ceccherini 
468058691d4SStefano Ceccherini void
469058691d4SStefano Ceccherini BTextControl::MouseMoved(BPoint pt, uint32 code, const BMessage *msg)
47052a38012Sejakowatz {
47152a38012Sejakowatz 	BControl::MouseMoved(pt, code, msg);
47252a38012Sejakowatz }
473058691d4SStefano Ceccherini 
474058691d4SStefano Ceccherini 
475058691d4SStefano Ceccherini void
476058691d4SStefano Ceccherini BTextControl::DetachedFromWindow()
47752a38012Sejakowatz {
47852a38012Sejakowatz 	BControl::DetachedFromWindow();
47952a38012Sejakowatz }
480058691d4SStefano Ceccherini 
481058691d4SStefano Ceccherini 
482058691d4SStefano Ceccherini void
483058691d4SStefano Ceccherini BTextControl::AllAttached()
48452a38012Sejakowatz {
48552a38012Sejakowatz 	BControl::AllAttached();
48652a38012Sejakowatz }
487058691d4SStefano Ceccherini 
488058691d4SStefano Ceccherini 
489058691d4SStefano Ceccherini void
490058691d4SStefano Ceccherini BTextControl::AllDetached()
49152a38012Sejakowatz {
49252a38012Sejakowatz 	BControl::AllDetached();
49352a38012Sejakowatz }
494058691d4SStefano Ceccherini 
495058691d4SStefano Ceccherini 
496058691d4SStefano Ceccherini void
497058691d4SStefano Ceccherini BTextControl::FrameMoved(BPoint newPosition)
49852a38012Sejakowatz {
49952a38012Sejakowatz 	BControl::FrameMoved(newPosition);
50052a38012Sejakowatz }
501058691d4SStefano Ceccherini 
502058691d4SStefano Ceccherini 
503058691d4SStefano Ceccherini void
504ffe72abdSAxel Dörfler BTextControl::FrameResized(float width, float height)
50552a38012Sejakowatz {
506ffe72abdSAxel Dörfler 	BControl::FrameResized(width, height);
507ffe72abdSAxel Dörfler 
508ffe72abdSAxel Dörfler 	// changes in width
509ffe72abdSAxel Dörfler 
510ffe72abdSAxel Dörfler 	BRect bounds = Bounds();
511ffe72abdSAxel Dörfler 	const float border = 2.0f;
512ffe72abdSAxel Dörfler 
513ffe72abdSAxel Dörfler 	if (bounds.Width() > fPreviousWidth) {
514ffe72abdSAxel Dörfler 		// invalidate the region between the old and the new right border
515ffe72abdSAxel Dörfler 		BRect rect = bounds;
516ffe72abdSAxel Dörfler 		rect.left += fPreviousWidth - border;
517ffe72abdSAxel Dörfler 		rect.right--;
518ffe72abdSAxel Dörfler 		Invalidate(rect);
519ffe72abdSAxel Dörfler 	} else if (bounds.Width() < fPreviousWidth) {
520ffe72abdSAxel Dörfler 		// invalidate the region of the new right border
521ffe72abdSAxel Dörfler 		BRect rect = bounds;
522ffe72abdSAxel Dörfler 		rect.left = rect.right - border;
523ffe72abdSAxel Dörfler 		Invalidate(rect);
524ffe72abdSAxel Dörfler 	}
525ffe72abdSAxel Dörfler 
526ffe72abdSAxel Dörfler 	// changes in height
527ffe72abdSAxel Dörfler 
528ffe72abdSAxel Dörfler 	if (bounds.Height() > fPreviousHeight) {
529ffe72abdSAxel Dörfler 		// invalidate the region between the old and the new bottom border
530ffe72abdSAxel Dörfler 		BRect rect = bounds;
531ffe72abdSAxel Dörfler 		rect.top += fPreviousHeight - border;
532ffe72abdSAxel Dörfler 		rect.bottom--;
533ffe72abdSAxel Dörfler 		Invalidate(rect);
534ffe72abdSAxel Dörfler 	} else if (bounds.Height() < fPreviousHeight) {
535ffe72abdSAxel Dörfler 		// invalidate the region of the new bottom border
536ffe72abdSAxel Dörfler 		BRect rect = bounds;
537ffe72abdSAxel Dörfler 		rect.top = rect.bottom - border;
538ffe72abdSAxel Dörfler 		Invalidate(rect);
539ffe72abdSAxel Dörfler 	}
540ffe72abdSAxel Dörfler 
541ffe72abdSAxel Dörfler 	fPreviousWidth = uint16(bounds.Width());
542ffe72abdSAxel Dörfler 	fPreviousHeight = uint16(bounds.Height());
54352a38012Sejakowatz }
544058691d4SStefano Ceccherini 
545058691d4SStefano Ceccherini 
546058691d4SStefano Ceccherini void
547058691d4SStefano Ceccherini BTextControl::WindowActivated(bool active)
54852a38012Sejakowatz {
5496d8d6cadSStephan Aßmus 	if (fText->IsFocus()) {
550dde10e45SStephan Aßmus 		// invalidate to remove/show focus indication
551dde10e45SStephan Aßmus 		BRect rect = Bounds();
552dde10e45SStephan Aßmus 		rect.left = fDivider;
5536d8d6cadSStephan Aßmus 		Invalidate(rect);
554dde10e45SStephan Aßmus 
555dde10e45SStephan Aßmus 		// help out embedded text view which doesn't
556dde10e45SStephan Aßmus 		// get notified of this
557dde10e45SStephan Aßmus 		fText->Invalidate();
5586d8d6cadSStephan Aßmus 	}
55952a38012Sejakowatz }
560058691d4SStefano Ceccherini 
561058691d4SStefano Ceccherini 
562058691d4SStefano Ceccherini status_t
563058691d4SStefano Ceccherini BTextControl::Perform(perform_code d, void *arg)
56452a38012Sejakowatz {
56552a38012Sejakowatz 	return BControl::Perform(d, arg);
56652a38012Sejakowatz }
567058691d4SStefano Ceccherini 
568058691d4SStefano Ceccherini 
5699cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl1() {}
5709cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl2() {}
5719cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl3() {}
5729cb2dbe2SMarc Flerackers void BTextControl::_ReservedTextControl4() {}
573058691d4SStefano Ceccherini 
574058691d4SStefano Ceccherini 
575058691d4SStefano Ceccherini BTextControl &
576058691d4SStefano Ceccherini BTextControl::operator=(const BTextControl&)
57752a38012Sejakowatz {
57852a38012Sejakowatz 	return *this;
57952a38012Sejakowatz }
580058691d4SStefano Ceccherini 
581058691d4SStefano Ceccherini 
582058691d4SStefano Ceccherini void
58379c35b39SAxel Dörfler BTextControl::_UpdateTextViewColors(bool enabled)
5843a3f6c1eSAxel Dörfler {
5853a3f6c1eSAxel Dörfler 	rgb_color textColor;
586aae7000dSAxel Dörfler 	rgb_color color;
5873a3f6c1eSAxel Dörfler 	BFont font;
5883a3f6c1eSAxel Dörfler 
589aae7000dSAxel Dörfler 	fText->GetFontAndColor(0, &font);
5903a3f6c1eSAxel Dörfler 
5913a3f6c1eSAxel Dörfler 	if (enabled)
592aae7000dSAxel Dörfler 		textColor = ui_color(B_DOCUMENT_TEXT_COLOR);
59312aefeb4SAxel Dörfler 	else {
59412aefeb4SAxel Dörfler 		textColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
59512aefeb4SAxel Dörfler 			B_DISABLED_LABEL_TINT);
59612aefeb4SAxel Dörfler 	}
5973a3f6c1eSAxel Dörfler 
5983a3f6c1eSAxel Dörfler 	fText->SetFontAndColor(&font, B_FONT_ALL, &textColor);
5993a3f6c1eSAxel Dörfler 
6003a3f6c1eSAxel Dörfler 	if (enabled) {
601aae7000dSAxel Dörfler 		color = ui_color(B_DOCUMENT_BACKGROUND_COLOR);
6023a3f6c1eSAxel Dörfler 	} else {
6033a3f6c1eSAxel Dörfler 		color = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
6043a3f6c1eSAxel Dörfler 			B_LIGHTEN_2_TINT);
6053a3f6c1eSAxel Dörfler 	}
6063a3f6c1eSAxel Dörfler 
6073a3f6c1eSAxel Dörfler 	fText->SetViewColor(color);
6083a3f6c1eSAxel Dörfler 	fText->SetLowColor(color);
6093a3f6c1eSAxel Dörfler }
6103a3f6c1eSAxel Dörfler 
6113a3f6c1eSAxel Dörfler 
6123a3f6c1eSAxel Dörfler void
613ffe72abdSAxel Dörfler BTextControl::_CommitValue()
6149cb2dbe2SMarc Flerackers {
6159cb2dbe2SMarc Flerackers }
616058691d4SStefano Ceccherini 
617058691d4SStefano Ceccherini 
618058691d4SStefano Ceccherini void
619ffe72abdSAxel Dörfler BTextControl::_InitData(const char* label, const char* initialText,
620ffe72abdSAxel Dörfler 	BMessage* archive)
6219cb2dbe2SMarc Flerackers {
6229cb2dbe2SMarc Flerackers 	BRect bounds(Bounds());
6239cb2dbe2SMarc Flerackers 
6249cb2dbe2SMarc Flerackers 	fText = NULL;
6259cb2dbe2SMarc Flerackers 	fModificationMessage = NULL;
6269cb2dbe2SMarc Flerackers 	fLabelAlign = B_ALIGN_LEFT;
6279cb2dbe2SMarc Flerackers 	fDivider = 0.0f;
628ffe72abdSAxel Dörfler 	fPreviousWidth = bounds.Width();
629ffe72abdSAxel Dörfler 	fPreviousHeight = bounds.Height();
6309cb2dbe2SMarc Flerackers 	fSkipSetFlags = false;
6319cb2dbe2SMarc Flerackers 
6329cb2dbe2SMarc Flerackers 	int32 flags = 0;
6339cb2dbe2SMarc Flerackers 
634918a22d9SDarkWyrm 	BFont font(be_plain_font);
6359cb2dbe2SMarc Flerackers 
636ffe72abdSAxel Dörfler 	if (!archive || !archive->HasString("_fname"))
637058691d4SStefano Ceccherini 		flags |= B_FONT_FAMILY_AND_STYLE;
6389cb2dbe2SMarc Flerackers 
639ffe72abdSAxel Dörfler 	if (!archive || !archive->HasFloat("_fflt"))
640058691d4SStefano Ceccherini 		flags |= B_FONT_SIZE;
6419cb2dbe2SMarc Flerackers 
6429cb2dbe2SMarc Flerackers 	if (flags != 0)
6439cb2dbe2SMarc Flerackers 		SetFont(&font, flags);
6449cb2dbe2SMarc Flerackers 
6459cb2dbe2SMarc Flerackers 	if (label)
6462e6a5805SStephan Aßmus 		fDivider = floorf(bounds.Width() / 2.0f);
6479cb2dbe2SMarc Flerackers 
648105644bfSAxel Dörfler 	uint32 navigableFlags = Flags() & B_NAVIGABLE;
649105644bfSAxel Dörfler 	if (navigableFlags != 0) {
6509cb2dbe2SMarc Flerackers 		fSkipSetFlags = true;
6519cb2dbe2SMarc Flerackers 		SetFlags(Flags() & ~B_NAVIGABLE);
6529cb2dbe2SMarc Flerackers 		fSkipSetFlags = false;
6539cb2dbe2SMarc Flerackers 	}
6549cb2dbe2SMarc Flerackers 
655ffe72abdSAxel Dörfler 	if (archive)
656058691d4SStefano Ceccherini 		fText = static_cast<_BTextInput_ *>(FindView("_input_"));
657058691d4SStefano Ceccherini 	else {
6582e6a5805SStephan Aßmus 		BRect frame(fDivider, bounds.top,
6592e6a5805SStephan Aßmus 					bounds.right, bounds.bottom);
660105644bfSAxel Dörfler 		// we are stroking the frame around the text view, which
6612e6a5805SStephan Aßmus 		// is 2 pixels wide
66247b3e74eSStefano Ceccherini 		frame.InsetBy(2.0, 3.0);
663111b4fbcSStefano Ceccherini 		BRect textRect(frame.OffsetToCopy(B_ORIGIN));
6649cb2dbe2SMarc Flerackers 
6659cb2dbe2SMarc Flerackers 		fText = new _BTextInput_(frame, textRect,
6667a70a2d6SStephan Aßmus 			B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
667105644bfSAxel Dörfler 			B_WILL_DRAW | B_FRAME_EVENTS | navigableFlags);
6689cb2dbe2SMarc Flerackers 		AddChild(fText);
6699cb2dbe2SMarc Flerackers 
670455d1c46SAxel Dörfler 		SetText(initialText);
6719cb2dbe2SMarc Flerackers 		fText->SetAlignment(B_ALIGN_LEFT);
6729cb2dbe2SMarc Flerackers 		fText->AlignTextRect();
6739cb2dbe2SMarc Flerackers 	}
6749cb2dbe2SMarc Flerackers }
675