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