1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2001-2005, Haiku, Inc. 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 // DEALINGS IN THE SOFTWARE. 21 // 22 // File Name: Box.cpp 23 // Author: Marc Flerackers (mflerackers@androme.be) 24 // Description: BBox objects group views together and draw a border 25 // around them. 26 //------------------------------------------------------------------------------ 27 #include <stdlib.h> 28 #include <string.h> 29 30 #include <Box.h> 31 #include <Message.h> 32 33 34 BBox::BBox(BRect frame, const char *name, uint32 resizingMode, uint32 flags, 35 border_style border) 36 : BView(frame, name, resizingMode, flags | B_FRAME_EVENTS), 37 fStyle(border) 38 { 39 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 40 SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 41 42 InitObject(); 43 } 44 45 46 BBox::~BBox() 47 { 48 ClearAnyLabel(); 49 } 50 51 52 BBox::BBox(BMessage *archive) 53 : BView(archive) 54 { 55 InitObject(archive); 56 57 const char *string; 58 59 if (archive->FindString("_label", &string) == B_OK) 60 SetLabel(string); 61 62 bool aBool; 63 int32 anInt32; 64 65 if (archive->FindBool("_style", &aBool) == B_OK) 66 fStyle = aBool ? B_FANCY_BORDER : B_PLAIN_BORDER; 67 else if (archive->FindInt32("_style", &anInt32) == B_OK) 68 fStyle = (border_style)anInt32; 69 70 if (archive->FindBool("_lblview", &aBool) == B_OK) 71 fLabelView = ChildAt(0); 72 } 73 74 75 BArchivable * 76 BBox::Instantiate(BMessage *archive) 77 { 78 if (validate_instantiation(archive, "BBox")) 79 return new BBox(archive); 80 else 81 return NULL; 82 } 83 84 85 status_t 86 BBox::Archive(BMessage *archive, bool deep) const 87 { 88 BView::Archive(archive, deep); 89 90 if (fLabel) 91 archive->AddString("_label", fLabel); 92 93 if (fLabelView) 94 archive->AddBool("_lblview", true); 95 96 if (fStyle != B_FANCY_BORDER) 97 archive->AddInt32("_style", fStyle); 98 99 return B_OK; 100 } 101 102 103 void 104 BBox::SetBorder(border_style border) 105 { 106 fStyle = border; 107 108 if (Window() != NULL && LockLooper()) { 109 Invalidate(); 110 UnlockLooper(); 111 } 112 } 113 114 115 border_style 116 BBox::Border() const 117 { 118 return fStyle; 119 } 120 121 122 void 123 BBox::SetLabel(const char *string) 124 { 125 ClearAnyLabel(); 126 127 if (string) { 128 // Update fBounds 129 fBounds = Bounds(); 130 font_height fh; 131 GetFontHeight(&fh); 132 133 fBounds.top = (float)ceil((fh.ascent + fh.descent) / 2.0f); 134 135 fLabel = strdup(string); 136 } 137 138 if (Window()) 139 Invalidate(); 140 } 141 142 143 status_t 144 BBox::SetLabel(BView *viewLabel) 145 { 146 ClearAnyLabel(); 147 148 if (viewLabel) { 149 // Update fBounds 150 fBounds = Bounds(); 151 152 fBounds.top = (float)ceil(viewLabel->Bounds().Height() / 2.0f); 153 154 fLabelView = viewLabel; 155 fLabelView->MoveTo(10.0f, 0.0f); 156 AddChild(fLabelView, ChildAt(0)); 157 } 158 159 if (Window()) 160 Invalidate(); 161 162 return B_OK; 163 } 164 165 166 const char * 167 BBox::Label() const 168 { 169 return fLabel; 170 } 171 172 173 BView * 174 BBox::LabelView() const 175 { 176 return fLabelView; 177 } 178 179 180 void 181 BBox::Draw(BRect updateRect) 182 { 183 switch (fStyle) { 184 case B_FANCY_BORDER: 185 DrawFancy(); 186 break; 187 188 case B_PLAIN_BORDER: 189 DrawPlain(); 190 break; 191 192 default: 193 break; 194 } 195 196 if (fLabel) { 197 font_height fh; 198 GetFontHeight(&fh); 199 200 SetHighColor(ViewColor()); 201 202 FillRect(BRect(6.0f, 1.0f, 12.0f + StringWidth(fLabel), 203 (float)ceil(fh.ascent + fh.descent))/*, B_SOLID_LOW*/); 204 205 SetHighColor(0, 0, 0); 206 DrawString(fLabel, BPoint(10.0f, (float)ceil(fh.ascent - fh.descent) 207 + 1.0f)); 208 } 209 } 210 211 212 void BBox::AttachedToWindow() 213 { 214 if (Parent()) { 215 SetViewColor(Parent()->ViewColor()); 216 SetLowColor(Parent()->ViewColor()); 217 } 218 } 219 220 221 void 222 BBox::DetachedFromWindow() 223 { 224 BView::DetachedFromWindow(); 225 } 226 227 228 void 229 BBox::AllAttached() 230 { 231 BView::AllAttached(); 232 } 233 234 235 void 236 BBox::AllDetached() 237 { 238 BView::AllDetached(); 239 } 240 241 242 void 243 BBox::FrameResized(float width, float height) 244 { 245 BRect bounds(Bounds()); 246 247 // TODO: only invalidate the part that really need redrawing! 248 249 fBounds.right = bounds.right; 250 fBounds.bottom = bounds.bottom; 251 252 Invalidate(); 253 } 254 255 256 void 257 BBox::MessageReceived(BMessage *message) 258 { 259 BView::MessageReceived(message); 260 } 261 262 263 void 264 BBox::MouseDown(BPoint point) 265 { 266 BView::MouseDown(point); 267 } 268 269 270 void 271 BBox::MouseUp(BPoint point) 272 { 273 BView::MouseUp(point); 274 } 275 276 277 void 278 BBox::WindowActivated(bool active) 279 { 280 BView::WindowActivated(active); 281 } 282 283 284 void 285 BBox::MouseMoved(BPoint point, uint32 transit, const BMessage *message) 286 { 287 BView::MouseMoved(point, transit, message); 288 } 289 290 291 void 292 BBox::FrameMoved(BPoint newLocation) 293 { 294 BView::FrameMoved(newLocation); 295 } 296 297 298 BHandler * 299 BBox::ResolveSpecifier(BMessage *message, int32 index, 300 BMessage *specifier, int32 what, 301 const char *property) 302 { 303 return BView::ResolveSpecifier(message, index, specifier, what, property); 304 } 305 306 307 void 308 BBox::ResizeToPreferred() 309 { 310 BView::ResizeToPreferred(); 311 } 312 313 314 void 315 BBox::GetPreferredSize(float *width, float *height) 316 { 317 /* BRect rect(0,0,99,99); 318 319 if (Parent()) 320 { 321 rect = Parent()->Bounds(); 322 rect.InsetBy(10,10); 323 } 324 325 *width = rect.Width(); 326 *height = rect.Height();*/ 327 328 BView::GetPreferredSize(width, height); 329 } 330 331 332 void 333 BBox::MakeFocus(bool focused) 334 { 335 BView::MakeFocus(focused); 336 } 337 338 339 status_t 340 BBox::GetSupportedSuites(BMessage *message) 341 { 342 return BView::GetSupportedSuites(message); 343 } 344 345 346 status_t 347 BBox::Perform(perform_code d, void *arg) 348 { 349 return BView::Perform(d, arg); 350 } 351 352 353 void BBox::_ReservedBox1() {} 354 void BBox::_ReservedBox2() {} 355 356 357 BBox & 358 BBox::operator=(const BBox &) 359 { 360 return *this; 361 } 362 363 364 void 365 BBox::InitObject(BMessage *data) 366 { 367 fLabel = NULL; 368 fBounds = Bounds(); 369 fLabelView = NULL; 370 371 int32 flags = 0; 372 373 BFont font(be_bold_font); 374 375 if (!data || !data->HasString("_fname")) 376 flags = B_FONT_FAMILY_AND_STYLE; 377 378 if (!data || !data->HasFloat("_fflt")) 379 flags |= B_FONT_SIZE; 380 381 if (flags != 0) 382 SetFont(&font, flags); 383 } 384 385 386 void 387 BBox::DrawPlain() 388 { 389 BRect r = fBounds; 390 391 rgb_color light = tint_color(ViewColor(), B_LIGHTEN_MAX_TINT); 392 rgb_color shadow = tint_color(ViewColor(), B_DARKEN_3_TINT); 393 394 BeginLineArray(4); 395 AddLine(BPoint(r.left, r.bottom), 396 BPoint(r.left, r.top), light); 397 AddLine(BPoint(r.left + 1.0f, r.top), 398 BPoint(r.right, r.top), light); 399 AddLine(BPoint(r.left + 1.0f, r.bottom), 400 BPoint(r.right, r.bottom), shadow); 401 AddLine(BPoint(r.right, r.bottom - 1.0f), 402 BPoint(r.right, r.top + 1.0f), shadow); 403 EndLineArray(); 404 } 405 406 407 void 408 BBox::DrawFancy() 409 { 410 BRect r = fBounds; 411 412 rgb_color light = tint_color(ViewColor(), B_LIGHTEN_MAX_TINT); 413 rgb_color shadow = tint_color(ViewColor(), B_DARKEN_3_TINT); 414 415 BeginLineArray(8); 416 AddLine(BPoint(r.left, r.bottom), 417 BPoint(r.left, r.top), shadow); 418 AddLine(BPoint(r.left + 1.0f, r.top), 419 BPoint(r.right, r.top), shadow); 420 AddLine(BPoint(r.left + 1.0f, r.bottom), 421 BPoint(r.right, r.bottom), light); 422 AddLine(BPoint(r.right, r.bottom - 1.0f), 423 BPoint(r.right, r.top + 1.0f), light); 424 425 r.InsetBy(1.0, 1.0); 426 427 AddLine(BPoint(r.left, r.bottom), 428 BPoint(r.left, r.top), light); 429 AddLine(BPoint(r.left + 1.0f, r.top), 430 BPoint(r.right, r.top), light); 431 AddLine(BPoint(r.left + 1.0f, r.bottom), 432 BPoint(r.right, r.bottom), shadow); 433 AddLine(BPoint(r.right, r.bottom - 1.0f), 434 BPoint(r.right, r.top + 1.0f), shadow); 435 EndLineArray(); 436 } 437 438 439 void 440 BBox::ClearAnyLabel() 441 { 442 fBounds.top = 0; 443 444 if (fLabel) { 445 free(fLabel); 446 fLabel = NULL; 447 } else if (fLabelView) { 448 fLabelView->RemoveSelf(); 449 delete fLabelView; 450 fLabelView = NULL; 451 } 452 } 453