tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / interface / StringView.cpp
blobe4d1ca7fb5e3011ab88e29f61b5a4b8cff2c4fd9
1 /*
2 * Copyright 2001-2015, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Stephan Aßmus <superstippi@gmx.de>
7 * Axel Dörfler, axeld@pinc-software.de
8 * Frans van Nispen (xlr8@tref.nl)
9 * Ingo Weinhold <ingo_weinhold@gmx.de>
13 //! BStringView draws a non-editable text string.
16 #include <StringView.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
22 #include <LayoutUtils.h>
23 #include <Message.h>
24 #include <PropertyInfo.h>
25 #include <View.h>
26 #include <Window.h>
28 #include <binary_compatibility/Interface.h>
31 static property_info sPropertyList[] = {
33 "Text",
34 { B_GET_PROPERTY, B_SET_PROPERTY },
35 { B_DIRECT_SPECIFIER },
36 NULL, 0,
37 { B_STRING_TYPE }
40 "Alignment",
41 { B_GET_PROPERTY, B_SET_PROPERTY },
42 { B_DIRECT_SPECIFIER },
43 NULL, 0,
44 { B_INT32_TYPE }
50 BStringView::BStringView(BRect frame, const char* name, const char* text,
51 uint32 resizingMode, uint32 flags)
53 BView(frame, name, resizingMode, flags | B_FULL_UPDATE_ON_RESIZE),
54 fText(text ? strdup(text) : NULL),
55 fTruncation(B_NO_TRUNCATION),
56 fAlign(B_ALIGN_LEFT),
57 fPreferredSize(text ? StringWidth(text) : 0.0, -1)
62 BStringView::BStringView(const char* name, const char* text, uint32 flags)
64 BView(name, flags | B_FULL_UPDATE_ON_RESIZE),
65 fText(text ? strdup(text) : NULL),
66 fTruncation(B_NO_TRUNCATION),
67 fAlign(B_ALIGN_LEFT),
68 fPreferredSize(text ? StringWidth(text) : 0.0, -1)
73 BStringView::BStringView(BMessage* archive)
75 BView(archive),
76 fText(NULL),
77 fTruncation(B_NO_TRUNCATION),
78 fPreferredSize(0, -1)
80 fAlign = (alignment)archive->GetInt32("_align", B_ALIGN_LEFT);
81 fTruncation = (uint32)archive->GetInt32("_truncation", B_NO_TRUNCATION);
83 const char* text = archive->GetString("_text", NULL);
85 SetText(text);
86 SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE);
90 BStringView::~BStringView()
92 free(fText);
96 // #pragma mark - Archiving methods
99 BArchivable*
100 BStringView::Instantiate(BMessage* data)
102 if (!validate_instantiation(data, "BStringView"))
103 return NULL;
105 return new BStringView(data);
109 status_t
110 BStringView::Archive(BMessage* data, bool deep) const
112 status_t status = BView::Archive(data, deep);
114 if (status == B_OK && fText)
115 status = data->AddString("_text", fText);
116 if (status == B_OK && fTruncation != B_NO_TRUNCATION)
117 status = data->AddInt32("_truncation", fTruncation);
118 if (status == B_OK)
119 status = data->AddInt32("_align", fAlign);
121 return status;
125 // #pragma mark - Hook methods
128 void
129 BStringView::AttachedToWindow()
131 rgb_color color = B_TRANSPARENT_COLOR;
133 BView* parent = Parent();
134 if (parent != NULL)
135 color = parent->ViewColor();
137 if (color == B_TRANSPARENT_COLOR)
138 color = ui_color(B_PANEL_BACKGROUND_COLOR);
140 SetViewColor(color);
144 void
145 BStringView::DetachedFromWindow()
147 BView::DetachedFromWindow();
151 void
152 BStringView::AllAttached()
154 BView::AllAttached();
158 void
159 BStringView::AllDetached()
161 BView::AllDetached();
165 // #pragma mark - Layout methods
168 void
169 BStringView::MakeFocus(bool focus)
171 BView::MakeFocus(focus);
175 void
176 BStringView::GetPreferredSize(float* _width, float* _height)
178 _ValidatePreferredSize();
180 if (_width)
181 *_width = fPreferredSize.width;
183 if (_height)
184 *_height = fPreferredSize.height;
188 BSize
189 BStringView::MinSize()
191 return BLayoutUtils::ComposeSize(ExplicitMinSize(),
192 _ValidatePreferredSize());
196 BSize
197 BStringView::MaxSize()
199 return BLayoutUtils::ComposeSize(ExplicitMaxSize(),
200 _ValidatePreferredSize());
204 BSize
205 BStringView::PreferredSize()
207 return BLayoutUtils::ComposeSize(ExplicitPreferredSize(),
208 _ValidatePreferredSize());
212 void
213 BStringView::ResizeToPreferred()
215 float width, height;
216 GetPreferredSize(&width, &height);
218 // Resize the width only for B_ALIGN_LEFT (if its large enough already, that is)
219 if (Bounds().Width() > width && Alignment() != B_ALIGN_LEFT)
220 width = Bounds().Width();
222 BView::ResizeTo(width, height);
226 BAlignment
227 BStringView::LayoutAlignment()
229 return BLayoutUtils::ComposeAlignment(ExplicitAlignment(),
230 BAlignment(fAlign, B_ALIGN_MIDDLE));
234 // #pragma mark - More hook methods
237 void
238 BStringView::FrameMoved(BPoint newPosition)
240 BView::FrameMoved(newPosition);
244 void
245 BStringView::FrameResized(float newWidth, float newHeight)
247 BView::FrameResized(newWidth, newHeight);
251 void
252 BStringView::Draw(BRect updateRect)
254 if (!fText)
255 return;
257 SetLowColor(ViewColor());
259 font_height fontHeight;
260 GetFontHeight(&fontHeight);
262 BRect bounds = Bounds();
264 const char* text = fText;
265 float width = fPreferredSize.width;
266 BString truncated;
267 if (fTruncation != B_NO_TRUNCATION && width > bounds.Width()) {
268 // The string needs to be truncated
269 // TODO: we should cache this
270 truncated = fText;
271 TruncateString(&truncated, fTruncation, bounds.Width());
272 text = truncated.String();
273 width = StringWidth(text);
276 float y = (bounds.top + bounds.bottom - ceilf(fontHeight.ascent)
277 - ceilf(fontHeight.descent)) / 2.0 + ceilf(fontHeight.ascent);
278 float x;
279 switch (fAlign) {
280 case B_ALIGN_RIGHT:
281 x = bounds.Width() - width;
282 break;
284 case B_ALIGN_CENTER:
285 x = (bounds.Width() - width) / 2.0;
286 break;
288 default:
289 x = 0.0;
290 break;
293 DrawString(text, BPoint(x, y));
297 void
298 BStringView::MessageReceived(BMessage* message)
300 if (message->what == B_GET_PROPERTY || message->what == B_SET_PROPERTY) {
301 int32 index;
302 BMessage specifier;
303 int32 form;
304 const char* property;
305 if (message->GetCurrentSpecifier(&index, &specifier, &form, &property)
306 != B_OK) {
307 BView::MessageReceived(message);
308 return;
311 BMessage reply(B_REPLY);
312 bool handled = false;
313 if (strcmp(property, "Text") == 0) {
314 if (message->what == B_GET_PROPERTY) {
315 reply.AddString("result", fText);
316 handled = true;
317 } else {
318 const char* text;
319 if (message->FindString("data", &text) == B_OK) {
320 SetText(text);
321 reply.AddInt32("error", B_OK);
322 handled = true;
325 } else if (strcmp(property, "Alignment") == 0) {
326 if (message->what == B_GET_PROPERTY) {
327 reply.AddInt32("result", (int32)fAlign);
328 handled = true;
329 } else {
330 int32 align;
331 if (message->FindInt32("data", &align) == B_OK) {
332 SetAlignment((alignment)align);
333 reply.AddInt32("error", B_OK);
334 handled = true;
339 if (handled) {
340 message->SendReply(&reply);
341 return;
345 BView::MessageReceived(message);
349 void
350 BStringView::MouseDown(BPoint point)
352 BView::MouseDown(point);
356 void
357 BStringView::MouseUp(BPoint point)
359 BView::MouseUp(point);
363 void
364 BStringView::MouseMoved(BPoint point, uint32 transit, const BMessage* msg)
366 BView::MouseMoved(point, transit, msg);
370 // #pragma mark -
373 void
374 BStringView::SetText(const char* text)
376 if ((text && fText && !strcmp(text, fText)) || (!text && !fText))
377 return;
379 free(fText);
380 fText = text ? strdup(text) : NULL;
382 float newStringWidth = StringWidth(fText);
383 if (fPreferredSize.width != newStringWidth) {
384 fPreferredSize.width = newStringWidth;
385 InvalidateLayout();
388 Invalidate();
392 const char*
393 BStringView::Text() const
395 return fText;
399 void
400 BStringView::SetAlignment(alignment flag)
402 fAlign = flag;
403 Invalidate();
407 alignment
408 BStringView::Alignment() const
410 return fAlign;
414 void
415 BStringView::SetTruncation(uint32 truncationMode)
417 if (fTruncation != truncationMode) {
418 fTruncation = truncationMode;
419 Invalidate();
424 uint32
425 BStringView::Truncation() const
427 return fTruncation;
431 BHandler*
432 BStringView::ResolveSpecifier(BMessage* message, int32 index,
433 BMessage* specifier, int32 form, const char* property)
435 BPropertyInfo propInfo(sPropertyList);
436 if (propInfo.FindMatch(message, 0, specifier, form, property) >= B_OK)
437 return this;
439 return BView::ResolveSpecifier(message, index, specifier, form, property);
443 status_t
444 BStringView::GetSupportedSuites(BMessage* data)
446 if (data == NULL)
447 return B_BAD_VALUE;
449 status_t status = data->AddString("suites", "suite/vnd.Be-string-view");
450 if (status != B_OK)
451 return status;
453 BPropertyInfo propertyInfo(sPropertyList);
454 status = data->AddFlat("messages", &propertyInfo);
455 if (status != B_OK)
456 return status;
458 return BView::GetSupportedSuites(data);
462 void
463 BStringView::SetFont(const BFont* font, uint32 mask)
465 BView::SetFont(font, mask);
467 fPreferredSize.width = StringWidth(fText);
469 Invalidate();
470 InvalidateLayout();
474 void
475 BStringView::LayoutInvalidated(bool descendants)
477 // invalidate cached preferred size
478 fPreferredSize.height = -1;
482 // #pragma mark - Perform
485 status_t
486 BStringView::Perform(perform_code code, void* _data)
488 switch (code) {
489 case PERFORM_CODE_MIN_SIZE:
490 ((perform_data_min_size*)_data)->return_value
491 = BStringView::MinSize();
492 return B_OK;
494 case PERFORM_CODE_MAX_SIZE:
495 ((perform_data_max_size*)_data)->return_value
496 = BStringView::MaxSize();
497 return B_OK;
499 case PERFORM_CODE_PREFERRED_SIZE:
500 ((perform_data_preferred_size*)_data)->return_value
501 = BStringView::PreferredSize();
502 return B_OK;
504 case PERFORM_CODE_LAYOUT_ALIGNMENT:
505 ((perform_data_layout_alignment*)_data)->return_value
506 = BStringView::LayoutAlignment();
507 return B_OK;
509 case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
510 ((perform_data_has_height_for_width*)_data)->return_value
511 = BStringView::HasHeightForWidth();
512 return B_OK;
514 case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
516 perform_data_get_height_for_width* data
517 = (perform_data_get_height_for_width*)_data;
518 BStringView::GetHeightForWidth(data->width, &data->min, &data->max,
519 &data->preferred);
520 return B_OK;
523 case PERFORM_CODE_SET_LAYOUT:
525 perform_data_set_layout* data = (perform_data_set_layout*)_data;
526 BStringView::SetLayout(data->layout);
527 return B_OK;
530 case PERFORM_CODE_LAYOUT_INVALIDATED:
532 perform_data_layout_invalidated* data
533 = (perform_data_layout_invalidated*)_data;
534 BStringView::LayoutInvalidated(data->descendants);
535 return B_OK;
538 case PERFORM_CODE_DO_LAYOUT:
540 BStringView::DoLayout();
541 return B_OK;
545 return BView::Perform(code, _data);
549 // #pragma mark - FBC padding methods
552 void BStringView::_ReservedStringView1() {}
553 void BStringView::_ReservedStringView2() {}
554 void BStringView::_ReservedStringView3() {}
557 // #pragma mark - Private methods
560 BStringView&
561 BStringView::operator=(const BStringView&)
563 // Assignment not allowed (private)
564 return *this;
568 BSize
569 BStringView::_ValidatePreferredSize()
571 if (fPreferredSize.height < 0) {
572 // height
573 font_height fontHeight;
574 GetFontHeight(&fontHeight);
576 fPreferredSize.height = ceilf(fontHeight.ascent + fontHeight.descent
577 + fontHeight.leading);
579 ResetLayoutInvalidation();
582 return fPreferredSize;
586 extern "C" void
587 B_IF_GCC_2(InvalidateLayout__11BStringViewb,
588 _ZN11BStringView16InvalidateLayoutEb)(BView* view, bool descendants)
590 perform_data_layout_invalidated data;
591 data.descendants = descendants;
593 view->Perform(PERFORM_CODE_LAYOUT_INVALIDATED, &data);