2 * Copyright 2001-2015, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
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>
22 #include <LayoutUtils.h>
24 #include <PropertyInfo.h>
28 #include <binary_compatibility/Interface.h>
31 static property_info sPropertyList
[] = {
34 { B_GET_PROPERTY
, B_SET_PROPERTY
},
35 { B_DIRECT_SPECIFIER
},
41 { B_GET_PROPERTY
, B_SET_PROPERTY
},
42 { B_DIRECT_SPECIFIER
},
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
),
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
),
69 fPreferredSize(text
? StringWidth(text
) : 0.0, -1)
74 BStringView::BStringView(BMessage
* archive
)
78 fTruncation(B_NO_TRUNCATION
),
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
);
87 SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE
);
91 BStringView::~BStringView()
97 // #pragma mark - Archiving methods
101 BStringView::Instantiate(BMessage
* data
)
103 if (!validate_instantiation(data
, "BStringView"))
106 return new BStringView(data
);
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
);
120 status
= data
->AddInt32("_align", fAlign
);
126 // #pragma mark - Hook methods
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
);
145 SetViewColor(parent
->ViewColor());
146 SetLowColor(ViewColor());
150 if (ViewColor() == B_TRANSPARENT_COLOR
)
156 BStringView::DetachedFromWindow()
158 BView::DetachedFromWindow();
163 BStringView::AllAttached()
165 BView::AllAttached();
170 BStringView::AllDetached()
172 BView::AllDetached();
176 // #pragma mark - Layout methods
180 BStringView::MakeFocus(bool focus
)
182 BView::MakeFocus(focus
);
187 BStringView::GetPreferredSize(float* _width
, float* _height
)
189 _ValidatePreferredSize();
192 *_width
= fPreferredSize
.width
;
195 *_height
= fPreferredSize
.height
;
200 BStringView::MinSize()
202 return BLayoutUtils::ComposeSize(ExplicitMinSize(),
203 _ValidatePreferredSize());
208 BStringView::MaxSize()
210 return BLayoutUtils::ComposeSize(ExplicitMaxSize(),
211 _ValidatePreferredSize());
216 BStringView::PreferredSize()
218 return BLayoutUtils::ComposeSize(ExplicitPreferredSize(),
219 _ValidatePreferredSize());
224 BStringView::ResizeToPreferred()
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
);
238 BStringView::LayoutAlignment()
240 return BLayoutUtils::ComposeAlignment(ExplicitAlignment(),
241 BAlignment(fAlign
, B_ALIGN_MIDDLE
));
245 // #pragma mark - More hook methods
249 BStringView::FrameMoved(BPoint newPosition
)
251 BView::FrameMoved(newPosition
);
256 BStringView::FrameResized(float newWidth
, float newHeight
)
258 BView::FrameResized(newWidth
, newHeight
);
263 BStringView::Draw(BRect updateRect
)
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
;
279 if (fTruncation
!= B_NO_TRUNCATION
&& width
> bounds
.Width()) {
280 // The string needs to be truncated
281 // TODO: we should cache this
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
);
293 x
= bounds
.Width() - width
;
297 x
= (bounds
.Width() - width
) / 2.0;
305 DrawString(text
, BPoint(x
, y
));
310 BStringView::MessageReceived(BMessage
* message
)
312 if (message
->what
== B_GET_PROPERTY
|| message
->what
== B_SET_PROPERTY
) {
316 const char* property
;
317 if (message
->GetCurrentSpecifier(&index
, &specifier
, &form
, &property
)
319 BView::MessageReceived(message
);
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
);
331 if (message
->FindString("data", &text
) == B_OK
) {
333 reply
.AddInt32("error", B_OK
);
337 } else if (strcmp(property
, "Alignment") == 0) {
338 if (message
->what
== B_GET_PROPERTY
) {
339 reply
.AddInt32("result", (int32
)fAlign
);
343 if (message
->FindInt32("data", &align
) == B_OK
) {
344 SetAlignment((alignment
)align
);
345 reply
.AddInt32("error", B_OK
);
352 message
->SendReply(&reply
);
357 BView::MessageReceived(message
);
362 BStringView::MouseDown(BPoint point
)
364 BView::MouseDown(point
);
369 BStringView::MouseUp(BPoint point
)
371 BView::MouseUp(point
);
376 BStringView::MouseMoved(BPoint point
, uint32 transit
, const BMessage
* msg
)
378 BView::MouseMoved(point
, transit
, msg
);
386 BStringView::SetText(const char* text
)
388 if ((text
&& fText
&& !strcmp(text
, fText
)) || (!text
&& !fText
))
392 fText
= text
? strdup(text
) : NULL
;
394 float newStringWidth
= StringWidth(fText
);
395 if (fPreferredSize
.width
!= newStringWidth
) {
396 fPreferredSize
.width
= newStringWidth
;
405 BStringView::Text() const
412 BStringView::SetAlignment(alignment flag
)
420 BStringView::Alignment() const
427 BStringView::SetTruncation(uint32 truncationMode
)
429 if (fTruncation
!= truncationMode
) {
430 fTruncation
= truncationMode
;
437 BStringView::Truncation() const
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
)
451 return BView::ResolveSpecifier(message
, index
, specifier
, form
, property
);
456 BStringView::GetSupportedSuites(BMessage
* data
)
461 status_t status
= data
->AddString("suites", "suite/vnd.Be-string-view");
465 BPropertyInfo
propertyInfo(sPropertyList
);
466 status
= data
->AddFlat("messages", &propertyInfo
);
470 return BView::GetSupportedSuites(data
);
475 BStringView::SetFont(const BFont
* font
, uint32 mask
)
477 BView::SetFont(font
, mask
);
479 fPreferredSize
.width
= StringWidth(fText
);
487 BStringView::LayoutInvalidated(bool descendants
)
489 // invalidate cached preferred size
490 fPreferredSize
.height
= -1;
494 // #pragma mark - Perform
498 BStringView::Perform(perform_code code
, void* _data
)
501 case PERFORM_CODE_MIN_SIZE
:
502 ((perform_data_min_size
*)_data
)->return_value
503 = BStringView::MinSize();
506 case PERFORM_CODE_MAX_SIZE
:
507 ((perform_data_max_size
*)_data
)->return_value
508 = BStringView::MaxSize();
511 case PERFORM_CODE_PREFERRED_SIZE
:
512 ((perform_data_preferred_size
*)_data
)->return_value
513 = BStringView::PreferredSize();
516 case PERFORM_CODE_LAYOUT_ALIGNMENT
:
517 ((perform_data_layout_alignment
*)_data
)->return_value
518 = BStringView::LayoutAlignment();
521 case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH
:
522 ((perform_data_has_height_for_width
*)_data
)->return_value
523 = BStringView::HasHeightForWidth();
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
,
535 case PERFORM_CODE_SET_LAYOUT
:
537 perform_data_set_layout
* data
= (perform_data_set_layout
*)_data
;
538 BStringView::SetLayout(data
->layout
);
542 case PERFORM_CODE_LAYOUT_INVALIDATED
:
544 perform_data_layout_invalidated
* data
545 = (perform_data_layout_invalidated
*)_data
;
546 BStringView::LayoutInvalidated(data
->descendants
);
550 case PERFORM_CODE_DO_LAYOUT
:
552 BStringView::DoLayout();
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
573 BStringView::operator=(const BStringView
&)
575 // Assignment not allowed (private)
581 BStringView::_ValidatePreferredSize()
583 if (fPreferredSize
.height
< 0) {
585 font_height fontHeight
;
586 GetFontHeight(&fontHeight
);
588 fPreferredSize
.height
= ceilf(fontHeight
.ascent
+ fontHeight
.descent
589 + fontHeight
.leading
);
591 ResetLayoutInvalidation();
594 return fPreferredSize
;
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
);