xref: /haiku/src/kits/interface/TextControl.cpp (revision 7120e97489acbf17d86d3f33e3b2e68974fd4b23)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, OpenBeOS
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		TextControl.cpp
23 //	Author:			Frans van Nispen (xlr8@tref.nl)
24 //	Description:	BTextControl displays text that can act like a control.
25 //------------------------------------------------------------------------------
26 
27 // Standard Includes -----------------------------------------------------------
28 #include <stdio.h>
29 
30 // System Includes -------------------------------------------------------------
31 #include <TextControl.h>
32 #include <Window.h>
33 #include <Message.h>
34 
35 // Project Includes ------------------------------------------------------------
36 
37 // Local Includes --------------------------------------------------------------
38 #include "TextInput.h"
39 
40 // Local Defines ---------------------------------------------------------------
41 
42 // Globals ---------------------------------------------------------------------
43 
44 //------------------------------------------------------------------------------
45 BTextControl::BTextControl(BRect frame, const char* name, const char* label,
46 						   const char* text, BMessage* message, uint32 mask,
47 						   uint32 flags)
48 	:	BControl(frame, name, label, message, mask, flags)
49 {
50 	if (label)
51 	{
52 		fDivider = frame.Width() / 2.0f;
53 	}
54 	else
55 	{
56 		// no label
57 		fDivider = 0.0f;
58 	}
59 
60 	fModificationMessage = NULL;
61 
62 	frame = Bounds();
63 	if (fDivider)
64 	{
65 		frame.left = fDivider + 5.0f;
66 	}
67 
68 	BRect rect(frame);
69 	rect.OffsetTo(0,0);
70 
71 	frame.OffsetBy(-2,1);
72 
73 	rect.InsetBy(2,2);
74 	fText = new _BTextInput_(this, frame, "text", rect);
75 	fText->SetText(text);
76 	AddChild(fText);
77 }
78 //------------------------------------------------------------------------------
79 BTextControl::~BTextControl()
80 {
81 	if (fText)
82 	{
83 		fText->RemoveSelf();
84 		delete fText;
85 	}
86 }
87 //------------------------------------------------------------------------------
88 BTextControl::BTextControl(BMessage* data)
89 	:	BControl(data)
90 {
91 	if (data->FindInt32("_a_label", (int32*)&fLabelAlign) != B_OK)
92 	{
93 		fLabelAlign = B_ALIGN_LEFT;
94 	}
95 
96 	alignment textAlign;
97 	if (data->FindInt32("_a_text", (int32*)&textAlign) != B_OK)
98 	{
99 		fText->SetAlignment(B_ALIGN_LEFT);
100 	}
101 	else
102 	{
103 		fText->SetAlignment(textAlign);
104 	}
105 
106 	if (data->FindFloat("_divide", &fDivider) != B_OK)
107 	{
108 		if (Label())
109 			fDivider = Frame().Width()/2.0f;
110 		else
111 			fDivider = 0.0f;
112 	}
113 
114 	if (data->FindMessage("_mod_msg", fModificationMessage) != B_OK)
115 	{
116 		fModificationMessage = NULL;	// Is this really necessary?
117 	}
118 
119 	// TODO: Recover additional info as per final implementation of Archive()
120 }
121 //------------------------------------------------------------------------------
122 BArchivable* BTextControl::Instantiate(BMessage* data)
123 {
124 	if (!validate_instantiation(data,"BTextControl"))
125 	{
126 		return NULL;
127 	}
128 
129 	return new BTextControl(data);
130 }
131 //------------------------------------------------------------------------------
132 status_t BTextControl::Archive(BMessage* data, bool deep = true) const
133 {
134 	// TODO: compare against original version and finish
135 	status_t err = BView::Archive(data, deep);
136 
137 	if (!err)
138 		err = data->AddInt32("_a_label", fLabelAlign);
139 	if (!err)
140 		err = data->AddInt32("_a_text", fText->Alignment());
141 	if (!err)
142 		err = data->AddFloat("_divide", fDivider);
143 	if (!err && fModificationMessage)
144 		err = data->AddMessage("_mod_msg", fModificationMessage);
145 
146 	return err;
147 }
148 //------------------------------------------------------------------------------
149 void BTextControl::SetText(const char* text)
150 {
151 	fText->SetText(text);
152 }
153 //------------------------------------------------------------------------------
154 const char* BTextControl::Text() const
155 {
156 	return fText->Text();
157 }
158 //------------------------------------------------------------------------------
159 void BTextControl::SetValue(int32 value)
160 {
161 }
162 //------------------------------------------------------------------------------
163 status_t BTextControl::Invoke(BMessage* msg = NULL)
164 {
165 	return BControl::Invoke(msg);
166 }
167 //------------------------------------------------------------------------------
168 BTextView* BTextControl::TextView() const
169 {
170 	return (BTextView*)fText;
171 }
172 //------------------------------------------------------------------------------
173 void BTextControl::SetModificationMessage(BMessage* message)
174 {
175 	fModificationMessage = message;
176 }
177 //------------------------------------------------------------------------------
178 BMessage* BTextControl::ModificationMessage() const
179 {
180 	return fModificationMessage;
181 }
182 //------------------------------------------------------------------------------
183 void BTextControl::SetAlignment(alignment label, alignment text)
184 {
185 	fLabelAlign = label;
186 	fText->SetAlignment(text);
187 }
188 //------------------------------------------------------------------------------
189 void BTextControl::GetAlignment(alignment* label, alignment* text) const
190 {
191 	*label = fLabelAlign;
192 	*text = fText->Alignment();
193 }
194 //------------------------------------------------------------------------------
195 void BTextControl::SetDivider(float dividing_line)
196 {
197 	fDivider = dividing_line;
198 // here I need some code to resize and invalidate the textView
199 
200 	BRect frame = fText->Frame();
201 	if (fDivider)
202 	{
203 		frame.left = fDivider + 5.0f;
204 	}
205 	else
206 	{
207 		frame.left = 0.0f;
208 	}
209 
210 	if (!frame.IsValid())
211 	{
212 		frame.left = frame.right - 6.0f;
213 	}
214 
215 	fText->ResizeTo( frame.Width(), frame.Height());
216 //	fText->FrameResized( frame.Width(), frame.Height());
217 	fText->MoveTo( frame.left, frame.top);
218 	fText->Invalidate();
219 
220 	Invalidate();
221 }
222 //------------------------------------------------------------------------------
223 float BTextControl::Divider() const
224 {
225 	return fDivider;
226 }
227 //------------------------------------------------------------------------------
228 void BTextControl::Draw(BRect rect)
229 {
230 	SetLowColor(ViewColor());
231 	BFont font;
232 	GetFont(&font);
233 	font_height fh;
234 	font.GetHeight(&fh);
235 
236 	if (Label())
237 	{
238 		float y = ceil(fh.ascent + fh.descent + fh.leading) + 2.0f;
239 		float x;
240 		switch (fLabelAlign)
241 		{
242 			case B_ALIGN_RIGHT:
243 				x = fDivider - font.StringWidth(Label()) - 3.0f;
244 				break;
245 
246 			case B_ALIGN_CENTER:
247 				x = fDivider - font.StringWidth(Label())/2.0f;
248 				break;
249 
250 			default:
251 				x = 3.0f;
252 				break;
253 		}
254 
255 		SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
256 					 IsEnabled() ? B_DARKEN_MAX_TINT : B_DISABLED_LABEL_TINT));
257 		DrawString(Label(), BPoint(x, y));
258 	}
259 
260 	rect = fText->Frame();
261 
262 	rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
263 
264 	rect.InsetBy(-1,-1);
265 	SetHighColor(tint_color(base, IsEnabled() ?
266 							B_DARKEN_1_TINT : B_DARKEN_2_TINT));
267 	StrokeLine(BPoint(rect.left,rect.bottom), BPoint(rect.left, rect.top));
268 	StrokeLine(BPoint(rect.left+1.0f,rect.top), BPoint(rect.right, rect.top));
269 	SetHighColor(tint_color(base, IsEnabled() ?
270 							B_LIGHTEN_MAX_TINT : B_LIGHTEN_2_TINT));
271 	StrokeLine(BPoint(rect.left+1.0f,rect.bottom),
272 			   BPoint(rect.right, rect.bottom));
273 	StrokeLine(BPoint(rect.right,rect.bottom),
274 			   BPoint(rect.right, rect.top+1.0f));
275 }
276 //------------------------------------------------------------------------------
277 void BTextControl::MouseDown(BPoint where)
278 {
279 	if (IsEnabled())
280 	{
281 		MakeFocus(true);
282 	}
283 }
284 void BTextControl::AttachedToWindow()
285 {
286 	BControl::AttachedToWindow();
287 	if (Parent())
288 	{
289 		SetViewColor(Parent()->ViewColor());
290 	}
291 
292 	float w;
293 	float h;
294 	GetPreferredSize(&w, &h);
295 	ResizeTo(Bounds().Width(), h);
296 	fText->ResizeTo(fText->Bounds().Width(), h);
297 }
298 void BTextControl::MakeFocus(bool state = true)
299 {
300 	if (IsEnabled())
301 	{
302 		fText->MakeFocus(state);
303 		Invalidate();
304 	}
305 }
306 //------------------------------------------------------------------------------
307 void BTextControl::SetEnabled(bool state)
308 {
309 	fText->SetEnabled(state);
310 	BControl::SetEnabled(state);
311 }
312 //------------------------------------------------------------------------------
313 void BTextControl::GetPreferredSize(float* width, float* height)
314 {
315 	BFont font;
316 	GetFont(&font);
317 	font_height fh;
318 	font.GetHeight(&fh);
319 
320 	*height = ceil(fh.ascent + fh.descent + fh.leading) + 7.0f;
321 
322 	// TODO: this one I need to find out
323 	*width = 4.0f + ceil(font.StringWidth(Label()))*2.0f;
324 }
325 //------------------------------------------------------------------------------
326 void BTextControl::ResizeToPreferred()
327 {
328 	float w;
329 	float h;
330 	GetPreferredSize(&w, &h);
331 	BView::ResizeTo(w,h);
332 }
333 //------------------------------------------------------------------------------
334 void BTextControl::SetFlags(uint32 flags)
335 {
336 	BView::SetFlags(flags);
337 }
338 //------------------------------------------------------------------------------
339 void BTextControl::MessageReceived(BMessage* msg)
340 {
341 	switch(msg->what)
342 	{
343 		case B_CONTROL_MODIFIED:
344 			if (fModificationMessage)
345 			{
346 				BControl::Invoke(fModificationMessage);
347 			}
348 			break;
349 
350 		default:
351 			BControl::MessageReceived(msg);
352 			break;
353 	}
354 }
355 //------------------------------------------------------------------------------
356 BHandler* BTextControl::ResolveSpecifier(BMessage* msg, int32 index,
357 										 BMessage* specifier, int32 form,
358 										 const char* property)
359 {
360 	return NULL;
361 }
362 //------------------------------------------------------------------------------
363 status_t BTextControl::GetSupportedSuites(BMessage* data)
364 {
365 	return B_OK;
366 }
367 //------------------------------------------------------------------------------
368 void BTextControl::MouseUp(BPoint pt)
369 {
370 	BControl::MouseUp(pt);
371 }
372 //------------------------------------------------------------------------------
373 void BTextControl::MouseMoved(BPoint pt, uint32 code, const BMessage* msg)
374 {
375 	BControl::MouseMoved(pt, code, msg);
376 }
377 //------------------------------------------------------------------------------
378 void BTextControl::DetachedFromWindow()
379 {
380 	BControl::DetachedFromWindow();
381 }
382 //------------------------------------------------------------------------------
383 void BTextControl::AllAttached()
384 {
385 	BControl::AllAttached();
386 }
387 //------------------------------------------------------------------------------
388 void BTextControl::AllDetached()
389 {
390 	BControl::AllDetached();
391 }
392 //------------------------------------------------------------------------------
393 void BTextControl::FrameMoved(BPoint newPosition)
394 {
395 	BControl::FrameMoved(newPosition);
396 }
397 //------------------------------------------------------------------------------
398 void BTextControl::FrameResized(float newWidth, float newHeight)
399 {
400 	BControl::FrameResized(newWidth, newHeight);
401 }
402 //------------------------------------------------------------------------------
403 void BTextControl::WindowActivated(bool active)
404 {
405 	BControl::WindowActivated(active);
406 }
407 //------------------------------------------------------------------------------
408 status_t BTextControl::Perform(perform_code d, void* arg)
409 {
410 	return BControl::Perform(d, arg);
411 }
412 //------------------------------------------------------------------------------
413 void BTextControl::_ReservedTextControl1()
414 {
415 }
416 //------------------------------------------------------------------------------
417 void BTextControl::_ReservedTextControl2()
418 {
419 }
420 //------------------------------------------------------------------------------
421 void BTextControl::_ReservedTextControl3()
422 {
423 }
424 //------------------------------------------------------------------------------
425 void BTextControl::_ReservedTextControl4()
426 {
427 }
428 //------------------------------------------------------------------------------
429 BTextControl& BTextControl::operator=(const BTextControl&)
430 {
431 	// Assignment not allowed
432 	return *this;
433 }
434 //------------------------------------------------------------------------------
435 
436 /*
437  * $Log $
438  *
439  * $Id  $
440  *
441  */
442 
443