btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / kits / interface / StringView.cpp
blob1f38c6896dc8f2bfd5efb21ab1af5a462b386c82
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 }
47 { 0 }
51 BStringView::BStringView(BRect frame, const char* name, const char* text,
52 uint32 resizingMode, uint32 flags)
54 BView(frame, name, resizingMode, flags | B_FULL_UPDATE_ON_RESIZE),
55 fText(text ? strdup(text) : NULL),
56 fTruncation(B_NO_TRUNCATION),
57 fAlign(B_ALIGN_LEFT),
58 fPreferredSize(text ? StringWidth(text) : 0.0, -1)
63 BStringView::BStringView(const char* name, const char* text, uint32 flags)
65 BView(name, flags | B_FULL_UPDATE_ON_RESIZE),
66 fText(text ? strdup(text) : NULL),
67 fTruncation(B_NO_TRUNCATION),
68 fAlign(B_ALIGN_LEFT),
69 fPreferredSize(text ? StringWidth(text) : 0.0, -1)
74 BStringView::BStringView(BMessage* archive)
76 BView(archive),
77 fText(NULL),
78 fTruncation(B_NO_TRUNCATION),
79 fPreferredSize(0, -1)
81 fAlign = (alignment)archive->GetInt32("_align", B_ALIGN_LEFT);
82 fTruncation = (uint32)archive->GetInt32("_truncation", B_NO_TRUNCATION);
84 const char* text = archive->GetString("_text", NULL);
86 SetText(text);
87 SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE);
91 BStringView::~BStringView()
93 free(fText);
97 // #pragma mark - Archiving methods
100 BArchivable*
101 BStringView::Instantiate(BMessage* data)
103 if (!validate_instantiation(data, "BStringView"))
104 return NULL;
106 return new BStringView(data);
110 status_t
111 BStringView::Archive(BMessage* data, bool deep) const
113 status_t status = BView::Archive(data, deep);
115 if (status == B_OK && fText)
116 status = data->AddString("_text", fText);
117 if (status == B_OK && fTruncation != B_NO_TRUNCATION)
118 status = data->AddInt32("_truncation", fTruncation);
119 if (status == B_OK)
120 status = data->AddInt32("_align", fAlign);
122 return status;
126 // #pragma mark - Hook methods
129 void
130 BStringView::AttachedToWindow()
132 if (HasDefaultColors())
133 SetHighUIColor(B_PANEL_TEXT_COLOR);
135 BView* parent = Parent();
137 if (parent != NULL) {
138 float tint = B_NO_TINT;
139 color_which which = parent->ViewUIColor(&tint);
141 if (which != B_NO_COLOR) {
142 SetViewUIColor(which, tint);
143 SetLowUIColor(which, tint);
144 } else {
145 SetViewColor(parent->ViewColor());
146 SetLowColor(ViewColor());
150 if (ViewColor() == B_TRANSPARENT_COLOR)
151 AdoptSystemColors();
155 void
156 BStringView::DetachedFromWindow()
158 BView::DetachedFromWindow();
162 void
163 BStringView::AllAttached()
165 BView::AllAttached();
169 void
170 BStringView::AllDetached()
172 BView::AllDetached();
176 // #pragma mark - Layout methods
179 void
180 BStringView::MakeFocus(bool focus)
182 BView::MakeFocus(focus);
186 void
187 BStringView::GetPreferredSize(float* _width, float* _height)
189 _ValidatePreferredSize();
191 if (_width)
192 *_width = fPreferredSize.width;
194 if (_height)
195 *_height = fPreferredSize.height;
199 BSize
200 BStringView::MinSize()
202 return BLayoutUtils::ComposeSize(ExplicitMinSize(),
203 _ValidatePreferredSize());
207 BSize
208 BStringView::MaxSize()
210 return BLayoutUtils::ComposeSize(ExplicitMaxSize(),
211 _ValidatePreferredSize());
215 BSize
216 BStringView::PreferredSize()
218 return BLayoutUtils::ComposeSize(ExplicitPreferredSize(),
219 _ValidatePreferredSize());
223 void
224 BStringView::ResizeToPreferred()
226 float width, height;
227 GetPreferredSize(&width, &height);
229 // Resize the width only for B_ALIGN_LEFT (if its large enough already, that is)
230 if (Bounds().Width() > width && Alignment() != B_ALIGN_LEFT)
231 width = Bounds().Width();
233 BView::ResizeTo(width, height);
237 BAlignment
238 BStringView::LayoutAlignment()
240 return BLayoutUtils::ComposeAlignment(ExplicitAlignment(),
241 BAlignment(fAlign, B_ALIGN_MIDDLE));
245 // #pragma mark - More hook methods
248 void
249 BStringView::FrameMoved(BPoint newPosition)
251 BView::FrameMoved(newPosition);
255 void
256 BStringView::FrameResized(float newWidth, float newHeight)
258 BView::FrameResized(newWidth, newHeight);
262 void
263 BStringView::Draw(BRect updateRect)
265 if (!fText)
266 return;
268 if (LowUIColor() == B_NO_COLOR)
269 SetLowColor(ViewColor());
271 font_height fontHeight;
272 GetFontHeight(&fontHeight);
274 BRect bounds = Bounds();
276 const char* text = fText;
277 float width = fPreferredSize.width;
278 BString truncated;
279 if (fTruncation != B_NO_TRUNCATION && width > bounds.Width()) {
280 // The string needs to be truncated
281 // TODO: we should cache this
282 truncated = fText;
283 TruncateString(&truncated, fTruncation, bounds.Width());
284 text = truncated.String();
285 width = StringWidth(text);
288 float y = (bounds.top + bounds.bottom - ceilf(fontHeight.ascent)
289 - ceilf(fontHeight.descent)) / 2.0 + ceilf(fontHeight.ascent);
290 float x;
291 switch (fAlign) {
292 case B_ALIGN_RIGHT:
293 x = bounds.Width() - width;
294 break;
296 case B_ALIGN_CENTER:
297 x = (bounds.Width() - width) / 2.0;
298 break;
300 default:
301 x = 0.0;
302 break;
305 DrawString(text, BPoint(x, y));
309 void
310 BStringView::MessageReceived(BMessage* message)
312 if (message->what == B_GET_PROPERTY || message->what == B_SET_PROPERTY) {
313 int32 index;
314 BMessage specifier;
315 int32 form;
316 const char* property;
317 if (message->GetCurrentSpecifier(&index, &specifier, &form, &property)
318 != B_OK) {
319 BView::MessageReceived(message);
320 return;
323 BMessage reply(B_REPLY);
324 bool handled = false;
325 if (strcmp(property, "Text") == 0) {
326 if (message->what == B_GET_PROPERTY) {
327 reply.AddString("result", fText);
328 handled = true;
329 } else {
330 const char* text;
331 if (message->FindString("data", &text) == B_OK) {
332 SetText(text);
333 reply.AddInt32("error", B_OK);
334 handled = true;
337 } else if (strcmp(property, "Alignment") == 0) {
338 if (message->what == B_GET_PROPERTY) {
339 reply.AddInt32("result", (int32)fAlign);
340 handled = true;
341 } else {
342 int32 align;
343 if (message->FindInt32("data", &align) == B_OK) {
344 SetAlignment((alignment)align);
345 reply.AddInt32("error", B_OK);
346 handled = true;
351 if (handled) {
352 message->SendReply(&reply);
353 return;
357 BView::MessageReceived(message);
361 void
362 BStringView::MouseDown(BPoint point)
364 BView::MouseDown(point);
368 void
369 BStringView::MouseUp(BPoint point)
371 BView::MouseUp(point);
375 void
376 BStringView::MouseMoved(BPoint point, uint32 transit, const BMessage* msg)
378 BView::MouseMoved(point, transit, msg);
382 // #pragma mark -
385 void
386 BStringView::SetText(const char* text)
388 if ((text && fText && !strcmp(text, fText)) || (!text && !fText))
389 return;
391 free(fText);
392 fText = text ? strdup(text) : NULL;
394 float newStringWidth = StringWidth(fText);
395 if (fPreferredSize.width != newStringWidth) {
396 fPreferredSize.width = newStringWidth;
397 InvalidateLayout();
400 Invalidate();
404 const char*
405 BStringView::Text() const
407 return fText;
411 void
412 BStringView::SetAlignment(alignment flag)
414 fAlign = flag;
415 Invalidate();
419 alignment
420 BStringView::Alignment() const
422 return fAlign;
426 void
427 BStringView::SetTruncation(uint32 truncationMode)
429 if (fTruncation != truncationMode) {
430 fTruncation = truncationMode;
431 Invalidate();
436 uint32
437 BStringView::Truncation() const
439 return fTruncation;
443 BHandler*
444 BStringView::ResolveSpecifier(BMessage* message, int32 index,
445 BMessage* specifier, int32 form, const char* property)
447 BPropertyInfo propInfo(sPropertyList);
448 if (propInfo.FindMatch(message, 0, specifier, form, property) >= B_OK)
449 return this;
451 return BView::ResolveSpecifier(message, index, specifier, form, property);
455 status_t
456 BStringView::GetSupportedSuites(BMessage* data)
458 if (data == NULL)
459 return B_BAD_VALUE;
461 status_t status = data->AddString("suites", "suite/vnd.Be-string-view");
462 if (status != B_OK)
463 return status;
465 BPropertyInfo propertyInfo(sPropertyList);
466 status = data->AddFlat("messages", &propertyInfo);
467 if (status != B_OK)
468 return status;
470 return BView::GetSupportedSuites(data);
474 void
475 BStringView::SetFont(const BFont* font, uint32 mask)
477 BView::SetFont(font, mask);
479 fPreferredSize.width = StringWidth(fText);
481 Invalidate();
482 InvalidateLayout();
486 void
487 BStringView::LayoutInvalidated(bool descendants)
489 // invalidate cached preferred size
490 fPreferredSize.height = -1;
494 // #pragma mark - Perform
497 status_t
498 BStringView::Perform(perform_code code, void* _data)
500 switch (code) {
501 case PERFORM_CODE_MIN_SIZE:
502 ((perform_data_min_size*)_data)->return_value
503 = BStringView::MinSize();
504 return B_OK;
506 case PERFORM_CODE_MAX_SIZE:
507 ((perform_data_max_size*)_data)->return_value
508 = BStringView::MaxSize();
509 return B_OK;
511 case PERFORM_CODE_PREFERRED_SIZE:
512 ((perform_data_preferred_size*)_data)->return_value
513 = BStringView::PreferredSize();
514 return B_OK;
516 case PERFORM_CODE_LAYOUT_ALIGNMENT:
517 ((perform_data_layout_alignment*)_data)->return_value
518 = BStringView::LayoutAlignment();
519 return B_OK;
521 case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
522 ((perform_data_has_height_for_width*)_data)->return_value
523 = BStringView::HasHeightForWidth();
524 return B_OK;
526 case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
528 perform_data_get_height_for_width* data
529 = (perform_data_get_height_for_width*)_data;
530 BStringView::GetHeightForWidth(data->width, &data->min, &data->max,
531 &data->preferred);
532 return B_OK;
535 case PERFORM_CODE_SET_LAYOUT:
537 perform_data_set_layout* data = (perform_data_set_layout*)_data;
538 BStringView::SetLayout(data->layout);
539 return B_OK;
542 case PERFORM_CODE_LAYOUT_INVALIDATED:
544 perform_data_layout_invalidated* data
545 = (perform_data_layout_invalidated*)_data;
546 BStringView::LayoutInvalidated(data->descendants);
547 return B_OK;
550 case PERFORM_CODE_DO_LAYOUT:
552 BStringView::DoLayout();
553 return B_OK;
557 return BView::Perform(code, _data);
561 // #pragma mark - FBC padding methods
564 void BStringView::_ReservedStringView1() {}
565 void BStringView::_ReservedStringView2() {}
566 void BStringView::_ReservedStringView3() {}
569 // #pragma mark - Private methods
572 BStringView&
573 BStringView::operator=(const BStringView&)
575 // Assignment not allowed (private)
576 return *this;
580 BSize
581 BStringView::_ValidatePreferredSize()
583 if (fPreferredSize.height < 0) {
584 // height
585 font_height fontHeight;
586 GetFontHeight(&fontHeight);
588 fPreferredSize.height = ceilf(fontHeight.ascent + fontHeight.descent
589 + fontHeight.leading);
591 ResetLayoutInvalidation();
594 return fPreferredSize;
598 extern "C" void
599 B_IF_GCC_2(InvalidateLayout__11BStringViewb,
600 _ZN11BStringView16InvalidateLayoutEb)(BView* view, bool descendants)
602 perform_data_layout_invalidated data;
603 data.descendants = descendants;
605 view->Perform(PERFORM_CODE_LAYOUT_INVALIDATED, &data);