xref: /haiku/src/kits/interface/StringView.cpp (revision 0562493379cd52eb7103531f895f10bb8e77c085)
1 /*
2  * Copyright 2001-2008, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Frans van Nispen (xlr8@tref.nl)
7  *		Ingo Weinhold <ingo_weinhold@gmx.de>
8  *		Stephan Aßmus <superstippi@gmx.de>
9  */
10 
11 //!	BStringView draws a non-editable text string.
12 
13 
14 #include <StringView.h>
15 
16 #include <LayoutUtils.h>
17 #include <Message.h>
18 #include <View.h>
19 #include <Window.h>
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include <binary_compatibility/Interface.h>
26 
27 
28 BStringView::BStringView(BRect frame, const char* name, const char* text,
29 			uint32 resizeMask, uint32 flags)
30 	:	BView(frame, name, resizeMask, flags),
31 		fText(text ? strdup(text) : NULL),
32 		fAlign(B_ALIGN_LEFT),
33 		fPreferredSize(-1, -1)
34 {
35 }
36 
37 
38 BStringView::BStringView(const char* name, const char* text, uint32 flags)
39 	:	BView(name, flags),
40 		fText(text ? strdup(text) : NULL),
41 		fAlign(B_ALIGN_LEFT),
42 		fPreferredSize(-1, -1)
43 {
44 }
45 
46 
47 BStringView::BStringView(BMessage* data)
48 	:	BView(data),
49 		fText(NULL),
50 		fPreferredSize(-1, -1)
51 {
52 	int32 align;
53 	if (data->FindInt32("_align", &align) == B_OK)
54 		fAlign = (alignment)align;
55 	else
56 		fAlign = B_ALIGN_LEFT;
57 
58 	const char* text;
59 	if (data->FindString("_text", &text) != B_OK)
60 		text = NULL;
61 
62 	SetText(text);
63 }
64 
65 
66 BArchivable*
67 BStringView::Instantiate(BMessage* data)
68 {
69 	if (!validate_instantiation(data, "BStringView"))
70 		return NULL;
71 
72 	return new BStringView(data);
73 }
74 
75 
76 status_t
77 BStringView::Archive(BMessage* data, bool deep) const
78 {
79 	status_t err = BView::Archive(data, deep);
80 
81 	if (err == B_OK && fText)
82 		err = data->AddString("_text", fText);
83 
84 	if (err == B_OK)
85 		err = data->AddInt32("_align", fAlign);
86 
87 	return err;
88 }
89 
90 
91 BStringView::~BStringView()
92 {
93 	free(fText);
94 }
95 
96 
97 void
98 BStringView::SetText(const char* text)
99 {
100 	if ((text && fText && !strcmp(text, fText)) || (!text && !fText))
101 		return;
102 
103 	free(fText);
104 	fText = text ? strdup(text) : NULL;
105 
106 	InvalidateLayout();
107 	Invalidate();
108 }
109 
110 
111 const char*
112 BStringView::Text() const
113 {
114 	return fText;
115 }
116 
117 
118 void
119 BStringView::SetAlignment(alignment flag)
120 {
121 	fAlign = flag;
122 	Invalidate();
123 }
124 
125 
126 alignment
127 BStringView::Alignment() const
128 {
129 	return fAlign;
130 }
131 
132 
133 void
134 BStringView::AttachedToWindow()
135 {
136 	rgb_color color = B_TRANSPARENT_COLOR;
137 
138 	BView* parent = Parent();
139 	if (parent != NULL)
140 		color = parent->ViewColor();
141 
142 	if (color == B_TRANSPARENT_COLOR)
143 		color = ui_color(B_PANEL_BACKGROUND_COLOR);
144 
145 	SetViewColor(color);
146 }
147 
148 
149 void
150 BStringView::Draw(BRect updateRect)
151 {
152 	if (!fText)
153 		return;
154 
155 	SetLowColor(ViewColor());
156 
157 	font_height fontHeight;
158 	GetFontHeight(&fontHeight);
159 
160 	BRect bounds = Bounds();
161 
162 	float y = (bounds.top + bounds.bottom - ceilf(fontHeight.ascent)
163 		- ceilf(fontHeight.descent)) / 2.0 + ceilf(fontHeight.ascent);
164 	float x;
165 	switch (fAlign) {
166 		case B_ALIGN_RIGHT:
167 			x = bounds.Width() - StringWidth(fText);
168 			break;
169 
170 		case B_ALIGN_CENTER:
171 			x = (bounds.Width() - StringWidth(fText)) / 2.0;
172 			break;
173 
174 		default:
175 			x = 0.0;
176 			break;
177 	}
178 
179 	DrawString(fText, BPoint(x, y));
180 }
181 
182 
183 void
184 BStringView::ResizeToPreferred()
185 {
186 	float width, height;
187 	GetPreferredSize(&width, &height);
188 
189 	// Resize the width only for B_ALIGN_LEFT (if its large enough already, that is)
190 	if (Bounds().Width() > width && Alignment() != B_ALIGN_LEFT)
191 		width = Bounds().Width();
192 
193 	BView::ResizeTo(width, height);
194 }
195 
196 
197 void
198 BStringView::GetPreferredSize(float* _width, float* _height)
199 {
200 	_ValidatePreferredSize();
201 
202 	if (_width)
203 		*_width = fPreferredSize.width;
204 
205 	if (_height)
206 		*_height = fPreferredSize.height;
207 }
208 
209 
210 void
211 BStringView::MessageReceived(BMessage* message)
212 {
213 	BView::MessageReceived(message);
214 }
215 
216 
217 void
218 BStringView::MouseDown(BPoint point)
219 {
220 	BView::MouseDown(point);
221 }
222 
223 
224 void
225 BStringView::MouseUp(BPoint point)
226 {
227 	BView::MouseUp(point);
228 }
229 
230 
231 void
232 BStringView::MouseMoved(BPoint point, uint32 transit, const BMessage* msg)
233 {
234 	BView::MouseMoved(point, transit, msg);
235 }
236 
237 
238 void
239 BStringView::DetachedFromWindow()
240 {
241 	BView::DetachedFromWindow();
242 }
243 
244 
245 void
246 BStringView::FrameMoved(BPoint newPosition)
247 {
248 	BView::FrameMoved(newPosition);
249 }
250 
251 
252 void
253 BStringView::FrameResized(float newWidth, float newHeight)
254 {
255 	BView::FrameResized(newWidth, newHeight);
256 }
257 
258 
259 BHandler*
260 BStringView::ResolveSpecifier(BMessage* msg, int32 index,
261 	BMessage* specifier, int32 form, const char* property)
262 {
263 	return NULL;
264 }
265 
266 
267 void
268 BStringView::MakeFocus(bool state)
269 {
270 	BView::MakeFocus(state);
271 }
272 
273 
274 void
275 BStringView::AllAttached()
276 {
277 	BView::AllAttached();
278 }
279 
280 
281 void
282 BStringView::AllDetached()
283 {
284 	BView::AllDetached();
285 }
286 
287 
288 status_t
289 BStringView::GetSupportedSuites(BMessage* message)
290 {
291 	return BView::GetSupportedSuites(message);
292 }
293 
294 
295 void
296 BStringView::SetFont(const BFont* font, uint32 mask)
297 {
298 	BView::SetFont(font, mask);
299 
300 	InvalidateLayout();
301 	Invalidate();
302 }
303 
304 
305 void
306 BStringView::InvalidateLayout(bool descendants)
307 {
308 	// invalidate cached preferred size
309 	fPreferredSize.Set(-1, -1);
310 
311 	BView::InvalidateLayout(descendants);
312 }
313 
314 
315 BSize
316 BStringView::MinSize()
317 {
318 	return BLayoutUtils::ComposeSize(ExplicitMinSize(),
319 		_ValidatePreferredSize());
320 }
321 
322 
323 BSize
324 BStringView::MaxSize()
325 {
326 	return BLayoutUtils::ComposeSize(ExplicitMaxSize(),
327 		_ValidatePreferredSize());
328 }
329 
330 
331 BSize
332 BStringView::PreferredSize()
333 {
334 	return BLayoutUtils::ComposeSize(ExplicitPreferredSize(),
335 		_ValidatePreferredSize());
336 }
337 
338 
339 status_t
340 BStringView::Perform(perform_code code, void* _data)
341 {
342 	switch (code) {
343 		case PERFORM_CODE_MIN_SIZE:
344 			((perform_data_min_size*)_data)->return_value
345 				= BStringView::MinSize();
346 			return B_OK;
347 		case PERFORM_CODE_MAX_SIZE:
348 			((perform_data_max_size*)_data)->return_value
349 				= BStringView::MaxSize();
350 			return B_OK;
351 		case PERFORM_CODE_PREFERRED_SIZE:
352 			((perform_data_preferred_size*)_data)->return_value
353 				= BStringView::PreferredSize();
354 			return B_OK;
355 		case PERFORM_CODE_LAYOUT_ALIGNMENT:
356 			((perform_data_layout_alignment*)_data)->return_value
357 				= BStringView::LayoutAlignment();
358 			return B_OK;
359 		case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
360 			((perform_data_has_height_for_width*)_data)->return_value
361 				= BStringView::HasHeightForWidth();
362 			return B_OK;
363 		case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
364 		{
365 			perform_data_get_height_for_width* data
366 				= (perform_data_get_height_for_width*)_data;
367 			BStringView::GetHeightForWidth(data->width, &data->min, &data->max,
368 				&data->preferred);
369 			return B_OK;
370 }
371 		case PERFORM_CODE_SET_LAYOUT:
372 		{
373 			perform_data_set_layout* data = (perform_data_set_layout*)_data;
374 			BStringView::SetLayout(data->layout);
375 			return B_OK;
376 		}
377 		case PERFORM_CODE_INVALIDATE_LAYOUT:
378 		{
379 			perform_data_invalidate_layout* data
380 				= (perform_data_invalidate_layout*)_data;
381 			BStringView::InvalidateLayout(data->descendants);
382 			return B_OK;
383 		}
384 		case PERFORM_CODE_DO_LAYOUT:
385 		{
386 			BStringView::DoLayout();
387 			return B_OK;
388 		}
389 	}
390 
391 	return BView::Perform(code, _data);
392 }
393 
394 
395 
396 void BStringView::_ReservedStringView1() {}
397 void BStringView::_ReservedStringView2() {}
398 void BStringView::_ReservedStringView3() {}
399 
400 
401 BStringView&
402 BStringView::operator=(const BStringView&)
403 {
404 	// Assignment not allowed (private)
405 	return *this;
406 }
407 
408 BSize
409 BStringView::_ValidatePreferredSize()
410 {
411 	if (fPreferredSize.width < 0) {
412 		// width
413 		fPreferredSize.width = ceilf(StringWidth(fText));
414 
415 		// height
416 		font_height fontHeight;
417 		GetFontHeight(&fontHeight);
418 
419 		fPreferredSize.height = ceilf(fontHeight.ascent + fontHeight.descent
420 			+ fontHeight.leading);
421 	}
422 
423 	return fPreferredSize;
424 }
425 
426