1 /* 2 * Copyright 2003-2023 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus, superstippi@gmx.de 7 * DarkWyrm, bpmagic@columbus.rr.com 8 * Marc Flerackers, mflerackers@androme.be 9 * François Revol, revol@free.fr 10 * John Scipione, jscipione@gmail.com 11 * Clemens Zeidler, haiku@clemens-zeidler.de 12 */ 13 14 15 /*! BControlLook resembling BeOS R5 */ 16 17 18 #include "BeControlLook.h" 19 20 #include <algorithm> 21 22 #include <Alignment.h> 23 #include <Bitmap.h> 24 #include <Button.h> 25 #include <Control.h> 26 #include <LayoutUtils.h> 27 #include <Region.h> 28 #include <Shape.h> 29 #include <String.h> 30 #include <TabView.h> 31 #include <View.h> 32 #include <Window.h> 33 #include <WindowPrivate.h> 34 35 //#define DEBUG_CONTROL_LOOK 36 #ifdef DEBUG_CONTROL_LOOK 37 # define STRACE(x) printf x 38 #else 39 # define STRACE(x) ; 40 #endif 41 42 43 namespace BPrivate { 44 45 static const float kButtonPopUpIndicatorWidth = 11; 46 47 48 BeControlLook::BeControlLook(image_id id) 49 : 50 fCachedOutline(false) 51 { 52 } 53 54 55 BeControlLook::~BeControlLook() 56 { 57 } 58 59 60 BAlignment 61 BeControlLook::DefaultLabelAlignment() const 62 { 63 return BAlignment(B_ALIGN_LEFT, B_ALIGN_VERTICAL_CENTER); 64 } 65 66 67 float 68 BeControlLook::DefaultLabelSpacing() const 69 { 70 return ceilf(be_plain_font->Size() / 2.0); 71 } 72 73 74 float 75 BeControlLook::DefaultItemSpacing() const 76 { 77 return ceilf(be_plain_font->Size() * 0.85); 78 } 79 80 81 uint32 82 BeControlLook::Flags(BControl* control) const 83 { 84 uint32 flags = B_IS_CONTROL; 85 86 if (!control->IsEnabled()) 87 flags |= B_DISABLED; 88 89 if (control->IsFocus() && control->Window() != NULL 90 && control->Window()->IsActive()) { 91 flags |= B_FOCUSED; 92 } 93 94 switch (control->Value()) { 95 case B_CONTROL_ON: 96 flags |= B_ACTIVATED; 97 break; 98 case B_CONTROL_PARTIALLY_ON: 99 flags |= B_PARTIALLY_ACTIVATED; 100 break; 101 } 102 103 if (control->Parent() != NULL 104 && (control->Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0) { 105 // In this constellation, assume we want to render the control 106 // against the already existing view contents of the parent view. 107 flags |= B_BLEND_FRAME; 108 } 109 110 return flags; 111 } 112 113 114 void 115 BeControlLook::DrawButtonFrame(BView* view, BRect& rect, 116 const BRect& updateRect, const rgb_color& base, 117 const rgb_color& background, uint32 flags, uint32 borders) 118 { 119 _DrawButtonFrame(view, rect, updateRect, 0, 0, 0, 0, base, 120 background, 1.0, 1.0, flags, borders); 121 } 122 123 124 void 125 BeControlLook::DrawButtonFrame(BView* view, BRect& rect, 126 const BRect& updateRect, float, const rgb_color& base, 127 const rgb_color& background, uint32 flags, uint32 borders) 128 { 129 _DrawButtonFrame(view, rect, updateRect, 0, 0, 0, 0, base, 130 background, 1.0, 1.0, flags, borders); 131 } 132 133 134 void 135 BeControlLook::DrawButtonFrame(BView* view, BRect& rect, 136 const BRect& updateRect, float, float, float, float, const rgb_color& base, 137 const rgb_color& background, uint32 flags, uint32 borders) 138 { 139 _DrawButtonFrame(view, rect, updateRect, 0, 0, 0, 0, base, 140 background, 1.0, 1.0, flags, borders); 141 } 142 143 144 void 145 BeControlLook::DrawButtonBackground(BView* view, BRect& rect, 146 const BRect& updateRect, const rgb_color& base, uint32 flags, 147 uint32 borders, orientation orientation) 148 { 149 _DrawButtonBackground(view, rect, updateRect, 0, 0, 0, 0, 150 base, false, flags, borders, orientation); 151 } 152 153 154 void 155 BeControlLook::DrawButtonBackground(BView* view, BRect& rect, 156 const BRect& updateRect, float, const rgb_color& base, uint32 flags, 157 uint32 borders, orientation orientation) 158 { 159 _DrawButtonBackground(view, rect, updateRect, 0, 0, 0, 0, 160 base, false, flags, borders, orientation); 161 } 162 163 164 void 165 BeControlLook::DrawButtonBackground(BView* view, BRect& rect, 166 const BRect& updateRect, float, float, float, float, const rgb_color& base, 167 uint32 flags, uint32 borders, orientation orientation) 168 { 169 _DrawButtonBackground(view, rect, updateRect, 0, 0, 0, 0, 170 base, false, flags, borders, orientation); 171 } 172 173 174 void 175 BeControlLook::DrawCheckBox(BView* view, BRect& rect, const BRect& updateRect, 176 const rgb_color& base, uint32 flags) 177 { 178 if (!rect.Intersects(updateRect)) 179 return; 180 181 bool isEnabled = (flags & B_DISABLED) == 0; 182 bool isActivated = (flags & B_ACTIVATED) != 0; 183 bool isFocused = (flags & B_FOCUSED) != 0; 184 bool isClicked = (flags & B_CLICKED) != 0; 185 186 rgb_color lighten1 = tint_color(base, B_LIGHTEN_1_TINT); 187 rgb_color lightenMax = tint_color(base, B_LIGHTEN_MAX_TINT); 188 rgb_color darken1 = tint_color(base, B_DARKEN_1_TINT); 189 rgb_color darken2 = tint_color(base, B_DARKEN_2_TINT); 190 rgb_color darken3 = tint_color(base, B_DARKEN_3_TINT); 191 rgb_color darken4 = tint_color(base, B_DARKEN_4_TINT); 192 193 view->SetLowColor(base); 194 195 if (isEnabled) { 196 // Filling 197 view->SetHighColor(lightenMax); 198 view->FillRect(rect); 199 200 // Box 201 if (isClicked) { 202 view->SetHighColor(darken3); 203 view->StrokeRect(rect); 204 205 rect.InsetBy(1, 1); 206 207 view->BeginLineArray(6); 208 209 view->AddLine(BPoint(rect.left, rect.bottom), 210 BPoint(rect.left, rect.top), darken2); 211 view->AddLine(BPoint(rect.left, rect.top), 212 BPoint(rect.right, rect.top), darken2); 213 view->AddLine(BPoint(rect.left, rect.bottom), 214 BPoint(rect.right, rect.bottom), darken4); 215 view->AddLine(BPoint(rect.right, rect.bottom), 216 BPoint(rect.right, rect.top), darken4); 217 218 view->EndLineArray(); 219 } else { 220 view->BeginLineArray(6); 221 222 view->AddLine(BPoint(rect.left, rect.bottom), 223 BPoint(rect.left, rect.top), darken1); 224 view->AddLine(BPoint(rect.left, rect.top), 225 BPoint(rect.right, rect.top), darken1); 226 227 rect.InsetBy(1, 1); 228 view->AddLine(BPoint(rect.left, rect.bottom), 229 BPoint(rect.left, rect.top), darken4); 230 view->AddLine(BPoint(rect.left, rect.top), 231 BPoint(rect.right, rect.top), darken4); 232 view->AddLine(BPoint(rect.left + 1, rect.bottom), 233 BPoint(rect.right, rect.bottom), base); 234 view->AddLine(BPoint(rect.right, rect.bottom), 235 BPoint(rect.right, rect.top + 1), base); 236 237 view->EndLineArray(); 238 } 239 240 // Focus 241 if (isFocused) { 242 view->SetDrawingMode(B_OP_OVER); 243 view->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); 244 view->StrokeRect(rect); 245 view->SetDrawingMode(B_OP_COPY); 246 } 247 } else { 248 // Filling 249 view->SetHighColor(lighten1); 250 view->FillRect(rect); 251 252 // Box 253 view->BeginLineArray(6); 254 255 view->AddLine(BPoint(rect.left, rect.bottom), 256 BPoint(rect.left, rect.top), base); 257 view->AddLine(BPoint(rect.left, rect.top), 258 BPoint(rect.right, rect.top), base); 259 260 rect.InsetBy(1, 1); 261 view->AddLine(BPoint(rect.left, rect.bottom), 262 BPoint(rect.left, rect.top), darken2); 263 view->AddLine(BPoint(rect.left, rect.top), 264 BPoint(rect.right, rect.top), darken2); 265 view->AddLine(BPoint(rect.left + 1, rect.bottom), 266 BPoint(rect.right, rect.bottom), darken1); 267 view->AddLine(BPoint(rect.right, rect.bottom), 268 BPoint(rect.right, rect.top + 1), darken1); 269 270 view->EndLineArray(); 271 } 272 273 // Checkmark 274 if (isActivated) { 275 rect.InsetBy(4, 4); 276 277 float penSize = std::max(1, 2); 278 if (penSize > 1 && fmodf(penSize, 2) == 0) { 279 // Tweak ends to "include" the pixel at the index, 280 // we need to do this in order to produce results like R5, 281 // where coordinates were inclusive 282 rect.right++; 283 rect.bottom++; 284 } 285 286 view->SetPenSize(penSize); 287 view->SetDrawingMode(B_OP_OVER); 288 if (isEnabled) 289 view->SetHighColor(ui_color(B_CONTROL_MARK_COLOR)); 290 else { 291 view->SetHighColor(tint_color(ui_color(B_CONTROL_MARK_COLOR), 292 B_DISABLED_MARK_TINT)); 293 } 294 view->StrokeLine(rect.LeftTop(), rect.RightBottom()); 295 view->StrokeLine(rect.LeftBottom(), rect.RightTop()); 296 } 297 } 298 299 300 void 301 BeControlLook::DrawRadioButton(BView* view, BRect& rect, 302 const BRect& updateRect, const rgb_color& base, uint32 flags) 303 { 304 if (!ShouldDraw(view, rect, updateRect)) 305 return; 306 307 bool isEnabled = (flags & B_DISABLED) == 0; 308 bool isActivated = (flags & B_ACTIVATED) != 0; 309 bool isFocused = (flags & B_FOCUSED) != 0; 310 311 // colors 312 rgb_color bg = ui_color(B_PANEL_BACKGROUND_COLOR); 313 rgb_color lightenmax; 314 rgb_color lighten1; 315 rgb_color darken1; 316 rgb_color darken2; 317 rgb_color darken3; 318 319 rgb_color markColor = ui_color(B_CONTROL_MARK_COLOR); 320 rgb_color knob; 321 rgb_color knobDark; 322 rgb_color knobLight; 323 324 if (isEnabled) { 325 lightenmax = tint_color(bg, B_LIGHTEN_MAX_TINT); 326 lighten1 = tint_color(bg, B_LIGHTEN_1_TINT); 327 darken1 = tint_color(bg, B_DARKEN_1_TINT); 328 darken2 = tint_color(bg, B_DARKEN_2_TINT); 329 darken3 = tint_color(bg, B_DARKEN_3_TINT); 330 331 knob = markColor; 332 knobDark = tint_color(markColor, B_DARKEN_3_TINT); 333 knobLight = tint_color(markColor, 0.15); 334 } else { 335 lightenmax = tint_color(bg, B_LIGHTEN_2_TINT); 336 lighten1 = bg; 337 darken1 = bg; 338 darken2 = tint_color(bg, B_DARKEN_1_TINT); 339 darken3 = tint_color(bg, B_DARKEN_2_TINT); 340 341 knob = tint_color(markColor, B_LIGHTEN_2_TINT); 342 knobDark = tint_color(markColor, B_LIGHTEN_1_TINT); 343 knobLight = tint_color(markColor, 344 (B_LIGHTEN_2_TINT + B_LIGHTEN_MAX_TINT) / 2.0); 345 } 346 347 rect.InsetBy(2, 2); 348 349 view->SetLowColor(bg); 350 351 // dot 352 if (isActivated) { 353 // full 354 view->SetHighColor(knobDark); 355 view->FillEllipse(rect); 356 357 view->SetHighColor(knob); 358 view->FillEllipse(BRect(rect.left + 2, rect.top + 2, rect.right - 3, 359 rect.bottom - 3)); 360 361 view->SetHighColor(knobLight); 362 view->FillEllipse(BRect(rect.left + 3, rect.top + 3, rect.right - 5, 363 rect.bottom - 5)); 364 } else { 365 // empty 366 view->SetHighColor(lightenmax); 367 view->FillEllipse(rect); 368 } 369 370 rect.InsetBy(-1, -1); 371 372 // outer circle 373 if (isFocused) { 374 // indicating "about to change value" 375 view->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); 376 view->SetPenSize(2); 377 view->SetDrawingMode(B_OP_OVER); 378 view->StrokeEllipse(rect.InsetByCopy(1, 1)); 379 view->SetDrawingMode(B_OP_COPY); 380 view->SetPenSize(1); 381 } else { 382 view->SetHighColor(darken1); 383 view->StrokeArc(rect, 45.0, 180.0); 384 view->SetHighColor(lightenmax); 385 view->StrokeArc(rect, 45.0, -180.0); 386 } 387 388 // inner circle 389 view->SetHighColor(darken3); 390 view->StrokeArc(rect, 45.0, 180.0); 391 view->SetHighColor(bg); 392 view->StrokeArc(rect, 45.0, -180.0); 393 394 // for faster font rendering, we restore B_OP_COPY 395 view->SetDrawingMode(B_OP_COPY); 396 } 397 398 399 void 400 BeControlLook::DrawScrollBarBorder(BView* view, BRect rect, 401 const BRect& updateRect, const rgb_color& base, uint32 flags, 402 orientation orientation) 403 { 404 if (!ShouldDraw(view, rect, updateRect)) 405 return; 406 407 view->PushState(); 408 409 view->ClipToRect(rect); 410 411 bool isEnabled = (flags & B_DISABLED) == 0; 412 bool isFocused = (flags & B_FOCUSED) != 0; 413 414 if (isEnabled && isFocused) 415 view->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); 416 else 417 view->SetHighColor(tint_color(base, B_DARKEN_2_TINT)); 418 419 view->StrokeRect(rect); 420 421 view->PopState(); 422 } 423 424 425 void 426 BeControlLook::DrawScrollBarButton(BView* view, BRect rect, 427 const BRect& updateRect, const rgb_color& base, uint32 flags, 428 int32 direction, orientation orientation, bool down) 429 { 430 view->PushState(); 431 432 bool isEnabled = (flags & B_DISABLED) == 0; 433 434 // border = 152, shine = 144/255, shadow = 208/184/192 435 rgb_color shine = down ? tint_color(base, 1.333) 436 : tint_color(base, B_LIGHTEN_MAX_TINT); 437 rgb_color shadow; 438 if (isEnabled && down) 439 shadow = tint_color(base, 1.037); 440 else if (isEnabled) 441 shadow = tint_color(base, B_DARKEN_1_TINT); 442 else 443 shadow = tint_color(base, 1.111); 444 445 view->BeginLineArray(4); 446 view->AddLine(rect.LeftTop(), rect.LeftBottom() - BPoint(0, 1), shine); 447 view->AddLine(rect.LeftTop(), rect.RightTop() - BPoint(1, 0), shine); 448 view->AddLine(rect.RightTop(), rect.RightBottom() - BPoint(0, 1), shadow); 449 view->AddLine(rect.LeftBottom(), rect.RightBottom(), shadow); 450 view->EndLineArray(); 451 452 rgb_color bg; 453 if (isEnabled) { 454 // bg = 176/216 455 bg = down ? tint_color(base, 1.185) : base; 456 } else { 457 // bg = 240 458 rgb_color lighten2 = tint_color(base, B_LIGHTEN_2_TINT); 459 lighten2.red++; lighten2.green++; lighten2.blue++; 460 // lighten2 = 239, 240 = 239 + 1 461 bg = lighten2; 462 } 463 view->SetHighColor(bg); 464 rect.InsetBy(1, 1); 465 view->FillRect(rect); 466 467 // draw button triangle 468 // don't use DrawArrowShape because we use that to draw arrows differently 469 // in menus and outline list view 470 471 rect.InsetBy(1, 1); 472 rect.OffsetBy(-3, -3); 473 474 BPoint tri1, tri2, tri3; 475 BPoint off1, off2, off3; 476 BRect r(rect.left, rect.top, rect.left + 14, rect.top + 14); 477 rgb_color lightenmax = tint_color(base, B_LIGHTEN_MAX_TINT); 478 rgb_color light, dark, arrow, arrow2; 479 480 switch(direction) { 481 case B_LEFT_ARROW: 482 tri1.Set(r.left + 3, floorf((r.top + r.bottom) / 2)); 483 tri2.Set(r.right - 4, r.top + 4); 484 tri3.Set(r.right - 4, r.bottom - 4); 485 break; 486 487 default: 488 case B_RIGHT_ARROW: 489 tri1.Set(r.left + 4, r.bottom - 4); 490 tri2.Set(r.left + 4, r.top + 4); 491 tri3.Set(r.right - 3, floorf((r.top + r.bottom) / 2)); 492 break; 493 494 case B_UP_ARROW: 495 tri1.Set(r.left + 4, r.bottom - 4); 496 tri2.Set(floorf((r.left + r.right) / 2), r.top + 3); 497 tri3.Set(r.right - 4, r.bottom - 4); 498 break; 499 500 case B_DOWN_ARROW: 501 tri1.Set(r.left + 4, r.top + 4); 502 tri2.Set(r.right - 4, r.top + 4); 503 tri3.Set(floorf((r.left + r.right) / 2), r.bottom - 3); 504 break; 505 } 506 507 r.InsetBy(1, 1); 508 509 float tint = B_NO_TINT; 510 if (!isEnabled) 511 tint = (tint + B_NO_TINT + B_NO_TINT) / 3; 512 513 view->SetHighColor(tint_color(base, tint)); 514 view->MovePenTo(B_ORIGIN); 515 view->SetDrawingMode(B_OP_OVER); 516 517 view->SetHighColor(tint_color(base, tint)); 518 519 if (isEnabled) { 520 arrow2 = light = tint_color(base, B_DARKEN_2_TINT); 521 dark = tint_color(base, B_DARKEN_3_TINT); 522 arrow = tint_color(base, B_DARKEN_MAX_TINT); 523 } else 524 arrow = arrow2 = light = dark = tint_color(base, B_DARKEN_1_TINT); 525 526 // white triangle offset by 1px 527 off1.Set(tri1.x + 1, tri1.y + 1); 528 off2.Set(tri2.x + 1, tri2.y + 1); 529 off3.Set(tri3.x + 1, tri3.y + 1); 530 531 // draw white triangle 532 view->BeginLineArray(3); 533 view->AddLine(off2, off3, lightenmax); 534 view->AddLine(off1, off3, lightenmax); 535 view->AddLine(off1, off2, lightenmax); 536 view->EndLineArray(); 537 538 // draw triangle on top 539 view->BeginLineArray(3); 540 view->AddLine(tri2, tri3, dark); 541 view->AddLine(tri1, tri3, dark); 542 view->AddLine(tri1, tri2, arrow2); 543 view->EndLineArray(); 544 545 view->PopState(); 546 } 547 548 549 void 550 BeControlLook::DrawScrollBarBackground(BView* view, BRect& rect1, BRect& rect2, 551 const BRect& updateRect, const rgb_color& base, uint32 flags, 552 orientation orientation) 553 { 554 _DrawScrollBarBackgroundFirst(view, rect1, updateRect, base, flags, 555 orientation); 556 _DrawScrollBarBackgroundSecond(view, rect2, updateRect, base, flags, 557 orientation); 558 } 559 560 561 void 562 BeControlLook::DrawScrollBarBackground(BView* view, BRect& rect, 563 const BRect& updateRect, const rgb_color& base, uint32 flags, 564 orientation orientation) 565 { 566 _DrawScrollBarBackgroundFirst(view, rect, updateRect, base, flags, 567 orientation); 568 } 569 570 571 void 572 BeControlLook::DrawScrollBarThumb(BView* view, BRect& rect, 573 const BRect& updateRect, const rgb_color& base, uint32 flags, 574 orientation orientation, uint32 knobStyle) 575 { 576 if (!ShouldDraw(view, rect, updateRect)) 577 return; 578 579 view->PushState(); 580 581 view->ClipToRect(rect); 582 583 bool isEnabled = (flags & B_DISABLED) == 0; 584 585 BRect orig(rect); 586 587 // shine = 255 588 rgb_color shine = tint_color(base, B_LIGHTEN_MAX_TINT); 589 rgb_color bg; 590 if (isEnabled) { 591 // bg = 216 592 bg = base; 593 } else { 594 // bg = 240 595 rgb_color lighten2 = tint_color(base, B_LIGHTEN_2_TINT); 596 lighten2.red++; lighten2.green++; lighten2.blue++; 597 // lighten2 = 239, 240 = 239 + 1 598 bg = lighten2; 599 } 600 601 // draw thumb over background 602 view->SetDrawingMode(B_OP_OVER); 603 604 view->BeginLineArray(2); 605 if (orientation == B_VERTICAL) { 606 // shine 607 view->AddLine(rect.LeftTop(), rect.LeftBottom(), shine); 608 rect.left++; 609 view->AddLine(rect.LeftTop(), rect.RightTop(), shine); 610 rect.top++; 611 } else { 612 // shine 613 view->AddLine(rect.LeftTop(), rect.LeftBottom(), shine); 614 rect.left++; 615 view->AddLine(rect.LeftTop(), rect.RightTop(), shine); 616 rect.top++; 617 } 618 view->EndLineArray(); 619 620 // fill bg 621 view->SetHighColor(bg); 622 view->FillRect(rect); 623 624 // undraw right top or left bottom point 625 view->BeginLineArray(1); 626 if (orientation == B_VERTICAL) { 627 rect.right--; 628 view->AddLine(rect.RightTop(), rect.RightTop(), base); 629 } else { 630 rect.bottom--; 631 view->AddLine(rect.LeftBottom(), rect.LeftBottom(), base); 632 } 633 view->EndLineArray(); 634 635 // restore rect 636 rect = orig; 637 638 // knobs 639 640 if (knobStyle != B_KNOB_NONE) { 641 float hcenter = rect.left + rect.Width() / 2; 642 float vmiddle = rect.top + rect.Height() / 2; 643 rgb_color knobDark = tint_color(base, B_DARKEN_1_TINT); 644 rgb_color knobLight = tint_color(base, B_LIGHTEN_MAX_TINT); 645 646 if (knobStyle == B_KNOB_DOTS) { 647 // center/middle dot 648 _DrawScrollBarKnobDot(view, hcenter, vmiddle, knobDark, knobLight, 649 orientation); 650 if (orientation == B_HORIZONTAL) { 651 float spacer = rect.Height(); 652 // left dot 653 if (rect.left + 7 < hcenter - spacer) { 654 _DrawScrollBarKnobDot(view, hcenter - 7, vmiddle, knobDark, 655 knobLight, orientation); 656 } 657 // right dot 658 if (rect.right - 7 > hcenter + spacer) { 659 _DrawScrollBarKnobDot(view, hcenter + 7, vmiddle, knobDark, 660 knobLight, orientation); 661 } 662 } else { 663 float spacer = rect.Width(); 664 // top dot 665 if (rect.top + 7 < vmiddle - spacer) { 666 _DrawScrollBarKnobDot(view, hcenter, vmiddle - 7, knobDark, 667 knobLight, orientation); 668 } 669 // bottom dot 670 if (rect.bottom - 7 > vmiddle + spacer) { 671 _DrawScrollBarKnobDot(view, hcenter, vmiddle + 7, knobDark, 672 knobLight, orientation); 673 } 674 } 675 } else if (knobStyle == B_KNOB_LINES) { 676 // center/middle line 677 _DrawScrollBarKnobLine(view, hcenter, vmiddle, knobDark, knobLight, 678 orientation); 679 if (orientation == B_HORIZONTAL) { 680 float spacer = rect.Height(); 681 // left line 682 if (rect.left + 4 < hcenter - spacer) { 683 _DrawScrollBarKnobLine(view, hcenter - 4, vmiddle, knobDark, 684 knobLight, orientation); 685 } 686 // right line 687 if (rect.right - 4 > hcenter + spacer) { 688 _DrawScrollBarKnobLine(view, hcenter + 4, vmiddle, knobDark, 689 knobLight, orientation); 690 } 691 } else { 692 float spacer = rect.Width(); 693 // top line 694 if (rect.top + 4 < vmiddle - spacer) { 695 _DrawScrollBarKnobLine(view, hcenter, vmiddle - 4, knobDark, 696 knobLight, orientation); 697 } 698 // bottom line 699 if (rect.bottom - 5 > vmiddle + spacer) { 700 _DrawScrollBarKnobLine(view, hcenter, vmiddle + 4, knobDark, 701 knobLight, orientation); 702 } 703 } 704 } 705 } 706 707 view->PopState(); 708 } 709 710 711 712 void 713 BeControlLook::DrawScrollViewFrame(BView* view, BRect& rect, 714 const BRect& updateRect, BRect verticalScrollBarFrame, 715 BRect horizontalScrollBarFrame, const rgb_color& base, 716 border_style borderStyle, uint32 flags, uint32 _borders) 717 { 718 rgb_color darken1 = tint_color(base, B_DARKEN_1_TINT); 719 rgb_color lightenmax = tint_color(base, B_LIGHTEN_MAX_TINT); 720 721 view->BeginLineArray(4); 722 view->AddLine(rect.LeftBottom(), rect.LeftTop(), darken1); 723 view->AddLine(rect.LeftTop(), rect.RightTop(), darken1); 724 view->AddLine(rect.RightTop(), rect.RightBottom(), lightenmax); 725 view->AddLine(rect.RightBottom(), rect.LeftBottom(), lightenmax); 726 view->EndLineArray(); 727 728 rect.InsetBy(1, 1); 729 730 bool isEnabled = (flags & B_DISABLED) == 0; 731 bool isFocused = (flags & B_FOCUSED) != 0; 732 733 if (isEnabled && isFocused) 734 view->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); 735 else 736 view->SetHighColor(tint_color(base, B_DARKEN_2_TINT)); 737 738 view->StrokeRect(rect); 739 } 740 741 742 void 743 BeControlLook::DrawArrowShape(BView* view, BRect& rect, const BRect& updateRect, 744 const rgb_color& base, uint32 direction, uint32 flags, float tint) 745 { 746 if (!ShouldDraw(view, rect, updateRect)) 747 return; 748 749 view->PushState(); 750 751 rgb_color fill = tint_color(base, 1.074); // 200 752 rgb_color stroke = tint_color(base, 1.629); // 80 753 754 switch(direction) { 755 case B_LEFT_ARROW: 756 view->SetHighColor(fill); 757 view->FillTriangle(rect.LeftTop() + BPoint(4, 6), 758 rect.LeftTop() + BPoint(8, 2), 759 rect.LeftTop() + BPoint(8, 10)); 760 view->SetHighColor(stroke); 761 view->StrokeTriangle(rect.LeftTop() + BPoint(4, 6), 762 rect.LeftTop() + BPoint(8, 2), 763 rect.LeftTop() + BPoint(8, 10)); 764 break; 765 766 default: 767 case B_RIGHT_ARROW: 768 view->SetHighColor(fill); 769 view->FillTriangle(rect.LeftTop() + BPoint(4, 2), 770 rect.LeftTop() + BPoint(4, 10), 771 rect.LeftTop() + BPoint(8, 6)); 772 view->SetHighColor(stroke); 773 view->StrokeTriangle(rect.LeftTop() + BPoint(4, 2), 774 rect.LeftTop() + BPoint(4, 10), 775 rect.LeftTop() + BPoint(8, 6)); 776 break; 777 778 case B_UP_ARROW: 779 view->SetHighColor(fill); 780 view->FillTriangle(rect.LeftTop() + BPoint(6, 4), 781 rect.LeftTop() + BPoint(2, 8), 782 rect.LeftTop() + BPoint(10, 8)); 783 view->SetHighColor(stroke); 784 view->StrokeTriangle(rect.LeftTop() + BPoint(6, 4), 785 rect.LeftTop() + BPoint(2, 8), 786 rect.LeftTop() + BPoint(10, 8)); 787 break; 788 789 case B_DOWN_ARROW: 790 view->SetHighColor(fill); 791 view->FillTriangle(rect.LeftTop() + BPoint(2, 4), 792 rect.LeftTop() + BPoint(10, 4), 793 rect.LeftTop() + BPoint(6, 8)); 794 view->SetHighColor(stroke); 795 view->StrokeTriangle(rect.LeftTop() + BPoint(2, 4), 796 rect.LeftTop() + BPoint(10, 4), 797 rect.LeftTop() + BPoint(6, 8)); 798 break; 799 } 800 801 view->PopState(); 802 } 803 804 805 void 806 BeControlLook::DrawMenuBarBackground(BView* view, BRect& rect, 807 const BRect& updateRect, const rgb_color& base, uint32 flags, 808 uint32 borders) 809 { 810 if (!ShouldDraw(view, rect, updateRect)) 811 return; 812 813 view->PushState(); 814 815 // restore the background color in case a menu item was selected 816 view->SetHighColor(base); 817 view->FillRect(rect); 818 819 rgb_color lighten2 = tint_color(base, B_LIGHTEN_2_TINT); 820 rgb_color darken1 = tint_color(base, B_DARKEN_1_TINT); 821 822 view->BeginLineArray(3); 823 view->AddLine(rect.LeftTop(), rect.RightTop(), lighten2); 824 // left bottom pixel is base color 825 view->AddLine(rect.LeftTop(), rect.LeftBottom() - BPoint(0, 1), 826 lighten2); 827 view->AddLine(rect.LeftBottom() + BPoint(1, 0), rect.RightBottom(), 828 darken1); 829 view->EndLineArray(); 830 831 view->PopState(); 832 } 833 834 835 void 836 BeControlLook::DrawMenuFieldFrame(BView* view, BRect& rect, 837 const BRect& updateRect, const rgb_color& base, 838 const rgb_color& background, uint32 flags, uint32 borders) 839 { 840 // BeControlLook does not support rounded corners and it never will 841 DrawMenuFieldFrame(view, rect, updateRect, 0, base, background, flags, 842 borders); 843 } 844 845 846 void 847 BeControlLook::DrawMenuFieldFrame(BView* view, BRect& rect, 848 const BRect& updateRect, float, const rgb_color& base, 849 const rgb_color& background, uint32 flags, uint32 borders) 850 { 851 // BeControlLook does not support rounded corners and it never will 852 DrawMenuFieldFrame(view, rect, updateRect, 0, 0, 0, 0, base, 853 background, flags, borders); 854 } 855 856 857 void 858 BeControlLook::DrawMenuFieldFrame(BView* view, BRect& rect, 859 const BRect& updateRect, float, float, float, float, const rgb_color& base, 860 const rgb_color& background, uint32 flags, uint32 borders) 861 { 862 if (!ShouldDraw(view, rect, updateRect)) 863 return; 864 865 bool isEnabled = (flags & B_DISABLED) == 0; 866 bool isFocused = (flags & B_FOCUSED) != 0; 867 868 // inset the frame by 2 and draw the outer border 869 rect.InsetBy(2, 2); 870 871 rgb_color darken2 = tint_color(base, B_DARKEN_2_TINT); 872 873 // draw left and top side and top right corner 874 view->BeginLineArray(3); 875 view->AddLine(BPoint(rect.left - 1, rect.top - 1), 876 BPoint(rect.left - 1, rect.bottom - 1), darken2); 877 view->AddLine(BPoint(rect.left - 1, rect.top - 1), 878 BPoint(rect.right - 1, rect.top - 1), darken2); 879 view->AddLine(BPoint(rect.right, rect.top - 1), 880 BPoint(rect.right, rect.top - 1), darken2); 881 view->EndLineArray(); 882 883 if (isEnabled && isFocused) { 884 // draw the focus ring on top of the frame 885 // Note that this is an intentional deviation from BeOS R5 886 // which draws the frame around the outside of the frame 887 // but that doesn't look as good. 888 view->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); 889 view->StrokeRect(rect.InsetByCopy(-1, -1)); 890 } 891 } 892 893 894 void 895 BeControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, 896 const BRect& updateRect, const rgb_color& base, bool popupIndicator, 897 uint32 flags) 898 { 899 _DrawMenuFieldBackgroundOutside(view, rect, updateRect, 900 0, 0, 0, 0, base, popupIndicator, flags); 901 } 902 903 904 void 905 BeControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, 906 const BRect& updateRect, const rgb_color& base, uint32 flags, 907 uint32 borders) 908 { 909 _DrawMenuFieldBackgroundInside(view, rect, updateRect, 910 0, 0, 0, 0, base, flags, borders); 911 } 912 913 914 void 915 BeControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, 916 const BRect& updateRect, float, const rgb_color& base, 917 bool popupIndicator, uint32 flags) 918 { 919 _DrawMenuFieldBackgroundOutside(view, rect, updateRect, 0, 0, 920 0, 0, base, popupIndicator, flags); 921 } 922 923 924 void 925 BeControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, 926 const BRect& updateRect, float, float, float, float, const rgb_color& base, 927 bool popupIndicator, uint32 flags) 928 { 929 _DrawMenuFieldBackgroundOutside(view, rect, updateRect, 0, 0, 930 0, 0, base, popupIndicator, flags); 931 } 932 933 934 void 935 BeControlLook::DrawMenuBackground(BView* view, BRect& rect, 936 const BRect& updateRect, const rgb_color& base, uint32 flags, 937 uint32 borders) 938 { 939 if (!ShouldDraw(view, rect, updateRect)) 940 return; 941 942 view->PushState(); 943 944 view->SetHighColor(base); 945 view->FillRect(rect); 946 947 view->PopState(); 948 } 949 950 951 void 952 BeControlLook::DrawMenuItemBackground(BView* view, BRect& rect, 953 const BRect& updateRect, const rgb_color& base, uint32 flags, 954 uint32 borders) 955 { 956 if (!ShouldDraw(view, rect, updateRect)) 957 return; 958 959 view->PushState(); 960 961 view->SetHighColor(base); 962 view->FillRect(rect); 963 964 view->PopState(); 965 } 966 967 968 void 969 BeControlLook::DrawStatusBar(BView* view, BRect& rect, const BRect& updateRect, 970 const rgb_color& base, const rgb_color& barColor, float progressPosition) 971 { 972 if (!ShouldDraw(view, rect, updateRect)) 973 return; 974 975 view->PushState(); 976 977 // draw background 978 view->SetHighColor(base); 979 view->FillRect(rect); 980 981 // draw frame around bar 982 DrawTextControlBorder(view, rect, updateRect, tint_color(base, B_DARKEN_1_TINT)); 983 984 // filled and nonfilled rects 985 BRect filledRect(rect); 986 filledRect.right = progressPosition - 1; 987 BRect nonfilledRect(rect); 988 nonfilledRect.left = progressPosition; 989 990 bool drawFilled = filledRect.Width() > 0; 991 bool drawNonfilled = nonfilledRect.Width() > 0; 992 993 // filled 994 if (drawFilled) { 995 rgb_color light = tint_color(barColor, 0.6); 996 rgb_color dark = tint_color(barColor, 1.4); 997 _DrawFrame(view, filledRect, light, light, dark, dark); 998 999 view->SetHighColor(barColor); 1000 view->FillRect(filledRect); 1001 } 1002 1003 // nonfilled 1004 if (drawNonfilled) { 1005 view->SetHighColor(ui_color(B_CONTROL_BACKGROUND_COLOR)); 1006 view->FillRect(nonfilledRect); 1007 } 1008 1009 view->PopState(); 1010 } 1011 1012 1013 rgb_color 1014 BeControlLook::SliderBarColor(const rgb_color& base) 1015 { 1016 return tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_1_TINT); 1017 } 1018 1019 1020 void 1021 BeControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect, 1022 const rgb_color& base, rgb_color leftFillColor, rgb_color rightFillColor, 1023 float sliderScale, uint32 flags, orientation orientation) 1024 { 1025 if (!ShouldDraw(view, rect, updateRect)) 1026 return; 1027 1028 // separate the bar in two sides 1029 float sliderPosition; 1030 BRect leftBarSide = rect; 1031 BRect rightBarSide = rect; 1032 1033 if (orientation == B_HORIZONTAL) { 1034 sliderPosition = floorf(rect.left + 2 + (rect.Width() - 2) 1035 * sliderScale); 1036 leftBarSide.right = sliderPosition - 1; 1037 rightBarSide.left = sliderPosition; 1038 } else { 1039 // NOTE: position is reverse of coords 1040 sliderPosition = floorf(rect.top + 2 + (rect.Height() - 2) 1041 * (1.0 - sliderScale)); 1042 leftBarSide.top = sliderPosition; 1043 rightBarSide.bottom = sliderPosition - 1; 1044 } 1045 1046 view->PushState(); 1047 view->ClipToRect(leftBarSide); 1048 1049 DrawSliderBar(view, rect, updateRect, base, leftFillColor, flags, 1050 orientation); 1051 view->PopState(); 1052 1053 view->PushState(); 1054 view->ClipToRect(rightBarSide); 1055 1056 DrawSliderBar(view, rect, updateRect, base, rightFillColor, flags, 1057 orientation); 1058 view->PopState(); 1059 } 1060 1061 1062 void 1063 BeControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect, 1064 const rgb_color& base, rgb_color fillColor, uint32 flags, 1065 orientation orientation) 1066 { 1067 if (!ShouldDraw(view, rect, updateRect)) 1068 return; 1069 1070 view->SetHighColor(fillColor); 1071 view->FillRect(rect); 1072 1073 rgb_color lightenmax = tint_color(base, B_LIGHTEN_MAX_TINT); 1074 rgb_color darken1 = tint_color(base, B_DARKEN_1_TINT); 1075 rgb_color darken2 = tint_color(base, B_DARKEN_2_TINT); 1076 rgb_color darkenmax = tint_color(base, B_DARKEN_MAX_TINT); 1077 1078 view->BeginLineArray(9); 1079 1080 view->AddLine(BPoint(rect.left, rect.top), 1081 BPoint(rect.left + 1, rect.top), darken1); 1082 view->AddLine(BPoint(rect.left, rect.bottom), 1083 BPoint(rect.left + 1, rect.bottom), darken1); 1084 view->AddLine(BPoint(rect.right - 1, rect.top), 1085 BPoint(rect.right, rect.top), darken1); 1086 1087 view->AddLine(BPoint(rect.left + 1, rect.top), 1088 BPoint(rect.right - 1, rect.top), darken2); 1089 view->AddLine(BPoint(rect.left, rect.bottom - 1), 1090 BPoint(rect.left, rect.top + 1), darken2); 1091 1092 view->AddLine(BPoint(rect.left + 1, rect.bottom), 1093 BPoint(rect.right, rect.bottom), lightenmax); 1094 view->AddLine(BPoint(rect.right, rect.top + 1), 1095 BPoint(rect.right, rect.bottom), lightenmax); 1096 1097 rect.InsetBy(1, 1); 1098 1099 view->AddLine(BPoint(rect.left, rect.top), 1100 BPoint(rect.left, rect.bottom), darkenmax); 1101 view->AddLine(BPoint(rect.left, rect.top), 1102 BPoint(rect.right, rect.top), darkenmax); 1103 1104 view->EndLineArray(); 1105 } 1106 1107 1108 void 1109 BeControlLook::DrawSliderThumb(BView* view, BRect& rect, const BRect& updateRect, 1110 const rgb_color& base, uint32 flags, orientation orientation) 1111 { 1112 if (!ShouldDraw(view, rect, updateRect)) 1113 return; 1114 1115 rgb_color lighten2 = tint_color(base, B_LIGHTEN_2_TINT); 1116 rgb_color dark = tint_color(base, 1.333); // 144 1117 rgb_color darker = tint_color(base, 1.444); // 120 1118 rgb_color darkenmax = tint_color(base, B_DARKEN_MAX_TINT); 1119 1120 view->BeginLineArray(14); 1121 1122 // outline 1123 view->AddLine(BPoint(rect.left, rect.bottom - 2), 1124 BPoint(rect.left, rect.top + 1), darker); 1125 view->AddLine(BPoint(rect.left + 1, rect.top), 1126 BPoint(rect.right - 2, rect.top), darker); 1127 view->AddLine(BPoint(rect.right, rect.top + 2), 1128 BPoint(rect.right, rect.bottom - 1), darker); 1129 view->AddLine(BPoint(rect.left + 2, rect.bottom), 1130 BPoint(rect.right - 1, rect.bottom), darker); 1131 1132 // first bevel 1133 rect.InsetBy(1, 1); 1134 1135 view->SetHighColor(lighten2); 1136 view->FillRect(rect); 1137 1138 view->AddLine(BPoint(rect.left, rect.bottom), 1139 BPoint(rect.right - 1, rect.bottom), darkenmax); 1140 view->AddLine(BPoint(rect.right, rect.bottom - 1), 1141 BPoint(rect.right, rect.top), darkenmax); 1142 1143 rect.InsetBy(1, 1); 1144 1145 // second bevel and center dots 1146 view->SetHighColor(dark); 1147 view->AddLine(BPoint(rect.left, rect.bottom), 1148 BPoint(rect.right, rect.bottom), dark); 1149 view->AddLine(BPoint(rect.right, rect.top), 1150 BPoint(rect.right, rect.bottom), dark); 1151 1152 // center dots 1153 float hCenter = rect.Width() / 2; 1154 float vMiddle = rect.Height() / 2; 1155 if (orientation == B_HORIZONTAL) { 1156 view->AddLine(BPoint(rect.left + hCenter, rect.top + 1), 1157 BPoint(rect.left + hCenter, rect.top + 1), dark); 1158 view->AddLine(BPoint(rect.left + hCenter, rect.top + 3), 1159 BPoint(rect.left + hCenter, rect.top + 3), dark); 1160 view->AddLine(BPoint(rect.left + hCenter, rect.top + 5), 1161 BPoint(rect.left + hCenter, rect.top + 5), dark); 1162 } else { 1163 view->AddLine(BPoint(rect.left + 1, rect.top + vMiddle), 1164 BPoint(rect.left + 1, rect.top + vMiddle), dark); 1165 view->AddLine(BPoint(rect.left + 3, rect.top + vMiddle), 1166 BPoint(rect.left + 3, rect.top + vMiddle), dark); 1167 view->AddLine(BPoint(rect.left + 5, rect.top + vMiddle - 1), 1168 BPoint(rect.left + 5, rect.top + vMiddle), dark); 1169 } 1170 1171 view->AddLine(BPoint(rect.right + 1, rect.bottom + 1), 1172 BPoint(rect.right + 1, rect.bottom + 1), dark); 1173 1174 rect.InsetBy(1, 1); 1175 1176 // third bevel 1177 view->AddLine(BPoint(rect.left, rect.bottom), 1178 BPoint(rect.right, rect.bottom), base); 1179 view->AddLine(BPoint(rect.right, rect.top), 1180 BPoint(rect.right, rect.bottom), base); 1181 1182 view->EndLineArray(); 1183 } 1184 1185 1186 void 1187 BeControlLook::DrawSliderTriangle(BView* view, BRect& rect, 1188 const BRect& updateRect, const rgb_color& base, uint32 flags, 1189 orientation orientation) 1190 { 1191 DrawSliderTriangle(view, rect, updateRect, base, base, flags, orientation); 1192 } 1193 1194 1195 void 1196 BeControlLook::DrawSliderTriangle(BView* view, BRect& rect, 1197 const BRect& updateRect, const rgb_color& base, const rgb_color& fill, 1198 uint32 flags, orientation orientation) 1199 { 1200 if (!ShouldDraw(view, rect, updateRect)) 1201 return; 1202 1203 rgb_color lighten1 = tint_color(base, B_LIGHTEN_1_TINT); 1204 rgb_color darken2 = tint_color(base, B_DARKEN_2_TINT); 1205 rgb_color darkenmax = tint_color(base, B_DARKEN_MAX_TINT); 1206 1207 if (orientation == B_HORIZONTAL) { 1208 view->SetHighColor(lighten1); 1209 view->FillTriangle(BPoint(rect.left, rect.bottom - 1), 1210 BPoint(rect.left + 6, rect.top), 1211 BPoint(rect.right, rect.bottom - 1)); 1212 1213 view->SetHighColor(darkenmax); 1214 view->StrokeLine(BPoint(rect.right, rect.bottom + 1), 1215 BPoint(rect.left, rect.bottom + 1)); 1216 view->StrokeLine(BPoint(rect.right, rect.bottom), 1217 BPoint(rect.left + 6, rect.top)); 1218 1219 view->SetHighColor(darken2); 1220 view->StrokeLine(BPoint(rect.right - 1, rect.bottom), 1221 BPoint(rect.left, rect.bottom)); 1222 view->StrokeLine(BPoint(rect.left, rect.bottom), 1223 BPoint(rect.left + 5, rect.top + 1)); 1224 1225 view->SetHighColor(base); 1226 view->StrokeLine(BPoint(rect.right - 2, rect.bottom - 1), 1227 BPoint(rect.left + 3, rect.bottom - 1)); 1228 view->StrokeLine(BPoint(rect.right - 3, rect.bottom - 2), 1229 BPoint(rect.left + 6, rect.top + 1)); 1230 } else { 1231 view->SetHighColor(lighten1); 1232 view->FillTriangle(BPoint(rect.left + 1, rect.top), 1233 BPoint(rect.left + 7, rect.top + 6), 1234 BPoint(rect.left + 1, rect.bottom)); 1235 1236 view->SetHighColor(darkenmax); 1237 view->StrokeLine(BPoint(rect.left, rect.top + 1), 1238 BPoint(rect.left, rect.bottom)); 1239 view->StrokeLine(BPoint(rect.left + 1, rect.bottom), 1240 BPoint(rect.left + 7, rect.top + 6)); 1241 1242 view->SetHighColor(darken2); 1243 view->StrokeLine(BPoint(rect.left, rect.top), 1244 BPoint(rect.left, rect.bottom - 1)); 1245 view->StrokeLine(BPoint(rect.left + 1, rect.top), 1246 BPoint(rect.left + 6, rect.top + 5)); 1247 1248 view->SetHighColor(base); 1249 view->StrokeLine(BPoint(rect.left + 1, rect.top + 2), 1250 BPoint(rect.left + 1, rect.bottom - 1)); 1251 view->StrokeLine(BPoint(rect.left + 2, rect.bottom - 2), 1252 BPoint(rect.left + 6, rect.top + 6)); 1253 } 1254 } 1255 1256 1257 void 1258 BeControlLook::DrawSliderHashMarks(BView* view, BRect& rect, 1259 const BRect& updateRect, const rgb_color& base, int32 count, 1260 hash_mark_location location, uint32 flags, orientation orientation) 1261 { 1262 if (!ShouldDraw(view, rect, updateRect)) 1263 return; 1264 1265 rgb_color lightColor; 1266 rgb_color darkColor; 1267 1268 if ((flags & B_DISABLED) != 0) { 1269 lightColor = tint_color(base, 0.9); 1270 darkColor = tint_color(base, 1.07); 1271 } else { 1272 lightColor = tint_color(base, 0.8); 1273 darkColor = tint_color(base, 1.14); 1274 } 1275 1276 int32 hashMarkCount = std::max(count, (int32)2); 1277 // draw at least two hashmarks at min/max if 1278 // fHashMarks != B_HASH_MARKS_NONE 1279 float factor; 1280 float startPos; 1281 if (orientation == B_HORIZONTAL) { 1282 factor = (rect.Width() - 2) / (hashMarkCount - 1); 1283 startPos = rect.left + 1; 1284 } else { 1285 factor = (rect.Height() - 2) / (hashMarkCount - 1); 1286 startPos = rect.top + 1; 1287 } 1288 1289 if (location & B_HASH_MARKS_TOP) { 1290 view->BeginLineArray(hashMarkCount * 2); 1291 1292 if (orientation == B_HORIZONTAL) { 1293 float pos = startPos; 1294 for (int32 i = 0; i < hashMarkCount; i++) { 1295 view->AddLine(BPoint(pos, rect.top), 1296 BPoint(pos, rect.top + 4), darkColor); 1297 view->AddLine(BPoint(pos + 1, rect.top), 1298 BPoint(pos + 1, rect.top + 4), lightColor); 1299 1300 pos += factor; 1301 } 1302 } else { 1303 float pos = startPos; 1304 for (int32 i = 0; i < hashMarkCount; i++) { 1305 view->AddLine(BPoint(rect.left, pos), 1306 BPoint(rect.left + 4, pos), darkColor); 1307 view->AddLine(BPoint(rect.left, pos + 1), 1308 BPoint(rect.left + 4, pos + 1), lightColor); 1309 1310 pos += factor; 1311 } 1312 } 1313 1314 view->EndLineArray(); 1315 } 1316 1317 if ((location & B_HASH_MARKS_BOTTOM) != 0) { 1318 view->BeginLineArray(hashMarkCount * 2); 1319 1320 if (orientation == B_HORIZONTAL) { 1321 float pos = startPos; 1322 for (int32 i = 0; i < hashMarkCount; i++) { 1323 view->AddLine(BPoint(pos, rect.bottom - 4), 1324 BPoint(pos, rect.bottom), darkColor); 1325 view->AddLine(BPoint(pos + 1, rect.bottom - 4), 1326 BPoint(pos + 1, rect.bottom), lightColor); 1327 1328 pos += factor; 1329 } 1330 } else { 1331 float pos = startPos; 1332 for (int32 i = 0; i < hashMarkCount; i++) { 1333 view->AddLine(BPoint(rect.right - 4, pos), 1334 BPoint(rect.right, pos), darkColor); 1335 view->AddLine(BPoint(rect.right - 4, pos + 1), 1336 BPoint(rect.right, pos + 1), lightColor); 1337 1338 pos += factor; 1339 } 1340 } 1341 1342 view->EndLineArray(); 1343 } 1344 } 1345 1346 1347 void 1348 BeControlLook::DrawTabFrame(BView* view, BRect& rect, const BRect& updateRect, 1349 const rgb_color& base, uint32 flags, uint32 borders, 1350 border_style borderStyle, uint32 side) 1351 { 1352 view->SetHighColor(base); 1353 view->FillRect(rect); 1354 1355 rgb_color lightenmax = tint_color(base, B_LIGHTEN_MAX_TINT); 1356 1357 view->BeginLineArray(1); 1358 1359 switch(side) { 1360 case BTabView::kLeftSide: 1361 view->AddLine(BPoint(rect.right, rect.top), 1362 BPoint(rect.right, rect.bottom), lightenmax); 1363 break; 1364 1365 case BTabView::kRightSide: 1366 view->AddLine(BPoint(rect.left, rect.top), 1367 BPoint(rect.left, rect.bottom), lightenmax); 1368 break; 1369 1370 default: 1371 case BTabView::kTopSide: 1372 view->AddLine(BPoint(rect.left, rect.bottom), 1373 BPoint(rect.right, rect.bottom), lightenmax); 1374 break; 1375 1376 case BTabView::kBottomSide: 1377 view->AddLine(BPoint(rect.left, rect.top), 1378 BPoint(rect.right, rect.top), lightenmax); 1379 break; 1380 } 1381 1382 view->EndLineArray(); 1383 } 1384 1385 1386 void 1387 BeControlLook::DrawActiveTab(BView* view, BRect& rect, 1388 const BRect& updateRect, const rgb_color& base, uint32 flags, 1389 uint32 borders, uint32 side, int32, int32, int32, int32) 1390 { 1391 if (!ShouldDraw(view, rect, updateRect)) 1392 return; 1393 1394 view->PushState(); 1395 1396 // clip draw rect to rect plus 2px 1397 view->ClipToRect(rect.InsetByCopy(-2, -2)); 1398 1399 // set colors and draw 1400 1401 rgb_color lightenmax = tint_color(base, B_LIGHTEN_MAX_TINT); 1402 rgb_color darken4 = tint_color(base, B_DARKEN_4_TINT); 1403 rgb_color darkenmax = tint_color(base, B_DARKEN_MAX_TINT); 1404 1405 view->SetHighColor(darkenmax); 1406 view->SetLowColor(base); 1407 1408 view->BeginLineArray(12); 1409 1410 switch (side) { 1411 case BTabView::kLeftSide: 1412 // before going left 1413 view->AddLine(BPoint(rect.right - 1, rect.top - 1), 1414 BPoint(rect.right - 1, rect.top - 1), lightenmax); 1415 view->AddLine(BPoint(rect.right - 2, rect.top), 1416 BPoint(rect.right - 3, rect.top), lightenmax); 1417 1418 // going left 1419 view->AddLine(BPoint(rect.right - 4, rect.top + 1), 1420 BPoint(rect.left + 5, rect.top + 1), lightenmax); 1421 1422 // before going down 1423 view->AddLine(BPoint(rect.left + 2, rect.top + 2), 1424 BPoint(rect.left + 4, rect.top + 2), lightenmax); 1425 view->AddLine(BPoint(rect.left + 1, rect.top + 3), 1426 BPoint(rect.left + 1, rect.top + 4 ), lightenmax); 1427 1428 // going down 1429 view->AddLine(BPoint(rect.left, rect.top + 5), 1430 BPoint(rect.left, rect.bottom - 5), lightenmax); 1431 1432 // after going down 1433 view->AddLine(BPoint(rect.left + 1, rect.bottom - 4), 1434 BPoint(rect.left + 1, rect.bottom - 3), lightenmax); 1435 view->AddLine(BPoint(rect.left + 2, rect.bottom - 2), 1436 BPoint(rect.left + 3, rect.bottom - 2), darken4); 1437 1438 // going right 1439 view->AddLine(BPoint(rect.left + 4, rect.bottom - 1), 1440 BPoint(rect.right - 4, rect.bottom - 1), darken4); 1441 1442 // after going right 1443 view->AddLine(BPoint(rect.right - 3, rect.bottom), 1444 BPoint(rect.right - 2, rect.bottom), darken4); 1445 view->AddLine(BPoint(rect.right - 1, rect.bottom + 1), 1446 BPoint(rect.right - 1, rect.bottom + 1), darken4); 1447 view->AddLine(BPoint(rect.right, rect.bottom + 2), 1448 BPoint(rect.right, rect.bottom + 2), darken4); 1449 break; 1450 1451 case BTabView::kRightSide: 1452 // before going right 1453 view->AddLine(BPoint(rect.left - 1, rect.top - 1), 1454 BPoint(rect.left - 1, rect.top - 1), lightenmax); 1455 view->AddLine(BPoint(rect.left - 2, rect.top), 1456 BPoint(rect.left - 3, rect.top), lightenmax); 1457 1458 // going right 1459 view->AddLine(BPoint(rect.left - 4, rect.top + 1), 1460 BPoint(rect.right + 5, rect.top + 1), lightenmax); 1461 1462 // before going down 1463 view->AddLine(BPoint(rect.right + 2, rect.top + 2), 1464 BPoint(rect.right + 4, rect.top + 2), lightenmax); 1465 view->AddLine(BPoint(rect.right + 1, rect.top + 3), 1466 BPoint(rect.right + 1, rect.top + 4 ), lightenmax); 1467 1468 // going down 1469 view->AddLine(BPoint(rect.right, rect.top + 5), 1470 BPoint(rect.right, rect.bottom - 5), lightenmax); 1471 1472 // after going down 1473 view->AddLine(BPoint(rect.right + 1, rect.bottom - 4), 1474 BPoint(rect.right + 1, rect.bottom - 3), lightenmax); 1475 view->AddLine(BPoint(rect.right + 2, rect.bottom - 2), 1476 BPoint(rect.right + 3, rect.bottom - 2), darken4); 1477 1478 // going left 1479 view->AddLine(BPoint(rect.right + 4, rect.bottom - 1), 1480 BPoint(rect.left - 4, rect.bottom - 1), darken4); 1481 1482 // after going left 1483 view->AddLine(BPoint(rect.left - 3, rect.bottom), 1484 BPoint(rect.left - 2, rect.bottom), darken4); 1485 view->AddLine(BPoint(rect.left - 1, rect.bottom + 1), 1486 BPoint(rect.left - 1, rect.bottom + 1), darken4); 1487 view->AddLine(BPoint(rect.left, rect.bottom + 2), 1488 BPoint(rect.left, rect.bottom + 2), darken4); 1489 break; 1490 1491 default: 1492 case BTabView::kTopSide: 1493 // before going up 1494 view->AddLine(BPoint(rect.left - 1, rect.bottom - 1), 1495 BPoint(rect.left - 1, rect.bottom - 1), lightenmax); 1496 view->AddLine(BPoint(rect.left, rect.bottom - 2), 1497 BPoint(rect.left, rect.bottom - 3), lightenmax); 1498 1499 // going up 1500 view->AddLine(BPoint(rect.left + 1, rect.bottom - 4), 1501 BPoint(rect.left + 1, rect.top + 5), lightenmax); 1502 1503 // before going right 1504 view->AddLine(BPoint(rect.left + 2, rect.top + 4), 1505 BPoint(rect.left + 2, rect.top + 2), lightenmax); 1506 view->AddLine(BPoint(rect.left + 3, rect.top + 1), 1507 BPoint(rect.left + 4, rect.top + 1), lightenmax); 1508 1509 // going right 1510 view->AddLine(BPoint(rect.left + 5, rect.top), 1511 BPoint(rect.right - 5, rect.top), lightenmax); 1512 1513 // after going right 1514 view->AddLine(BPoint(rect.right - 4, rect.top + 1), 1515 BPoint(rect.right - 3, rect.top + 1), lightenmax); 1516 view->AddLine(BPoint(rect.right - 2, rect.top + 2), 1517 BPoint(rect.right - 2, rect.top + 3), darken4); 1518 1519 // going down 1520 view->AddLine(BPoint(rect.right - 1, rect.top + 4), 1521 BPoint(rect.right - 1, rect.bottom - 4), darken4); 1522 1523 // after going down 1524 view->AddLine(BPoint(rect.right, rect.bottom - 3), 1525 BPoint(rect.right, rect.bottom - 2), darken4); 1526 view->AddLine(BPoint(rect.right + 1, rect.bottom - 1), 1527 BPoint(rect.right + 1, rect.bottom - 1), darken4); 1528 view->AddLine(BPoint(rect.right + 2, rect.bottom), 1529 BPoint(rect.right + 2, rect.bottom), darken4); 1530 break; 1531 1532 case BTabView::kBottomSide: 1533 // before going down 1534 view->AddLine(BPoint(rect.left - 1, rect.top - 1), 1535 BPoint(rect.left - 1, rect.top - 1), lightenmax); 1536 view->AddLine(BPoint(rect.left, rect.top - 2), 1537 BPoint(rect.left, rect.top - 3), lightenmax); 1538 1539 // going down 1540 view->AddLine(BPoint(rect.left + 1, rect.top - 4), 1541 BPoint(rect.left + 1, rect.bottom + 5), lightenmax); 1542 1543 // before going right 1544 view->AddLine(BPoint(rect.left + 2, rect.bottom + 4), 1545 BPoint(rect.left + 2, rect.bottom + 2), lightenmax); 1546 view->AddLine(BPoint(rect.left + 3, rect.bottom + 1), 1547 BPoint(rect.left + 4, rect.bottom + 1), lightenmax); 1548 1549 // going right 1550 view->AddLine(BPoint(rect.left + 5, rect.bottom), 1551 BPoint(rect.right - 5, rect.bottom), lightenmax); 1552 1553 // after going right 1554 view->AddLine(BPoint(rect.right - 4, rect.bottom + 1), 1555 BPoint(rect.right - 3, rect.bottom + 1), lightenmax); 1556 view->AddLine(BPoint(rect.right - 2, rect.bottom + 2), 1557 BPoint(rect.right - 2, rect.bottom + 3), darken4); 1558 1559 // going up 1560 view->AddLine(BPoint(rect.right - 1, rect.bottom + 4), 1561 BPoint(rect.right - 1, rect.top - 4), darken4); 1562 1563 // after going up 1564 view->AddLine(BPoint(rect.right, rect.top - 3), 1565 BPoint(rect.right, rect.top - 2), darken4); 1566 view->AddLine(BPoint(rect.right + 1, rect.top - 1), 1567 BPoint(rect.right + 1, rect.top - 1), darken4); 1568 view->AddLine(BPoint(rect.right + 2, rect.top), 1569 BPoint(rect.right + 2, rect.top), darken4); 1570 break; 1571 } 1572 view->EndLineArray(); 1573 1574 // undraw white line 1575 view->BeginLineArray(1); 1576 switch (side) { 1577 case BTabView::kLeftSide: 1578 view->AddLine(BPoint(rect.right, rect.top - 1), 1579 BPoint(rect.right, rect.bottom + 1), base); 1580 break; 1581 1582 case BTabView::kRightSide: 1583 view->AddLine(BPoint(rect.left, rect.top - 1), 1584 BPoint(rect.left, rect.bottom + 1), base); 1585 break; 1586 1587 default: 1588 case BTabView::kTopSide: 1589 view->AddLine(BPoint(rect.left - 1, rect.bottom), 1590 BPoint(rect.right + 1, rect.bottom), base); 1591 break; 1592 1593 case BTabView::kBottomSide: 1594 view->AddLine(BPoint(rect.left - 1, rect.top), 1595 BPoint(rect.right + 1, rect.top), base); 1596 break; 1597 } 1598 view->EndLineArray(); 1599 1600 // inset rect for view contents 1601 rect.InsetBy(2, 2); 1602 1603 view->PopState(); 1604 } 1605 1606 1607 void 1608 BeControlLook::DrawInactiveTab(BView* view, BRect& rect, 1609 const BRect& updateRect, const rgb_color& base, uint32 flags, 1610 uint32 borders, uint32 side, int32 index, int32 selected, 1611 int32 first, int32 last) 1612 { 1613 if (!ShouldDraw(view, rect, updateRect)) 1614 return; 1615 1616 bool isFirst = index == first; 1617 bool isFull = index != selected - 1; 1618 1619 view->PushState(); 1620 1621 // clip draw rect to rect plus 2px 1622 view->ClipToRect(rect.InsetByCopy(-2, -2)); 1623 1624 // set colors and draw 1625 1626 rgb_color lightenmax = tint_color(base, B_LIGHTEN_MAX_TINT); 1627 rgb_color darken4 = tint_color(base, B_DARKEN_4_TINT); 1628 rgb_color darkenmax = tint_color(base, B_DARKEN_MAX_TINT); 1629 1630 view->SetHighColor(darkenmax); 1631 view->SetLowColor(base); 1632 1633 view->BeginLineArray(12); 1634 1635 switch (side) { 1636 case BTabView::kLeftSide: 1637 // only draw if first tab is unselected 1638 if (isFirst) { 1639 // before going left 1640 view->AddLine(BPoint(rect.right - 1, rect.top - 1), 1641 BPoint(rect.right - 1, rect.top - 1), lightenmax); 1642 view->AddLine(BPoint(rect.right - 2, rect.top), 1643 BPoint(rect.right - 3, rect.top), lightenmax); 1644 } 1645 1646 // going left 1647 view->AddLine(BPoint(rect.right - 4, rect.top + 1), 1648 BPoint(rect.left + 5, rect.top + 1), lightenmax); 1649 1650 // before going down 1651 view->AddLine(BPoint(rect.left + 2, rect.top + 2), 1652 BPoint(rect.left + 4, rect.top + 2), lightenmax); 1653 view->AddLine(BPoint(rect.left + 1, rect.top + 3), 1654 BPoint(rect.left + 1, rect.top + 4 ), lightenmax); 1655 1656 // going down 1657 view->AddLine(BPoint(rect.left, rect.top + 5), 1658 BPoint(rect.left, rect.bottom - 5), lightenmax); 1659 1660 // after going down 1661 view->AddLine(BPoint(rect.left + 1, rect.bottom - 4), 1662 BPoint(rect.left + 1, rect.bottom - 3), lightenmax); 1663 view->AddLine(BPoint(rect.left + 2, rect.bottom - 2), 1664 BPoint(rect.left + 3, rect.bottom - 2), darken4); 1665 1666 // going right 1667 view->AddLine(BPoint(rect.left + 4, rect.bottom - 1), 1668 BPoint(rect.right - 4, rect.bottom - 1), darken4); 1669 1670 // only draw if not before selected tab 1671 if (isFull) { 1672 // after going right 1673 view->AddLine(BPoint(rect.right - 3, rect.bottom), 1674 BPoint(rect.right - 2, rect.bottom), darken4); 1675 view->AddLine(BPoint(rect.right - 1, rect.bottom + 1), 1676 BPoint(rect.right - 1, rect.bottom + 1), darken4); 1677 } 1678 break; 1679 1680 case BTabView::kRightSide: 1681 // only draw if first tab is unselected 1682 if (isFirst) { 1683 // before going right 1684 view->AddLine(BPoint(rect.left - 1, rect.top - 1), 1685 BPoint(rect.left - 1, rect.top - 1), lightenmax); 1686 view->AddLine(BPoint(rect.left - 2, rect.top), 1687 BPoint(rect.left - 3, rect.top), lightenmax); 1688 } 1689 1690 // going right 1691 view->AddLine(BPoint(rect.left - 4, rect.top + 1), 1692 BPoint(rect.right + 5, rect.top + 1), lightenmax); 1693 1694 // before going down 1695 view->AddLine(BPoint(rect.right + 2, rect.top + 2), 1696 BPoint(rect.right + 4, rect.top + 2), lightenmax); 1697 view->AddLine(BPoint(rect.right + 1, rect.top + 3), 1698 BPoint(rect.right + 1, rect.top + 4 ), lightenmax); 1699 1700 // going down 1701 view->AddLine(BPoint(rect.right, rect.top + 5), 1702 BPoint(rect.right, rect.bottom - 5), lightenmax); 1703 1704 // after going down 1705 view->AddLine(BPoint(rect.right + 1, rect.bottom - 4), 1706 BPoint(rect.right + 1, rect.bottom - 3), lightenmax); 1707 view->AddLine(BPoint(rect.right + 2, rect.bottom - 2), 1708 BPoint(rect.right + 3, rect.bottom - 2), darken4); 1709 1710 // going left 1711 view->AddLine(BPoint(rect.right + 4, rect.bottom - 1), 1712 BPoint(rect.left - 4, rect.bottom - 1), darken4); 1713 1714 // only draw if not before selected tab 1715 if (isFull) { 1716 // after going left 1717 view->AddLine(BPoint(rect.left - 3, rect.bottom), 1718 BPoint(rect.left - 2, rect.bottom), darken4); 1719 view->AddLine(BPoint(rect.left - 1, rect.bottom + 1), 1720 BPoint(rect.left - 1, rect.bottom + 1), darken4); 1721 } 1722 break; 1723 1724 default: 1725 case BTabView::kTopSide: 1726 // only draw if first tab is unselected 1727 if (isFirst) { 1728 // before going up 1729 view->AddLine(BPoint(rect.left - 1, rect.bottom - 1), 1730 BPoint(rect.left - 1, rect.bottom - 1), lightenmax); 1731 view->AddLine(BPoint(rect.left, rect.bottom - 2), 1732 BPoint(rect.left, rect.bottom - 3), lightenmax);; 1733 } 1734 1735 // going up 1736 view->AddLine(BPoint(rect.left + 1, rect.bottom - 4), 1737 BPoint(rect.left + 1, rect.top + 5), lightenmax); 1738 1739 // before going right 1740 view->AddLine(BPoint(rect.left + 2, rect.top + 4), 1741 BPoint(rect.left + 2, rect.top + 2), lightenmax); 1742 view->AddLine(BPoint(rect.left + 3, rect.top + 1), 1743 BPoint(rect.left + 4, rect.top + 1), lightenmax); 1744 1745 // going right 1746 view->AddLine(BPoint(rect.left + 5, rect.top), 1747 BPoint(rect.right - 5, rect.top), lightenmax); 1748 1749 // after going right 1750 view->AddLine(BPoint(rect.right - 4, rect.top + 1), 1751 BPoint(rect.right - 3, rect.top + 1), lightenmax); 1752 view->AddLine(BPoint(rect.right - 2, rect.top + 2), 1753 BPoint(rect.right - 2, rect.top + 3), darken4); 1754 1755 // going down 1756 view->AddLine(BPoint(rect.right - 1, rect.top + 4), 1757 BPoint(rect.right - 1, rect.bottom - 4), darken4); 1758 1759 // only draw if not before selected tab 1760 if (isFull) { 1761 // after going down 1762 view->AddLine(BPoint(rect.right, rect.bottom - 3), 1763 BPoint(rect.right, rect.bottom - 2), darken4); 1764 view->AddLine(BPoint(rect.right + 1, rect.bottom - 1), 1765 BPoint(rect.right + 1, rect.bottom - 1), darken4); 1766 } 1767 break; 1768 1769 case BTabView::kBottomSide: 1770 // only draw if first tab is unselected 1771 if (isFirst) { 1772 // before going down 1773 view->AddLine(BPoint(rect.left - 1, rect.top - 1), 1774 BPoint(rect.left - 1, rect.top - 1), lightenmax); 1775 view->AddLine(BPoint(rect.left, rect.top - 2), 1776 BPoint(rect.left, rect.top - 3), lightenmax); 1777 } 1778 1779 // before going down 1780 view->AddLine(BPoint(rect.left + 1, rect.top - 4), 1781 BPoint(rect.left + 1, rect.bottom + 5), lightenmax); 1782 1783 // before going right 1784 view->AddLine(BPoint(rect.left + 2, rect.bottom + 4), 1785 BPoint(rect.left + 2, rect.bottom + 2), lightenmax); 1786 view->AddLine(BPoint(rect.left + 3, rect.bottom + 1), 1787 BPoint(rect.left + 4, rect.bottom + 1), lightenmax); 1788 1789 // going right 1790 view->AddLine(BPoint(rect.left + 5, rect.bottom), 1791 BPoint(rect.right - 5, rect.bottom), lightenmax); 1792 1793 // after going right 1794 view->AddLine(BPoint(rect.right - 4, rect.bottom + 1), 1795 BPoint(rect.right - 3, rect.bottom + 1), lightenmax); 1796 view->AddLine(BPoint(rect.right - 2, rect.bottom + 2), 1797 BPoint(rect.right - 2, rect.bottom + 3), darken4); 1798 1799 // going up 1800 view->AddLine(BPoint(rect.right - 1, rect.bottom + 4), 1801 BPoint(rect.right - 1, rect.top - 4), darken4); 1802 1803 // only draw if not before selected tab 1804 if (isFull) { 1805 // after going up 1806 view->AddLine(BPoint(rect.right, rect.top - 3), 1807 BPoint(rect.right, rect.top - 2), darken4); 1808 view->AddLine(BPoint(rect.right + 1, rect.top - 1), 1809 BPoint(rect.right + 1, rect.top - 1), darken4); 1810 } 1811 break; 1812 } 1813 1814 view->EndLineArray(); 1815 1816 // inset rect for view contents 1817 rect.InsetBy(2, 2); 1818 1819 view->PopState(); 1820 } 1821 1822 1823 void 1824 BeControlLook::DrawSplitter(BView* view, BRect& rect, const BRect& updateRect, 1825 const rgb_color& base, orientation orientation, uint32 flags, 1826 uint32 borders) 1827 { 1828 if (!ShouldDraw(view, rect, updateRect)) 1829 return; 1830 1831 rgb_color background; 1832 if ((flags & (B_CLICKED | B_ACTIVATED)) != 0) 1833 background = tint_color(base, B_DARKEN_1_TINT); 1834 else 1835 background = base; 1836 1837 rgb_color light = tint_color(background, 0.6); 1838 rgb_color shadow = tint_color(background, 1.21); 1839 1840 // frame 1841 if (borders != 0 && rect.Width() > 3 && rect.Height() > 3) 1842 DrawRaisedBorder(view, rect, updateRect, background, flags, borders); 1843 1844 // dots and rest of background 1845 if (orientation == B_HORIZONTAL) { 1846 if (rect.Width() > 2) { 1847 // background on left/right 1848 BRegion region(rect); 1849 rect.left = floorf((rect.left + rect.right) / 2.0 - 0.5); 1850 rect.right = rect.left + 1; 1851 region.Exclude(rect); 1852 view->SetHighColor(background); 1853 view->FillRegion(®ion); 1854 } 1855 1856 BPoint dot = rect.LeftTop(); 1857 BPoint stop = rect.LeftBottom(); 1858 int32 num = 1; 1859 while (dot.y <= stop.y) { 1860 rgb_color col1; 1861 rgb_color col2; 1862 switch (num) { 1863 case 1: 1864 col1 = background; 1865 col2 = background; 1866 break; 1867 case 2: 1868 col1 = shadow; 1869 col2 = background; 1870 break; 1871 case 3: 1872 default: 1873 col1 = background; 1874 col2 = light; 1875 num = 0; 1876 break; 1877 } 1878 view->SetHighColor(col1); 1879 view->StrokeLine(dot, dot, B_SOLID_HIGH); 1880 view->SetHighColor(col2); 1881 dot.x++; 1882 view->StrokeLine(dot, dot, B_SOLID_HIGH); 1883 dot.x -= 1.0; 1884 // next pixel 1885 num++; 1886 dot.y++; 1887 } 1888 } else { 1889 if (rect.Height() > 2) { 1890 // background on left/right 1891 BRegion region(rect); 1892 rect.top = floorf((rect.top + rect.bottom) / 2.0 - 0.5); 1893 rect.bottom = rect.top + 1; 1894 region.Exclude(rect); 1895 view->SetHighColor(background); 1896 view->FillRegion(®ion); 1897 } 1898 1899 BPoint dot = rect.LeftTop(); 1900 BPoint stop = rect.RightTop(); 1901 int32 num = 1; 1902 while (dot.x <= stop.x) { 1903 rgb_color col1; 1904 rgb_color col2; 1905 switch (num) { 1906 case 1: 1907 col1 = background; 1908 col2 = background; 1909 break; 1910 case 2: 1911 col1 = shadow; 1912 col2 = background; 1913 break; 1914 case 3: 1915 default: 1916 col1 = background; 1917 col2 = light; 1918 num = 0; 1919 break; 1920 } 1921 view->SetHighColor(col1); 1922 view->StrokeLine(dot, dot, B_SOLID_HIGH); 1923 view->SetHighColor(col2); 1924 dot.y++; 1925 view->StrokeLine(dot, dot, B_SOLID_HIGH); 1926 dot.y -= 1.0; 1927 // next pixel 1928 num++; 1929 dot.x++; 1930 } 1931 } 1932 } 1933 1934 1935 // #pragma mark - various borders 1936 1937 1938 void 1939 BeControlLook::DrawBorder(BView* view, BRect& rect, const BRect& updateRect, 1940 const rgb_color& base, border_style borderStyle, uint32 flags, 1941 uint32 borders) 1942 { 1943 if (borderStyle == B_NO_BORDER) 1944 return; 1945 1946 if (!ShouldDraw(view, rect, updateRect)) 1947 return; 1948 1949 view->PushState(); 1950 1951 view->ClipToRect(rect); 1952 1953 rgb_color lightColor; 1954 rgb_color shadowColor; 1955 if (base.IsLight()) { 1956 lightColor = tint_color(base, B_DARKEN_2_TINT); 1957 shadowColor = tint_color(base, B_LIGHTEN_2_TINT); 1958 } else { 1959 lightColor = tint_color(base, B_LIGHTEN_MAX_TINT); 1960 shadowColor = tint_color(base, B_DARKEN_3_TINT); 1961 } 1962 1963 view->BeginLineArray(8); 1964 1965 if (borderStyle == B_FANCY_BORDER) { 1966 if ((borders & B_LEFT_BORDER) != 0) { 1967 view->AddLine(rect.LeftBottom(), rect.LeftTop(), shadowColor); 1968 rect.left++; 1969 } 1970 if ((borders & B_TOP_BORDER) != 0) { 1971 view->AddLine(rect.LeftTop(), rect.RightTop(), shadowColor); 1972 rect.top++; 1973 } 1974 if ((borders & B_RIGHT_BORDER) != 0) { 1975 view->AddLine(rect.RightTop(), rect.RightBottom(), shadowColor); 1976 rect.right--; 1977 } 1978 if ((borders & B_BOTTOM_BORDER) != 0) { 1979 view->AddLine(rect.RightBottom(), rect.LeftBottom(), shadowColor); 1980 rect.bottom--; 1981 } 1982 1983 if ((borders & B_LEFT_BORDER) != 0) { 1984 view->AddLine(rect.LeftBottom(), rect.LeftTop(), lightColor); 1985 rect.left++; 1986 } 1987 if ((borders & B_TOP_BORDER) != 0) { 1988 view->AddLine(rect.LeftTop(), rect.RightTop(), lightColor); 1989 rect.top++; 1990 } 1991 if ((borders & B_RIGHT_BORDER) != 0) { 1992 view->AddLine(rect.RightTop(), rect.RightBottom(), lightColor); 1993 rect.right--; 1994 } 1995 if ((borders & B_BOTTOM_BORDER) != 0) { 1996 view->AddLine(rect.RightBottom(), rect.LeftBottom(), lightColor); 1997 rect.bottom--; 1998 } 1999 } else if (borderStyle == B_PLAIN_BORDER) { 2000 if ((borders & B_LEFT_BORDER) != 0) { 2001 view->AddLine(rect.LeftBottom(), rect.LeftTop(), shadowColor); 2002 rect.left++; 2003 } 2004 if ((borders & B_TOP_BORDER) != 0) { 2005 view->AddLine(rect.LeftTop(), rect.RightTop(), shadowColor); 2006 rect.top++; 2007 } 2008 if ((borders & B_RIGHT_BORDER) != 0) { 2009 view->AddLine(rect.RightTop(), rect.RightBottom(), shadowColor); 2010 rect.right--; 2011 } 2012 if ((borders & B_BOTTOM_BORDER) != 0) { 2013 view->AddLine(rect.RightBottom(), rect.LeftBottom(), shadowColor); 2014 rect.bottom--; 2015 } 2016 2017 if ((borders & B_LEFT_BORDER) != 0) { 2018 view->AddLine(rect.LeftBottom(), rect.LeftTop(), lightColor); 2019 rect.left++; 2020 } 2021 if ((borders & B_TOP_BORDER) != 0) { 2022 view->AddLine(rect.LeftTop(), rect.RightTop(), lightColor); 2023 rect.top++; 2024 } 2025 if ((borders & B_RIGHT_BORDER) != 0) { 2026 view->AddLine(rect.RightTop(), rect.RightBottom(), lightColor); 2027 rect.right--; 2028 } 2029 if ((borders & B_BOTTOM_BORDER) != 0) { 2030 view->AddLine(rect.RightBottom(), rect.LeftBottom(), lightColor); 2031 rect.bottom--; 2032 } 2033 } 2034 2035 view->EndLineArray(); 2036 2037 view->PopState(); 2038 } 2039 2040 2041 void 2042 BeControlLook::DrawRaisedBorder(BView* view, BRect& rect, 2043 const BRect& updateRect, const rgb_color& base, uint32 flags, 2044 uint32 borders) 2045 { 2046 if (!ShouldDraw(view, rect, updateRect)) 2047 return; 2048 2049 view->PushState(); 2050 2051 view->ClipToRect(rect); 2052 2053 rgb_color lightColor; 2054 rgb_color shadowColor; 2055 2056 if ((flags & B_DISABLED) != 0) { 2057 lightColor = base; 2058 shadowColor = base; 2059 } else { 2060 lightColor = tint_color(base, 0.85); 2061 shadowColor = tint_color(base, 1.07); 2062 } 2063 2064 view->BeginLineArray(8); 2065 2066 if ((borders & B_LEFT_BORDER) != 0) { 2067 view->AddLine(rect.LeftBottom(), rect.LeftTop(), lightColor); 2068 rect.left++; 2069 } 2070 if ((borders & B_TOP_BORDER) != 0) { 2071 view->AddLine(rect.LeftTop(), rect.RightTop(), lightColor); 2072 rect.top++; 2073 } 2074 if ((borders & B_RIGHT_BORDER) != 0) { 2075 view->AddLine(rect.RightTop(), rect.RightBottom(), lightColor); 2076 rect.right--; 2077 } 2078 if ((borders & B_BOTTOM_BORDER) != 0) { 2079 view->AddLine(rect.RightBottom(), rect.LeftBottom(), lightColor); 2080 rect.bottom--; 2081 } 2082 2083 if ((borders & B_LEFT_BORDER) != 0) { 2084 view->AddLine(rect.LeftBottom(), rect.LeftTop(), shadowColor); 2085 rect.left++; 2086 } 2087 if ((borders & B_TOP_BORDER) != 0) { 2088 view->AddLine(rect.LeftTop(), rect.RightTop(), shadowColor); 2089 rect.top++; 2090 } 2091 if ((borders & B_RIGHT_BORDER) != 0) { 2092 view->AddLine(rect.RightTop(), rect.RightBottom(), shadowColor); 2093 rect.right--; 2094 } 2095 if ((borders & B_BOTTOM_BORDER) != 0) { 2096 view->AddLine(rect.RightBottom(), rect.LeftBottom(), shadowColor); 2097 rect.bottom--; 2098 } 2099 2100 view->EndLineArray(); 2101 2102 view->PopState(); 2103 } 2104 2105 2106 void 2107 BeControlLook::DrawTextControlBorder(BView* view, BRect& rect, 2108 const BRect& updateRect, const rgb_color& base, uint32 flags, 2109 uint32 borders) 2110 { 2111 if (!ShouldDraw(view, rect, updateRect)) 2112 return; 2113 2114 view->PushState(); 2115 2116 view->ClipToRect(rect); 2117 2118 bool isEnabled = (flags & B_DISABLED) == 0; 2119 bool isFocused = (flags & B_FOCUSED) != 0; 2120 2121 rgb_color dark; 2122 rgb_color light; 2123 2124 // outer bevel 2125 2126 dark = tint_color(base, (isEnabled ? B_DARKEN_1_TINT : B_DARKEN_2_TINT)); 2127 light = tint_color(base, (isEnabled ? B_LIGHTEN_MAX_TINT : B_LIGHTEN_2_TINT)); 2128 2129 _DrawFrame(view, rect, dark, dark, light, light); 2130 2131 // inner bevel 2132 2133 if (isEnabled && isFocused) { 2134 view->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); 2135 view->StrokeRect(rect); 2136 rect.InsetBy(1, 1); 2137 } else { 2138 dark = tint_color(base, (isEnabled ? B_DARKEN_4_TINT : B_LIGHTEN_2_TINT)); 2139 light = base; 2140 2141 _DrawFrame(view, rect, dark, dark, light, light); 2142 } 2143 2144 view->PopState(); 2145 } 2146 2147 2148 void 2149 BeControlLook::DrawGroupFrame(BView* view, BRect& rect, const BRect& updateRect, 2150 const rgb_color& base, uint32 borders) 2151 { 2152 DrawBorder(view, rect, updateRect, base, B_FANCY_BORDER, 0, borders); 2153 } 2154 2155 2156 // #pragma mark - Labels 2157 2158 2159 void 2160 BeControlLook::DrawLabel(BView* view, const char* label, BRect rect, 2161 const BRect& updateRect, const rgb_color& base, uint32 flags, 2162 const rgb_color* textColor) 2163 { 2164 DrawLabel(view, label, NULL, rect, updateRect, base, flags, 2165 DefaultLabelAlignment(), textColor); 2166 } 2167 2168 2169 void 2170 BeControlLook::DrawLabel(BView* view, const char* label, BRect rect, 2171 const BRect& updateRect, const rgb_color& base, uint32 flags, 2172 const BAlignment& alignment, const rgb_color* textColor) 2173 { 2174 DrawLabel(view, label, NULL, rect, updateRect, base, flags, alignment, 2175 textColor); 2176 } 2177 2178 2179 void 2180 BeControlLook::DrawLabel(BView* view, const char* label, const rgb_color& base, 2181 uint32 flags, const BPoint& where, const rgb_color* textColor) 2182 { 2183 view->PushState(); 2184 2185 bool isButton = (flags & B_FLAT) != 0 || (flags & B_HOVER) != 0 2186 || (flags & B_DEFAULT_BUTTON) != 0; 2187 bool isEnabled = (flags & B_DISABLED) == 0; 2188 bool isActivated = (flags & B_ACTIVATED) != 0; 2189 2190 BWindow* window = view->Window(); 2191 bool isDesktop = window != NULL 2192 && window->Feel() == kDesktopWindowFeel 2193 && window->Look() == kDesktopWindowLook 2194 && view->Parent() 2195 && view->Parent()->Parent() == NULL 2196 && (flags & B_IGNORE_OUTLINE) == 0; 2197 2198 rgb_color low; 2199 rgb_color color; 2200 rgb_color glowColor; 2201 2202 if (textColor != NULL) 2203 glowColor = *textColor; 2204 else if (view->Parent() != NULL) 2205 glowColor = view->Parent()->HighColor(); 2206 else if ((flags & B_IS_CONTROL) != 0) 2207 glowColor = ui_color(B_CONTROL_TEXT_COLOR); 2208 else 2209 glowColor = ui_color(B_PANEL_TEXT_COLOR); 2210 2211 color = glowColor; 2212 2213 if (isDesktop) 2214 low = view->Parent()->ViewColor(); 2215 else 2216 low = base; 2217 2218 if (!isEnabled) { 2219 color.red = (uint8)(((int32)low.red + color.red + 1) / 2); 2220 color.green = (uint8)(((int32)low.green + color.green + 1) / 2); 2221 color.blue = (uint8)(((int32)low.blue + color.blue + 1) / 2); 2222 } 2223 2224 if (isDesktop) { 2225 // enforce proper use of desktop label colors 2226 if (low.IsDark()) { 2227 if (textColor == NULL) 2228 color = make_color(255, 255, 255); 2229 2230 glowColor = make_color(0, 0, 0); 2231 } else { 2232 if (textColor == NULL) 2233 color = make_color(0, 0, 0); 2234 2235 glowColor = make_color(255, 255, 255); 2236 } 2237 2238 // drawing occurs on the desktop 2239 if (fCachedWorkspace != current_workspace()) { 2240 int8 indice = 0; 2241 int32 mask; 2242 bool tmpOutline; 2243 while (fBackgroundInfo.FindInt32("be:bgndimginfoworkspaces", 2244 indice, &mask) == B_OK 2245 && fBackgroundInfo.FindBool("be:bgndimginfoerasetext", 2246 indice, &tmpOutline) == B_OK) { 2247 2248 if (((1 << current_workspace()) & mask) != 0) { 2249 fCachedOutline = tmpOutline; 2250 fCachedWorkspace = current_workspace(); 2251 break; 2252 } 2253 indice++; 2254 } 2255 } 2256 2257 if (fCachedOutline) { 2258 BFont font; 2259 view->GetFont(&font); 2260 2261 view->SetDrawingMode(B_OP_ALPHA); 2262 view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); 2263 // Draw glow or outline 2264 if (glowColor.IsLight()) { 2265 font.SetFalseBoldWidth(2.0); 2266 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH); 2267 2268 glowColor.alpha = 30; 2269 view->SetHighColor(glowColor); 2270 view->DrawString(label, where); 2271 2272 font.SetFalseBoldWidth(1.0); 2273 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH); 2274 2275 glowColor.alpha = 65; 2276 view->SetHighColor(glowColor); 2277 view->DrawString(label, where); 2278 2279 font.SetFalseBoldWidth(0.0); 2280 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH); 2281 } else { 2282 font.SetFalseBoldWidth(1.0); 2283 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH); 2284 2285 glowColor.alpha = 30; 2286 view->SetHighColor(glowColor); 2287 view->DrawString(label, where); 2288 2289 font.SetFalseBoldWidth(0.0); 2290 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH); 2291 2292 glowColor.alpha = 200; 2293 view->SetHighColor(glowColor); 2294 view->DrawString(label, BPoint(where.x + 1, where.y + 1)); 2295 } 2296 } 2297 } 2298 2299 rgb_color invertedIfClicked = color; 2300 if (isButton && isEnabled && isActivated) { 2301 // only for enabled and activated buttons 2302 invertedIfClicked.red = 255 - invertedIfClicked.red; 2303 invertedIfClicked.green = 255 - invertedIfClicked.green; 2304 invertedIfClicked.blue = 255 - invertedIfClicked.blue; 2305 } 2306 2307 view->SetLowColor(invertedIfClicked); 2308 view->SetHighColor(invertedIfClicked); 2309 view->SetDrawingMode(B_OP_OVER); 2310 view->DrawString(label, where); 2311 view->SetDrawingMode(B_OP_COPY); 2312 2313 view->PopState(); 2314 } 2315 2316 2317 void 2318 BeControlLook::DrawLabel(BView* view, const char* label, const BBitmap* icon, 2319 BRect rect, const BRect& updateRect, const rgb_color& base, uint32 flags, 2320 const BAlignment& alignment, const rgb_color* textColor) 2321 { 2322 if (!ShouldDraw(view, rect, updateRect)) 2323 return; 2324 2325 if (label == NULL && icon == NULL) 2326 return; 2327 2328 if (label == NULL && icon != NULL) { 2329 // icon only 2330 BRect alignedRect = BLayoutUtils::AlignInFrame( 2331 rect.OffsetByCopy(-2, -2), 2332 icon->Bounds().Size(), alignment); 2333 view->SetDrawingMode(B_OP_OVER); 2334 view->DrawBitmap(icon, alignedRect.LeftTop()); 2335 view->SetDrawingMode(B_OP_COPY); 2336 return; 2337 } 2338 2339 view->PushState(); 2340 2341 // label, possibly with icon 2342 float availableWidth = rect.Width() + 1; 2343 float width = 0; 2344 float textOffset = 0; 2345 float height = 0; 2346 2347 if (icon != NULL && label != NULL) { 2348 // move text over to fit icon 2349 width = icon->Bounds().Width() + DefaultLabelSpacing() + 1; 2350 height = icon->Bounds().Height() + 1; 2351 textOffset = width; 2352 availableWidth -= textOffset; 2353 } 2354 2355 // truncate the label if necessary and get the width and height 2356 BString truncatedLabel(label); 2357 2358 BFont font; 2359 view->GetFont(&font); 2360 2361 font.TruncateString(&truncatedLabel, B_TRUNCATE_MIDDLE, availableWidth); 2362 width += ceilf(font.StringWidth(truncatedLabel.String())); 2363 2364 font_height fontHeight; 2365 font.GetHeight(&fontHeight); 2366 float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent); 2367 height = std::max(height, textHeight); 2368 2369 // handle alignment 2370 BRect alignedRect(BLayoutUtils::AlignOnRect(rect, 2371 BSize(width - 1, height - 1), alignment)); 2372 2373 if (icon != NULL) { 2374 BPoint location(alignedRect.LeftTop()); 2375 if (icon->Bounds().Height() + 1 < height) 2376 location.y += ceilf((height - icon->Bounds().Height() - 1) / 2); 2377 2378 view->SetDrawingMode(B_OP_OVER); 2379 view->DrawBitmap(icon, location); 2380 view->SetDrawingMode(B_OP_COPY); 2381 } 2382 2383 BPoint location(alignedRect.left + textOffset, 2384 alignedRect.top + ceilf(fontHeight.ascent)); 2385 if (textHeight < height) 2386 location.y += ceilf((height - textHeight) / 2); 2387 2388 if ((flags & B_FOCUSED) != 0) { 2389 // draw underline under label 2390 float x = location.x; 2391 float y = location.y + ceilf(fontHeight.descent); 2392 view->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); 2393 view->StrokeLine(BPoint(x, y), 2394 BPoint(x + view->StringWidth(truncatedLabel.String()), y)); 2395 } 2396 2397 DrawLabel(view, truncatedLabel.String(), base, flags, location, textColor); 2398 2399 view->PopState(); 2400 } 2401 2402 2403 void 2404 BeControlLook::GetFrameInsets(frame_type frameType, uint32 flags, float& _left, 2405 float& _top, float& _right, float& _bottom) 2406 { 2407 // All frames have the same inset on each side. 2408 float inset = 0; 2409 2410 switch (frameType) { 2411 case B_BUTTON_FRAME: 2412 inset = (flags & B_DEFAULT_BUTTON) != 0 ? 5 : 2; 2413 break; 2414 2415 case B_GROUP_FRAME: 2416 case B_MENU_FIELD_FRAME: 2417 inset = 3; 2418 break; 2419 2420 case B_SCROLL_VIEW_FRAME: 2421 case B_TEXT_CONTROL_FRAME: 2422 inset = 2; 2423 break; 2424 } 2425 2426 _left = inset; 2427 _top = inset; 2428 _right = inset; 2429 _bottom = inset; 2430 } 2431 2432 2433 void 2434 BeControlLook::GetBackgroundInsets(background_type backgroundType, 2435 uint32 flags, float& _left, float& _top, float& _right, float& _bottom) 2436 { 2437 // Most backgrounds have the same inset on each side. 2438 float inset = 0; 2439 2440 switch (backgroundType) { 2441 case B_BUTTON_BACKGROUND: 2442 case B_MENU_BACKGROUND: 2443 case B_MENU_BAR_BACKGROUND: 2444 case B_MENU_FIELD_BACKGROUND: 2445 case B_MENU_ITEM_BACKGROUND: 2446 inset = 1; 2447 break; 2448 case B_BUTTON_WITH_POP_UP_BACKGROUND: 2449 _left = 1; 2450 _top = 1; 2451 _right = 1 + kButtonPopUpIndicatorWidth; 2452 _bottom = 1; 2453 return; 2454 case B_HORIZONTAL_SCROLL_BAR_BACKGROUND: 2455 _left = 2; 2456 _top = 0; 2457 _right = 1; 2458 _bottom = 0; 2459 return; 2460 case B_VERTICAL_SCROLL_BAR_BACKGROUND: 2461 _left = 0; 2462 _top = 2; 2463 _right = 0; 2464 _bottom = 1; 2465 return; 2466 } 2467 2468 _left = inset; 2469 _top = inset; 2470 _right = inset; 2471 _bottom = inset; 2472 } 2473 2474 2475 void 2476 BeControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect, 2477 const BRect& updateRect, const rgb_color& base, uint32 flags, 2478 uint32 borders, orientation orientation) 2479 { 2480 _DrawButtonBackground(view, rect, updateRect, 0.0f, 0.0f, 0.0f, 0.0f, 2481 base, true, flags, borders, orientation); 2482 } 2483 2484 2485 void 2486 BeControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect, 2487 const BRect& updateRect, float radius, const rgb_color& base, uint32 flags, 2488 uint32 borders, orientation orientation) 2489 { 2490 _DrawButtonBackground(view, rect, updateRect, radius, radius, radius, 2491 radius, base, true, flags, borders, orientation); 2492 } 2493 2494 2495 void 2496 BeControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect, 2497 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 2498 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 2499 uint32 flags, uint32 borders, orientation orientation) 2500 { 2501 _DrawButtonBackground(view, rect, updateRect, leftTopRadius, 2502 rightTopRadius, leftBottomRadius, rightBottomRadius, base, true, flags, 2503 borders, orientation); 2504 } 2505 2506 2507 // #pragma mark - protected methods 2508 2509 2510 void 2511 BeControlLook::_DrawButtonFrame(BView* view, BRect& rect, 2512 const BRect& updateRect, float, float, float, float, const rgb_color& base, 2513 const rgb_color& background, float contrast, float brightness, 2514 uint32 flags, uint32 borders) 2515 { 2516 if (!ShouldDraw(view, rect, updateRect)) 2517 return; 2518 2519 view->PushState(); 2520 2521 view->ClipToRect(rect); 2522 2523 // flags 2524 bool isEnabled = (flags & B_DISABLED) == 0; 2525 bool isDefault = (flags & B_DEFAULT_BUTTON) != 0; 2526 2527 // colors 2528 rgb_color lighten1 = tint_color(base, B_LIGHTEN_1_TINT); // 231 2529 lighten1.red++; lighten1.green++; lighten1.blue++; // 232 = 231 + 1 2530 rgb_color lighten2 = tint_color(base, B_LIGHTEN_2_TINT); 2531 rgb_color lightenMax = tint_color(base, B_LIGHTEN_MAX_TINT); 2532 rgb_color darken1 = tint_color(base, B_DARKEN_1_TINT); // 184 2533 rgb_color darken2 = tint_color(base, B_DARKEN_2_TINT); // 158 2534 rgb_color darken3 = tint_color(base, B_DARKEN_3_TINT); 2535 rgb_color darken4 = tint_color(base, B_DARKEN_4_TINT); // 96 2536 2537 rgb_color buttonBgColor = lighten1; 2538 rgb_color lightColor; 2539 2540 rgb_color dark1BorderColor; 2541 rgb_color dark2BorderColor; 2542 2543 rgb_color bevelColor1; 2544 rgb_color bevelColor2; 2545 rgb_color bevelColorRBCorner; 2546 2547 rgb_color borderBevelShadow; 2548 rgb_color borderBevelLight; 2549 2550 if (isEnabled) { 2551 lightColor = tint_color(base, B_LIGHTEN_2_TINT); 2552 dark1BorderColor = darken3; 2553 dark2BorderColor = darken4; 2554 bevelColor1 = darken2; 2555 bevelColor2 = lighten1; 2556 2557 if (isDefault) { 2558 borderBevelShadow = tint_color(dark1BorderColor, 2559 (B_NO_TINT + B_DARKEN_1_TINT) / 2); 2560 borderBevelLight = tint_color(dark1BorderColor, B_LIGHTEN_1_TINT); 2561 2562 borderBevelLight.red = (borderBevelLight.red + base.red) / 2; 2563 borderBevelLight.green = (borderBevelLight.green + base.green) / 2; 2564 borderBevelLight.blue = (borderBevelLight.blue + base.blue) / 2; 2565 2566 dark1BorderColor = darken3; 2567 dark2BorderColor = darken4; 2568 2569 bevelColorRBCorner = borderBevelShadow; 2570 } else { 2571 borderBevelShadow = tint_color(base, 2572 (B_NO_TINT + B_DARKEN_1_TINT) / 2); 2573 borderBevelLight = buttonBgColor; 2574 bevelColorRBCorner = dark1BorderColor; 2575 } 2576 } else { 2577 lightColor = lighten2; 2578 dark1BorderColor = darken1; 2579 dark2BorderColor = darken2; 2580 bevelColor1 = base; 2581 bevelColor2 = buttonBgColor; 2582 2583 if (isDefault) { 2584 borderBevelShadow = dark1BorderColor; 2585 borderBevelLight = base; 2586 dark1BorderColor = tint_color(dark1BorderColor, B_DARKEN_1_TINT); 2587 dark2BorderColor = tint_color(dark1BorderColor, 1.16); 2588 } else { 2589 borderBevelShadow = base; 2590 borderBevelLight = base; 2591 } 2592 2593 bevelColorRBCorner = tint_color(base, 1.08); 2594 } 2595 2596 if (isDefault) { 2597 if (isEnabled) { 2598 // dark border 2599 view->BeginLineArray(4); 2600 if ((borders & B_LEFT_BORDER) != 0) { 2601 view->AddLine(BPoint(rect.left, rect.top + 1), 2602 BPoint(rect.left, rect.bottom - 1), dark2BorderColor); 2603 rect.left++; 2604 } 2605 if ((borders & B_TOP_BORDER) != 0) { 2606 view->AddLine(BPoint(rect.left, rect.top), 2607 BPoint(rect.right - 1, rect.top), dark2BorderColor); 2608 rect.top++; 2609 } 2610 if ((borders & B_RIGHT_BORDER) != 0) { 2611 view->AddLine(BPoint(rect.right, rect.top), 2612 BPoint(rect.right, rect.bottom - 1), dark2BorderColor); 2613 rect.right--; 2614 } 2615 if ((borders & B_BOTTOM_BORDER) != 0) { 2616 view->AddLine(BPoint(rect.left, rect.bottom), 2617 BPoint(rect.right, rect.bottom), dark2BorderColor); 2618 rect.bottom--; 2619 } 2620 view->EndLineArray(); 2621 2622 // bevel 2623 view->SetHighColor(darken1); 2624 view->StrokeRect(rect); 2625 2626 rect.InsetBy(1, 1); 2627 2628 // fill 2629 view->SetHighColor(lighten1); 2630 view->FillRect(rect); 2631 2632 rect.InsetBy(2, 2); 2633 } else { 2634 // dark border 2635 view->BeginLineArray(4); 2636 if ((borders & B_LEFT_BORDER) != 0) { 2637 view->AddLine(BPoint(rect.left, rect.top + 1), 2638 BPoint(rect.left, rect.bottom - 1), darken1); 2639 rect.left++; 2640 } 2641 if ((borders & B_TOP_BORDER) != 0) { 2642 view->AddLine(BPoint(rect.left, rect.top), 2643 BPoint(rect.right - 1, rect.top), darken1); 2644 rect.top++; 2645 } 2646 if ((borders & B_RIGHT_BORDER) != 0) { 2647 view->AddLine(BPoint(rect.right, rect.top), 2648 BPoint(rect.right, rect.bottom - 1), darken1); 2649 rect.right--; 2650 } 2651 if ((borders & B_BOTTOM_BORDER) != 0) { 2652 view->AddLine(BPoint(rect.left, rect.bottom), 2653 BPoint(rect.right, rect.bottom), darken1); 2654 rect.bottom--; 2655 } 2656 view->EndLineArray(); 2657 2658 // fill 2659 view->SetHighColor(lighten1); 2660 view->FillRect(rect); 2661 2662 rect.InsetBy(3, 3); 2663 } 2664 } else { 2665 // if not default button, inset top and bottom by 1px 2666 rect.InsetBy(1, 0); 2667 } 2668 2669 // stroke frame to draw four corners, then write on top 2670 view->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 2671 view->StrokeRect(rect); 2672 2673 view->BeginLineArray(16); 2674 2675 // external border 2676 view->AddLine(BPoint(rect.left, rect.top + 1), 2677 BPoint(rect.left, rect.bottom - 1), 2678 (borders & B_LEFT_BORDER) != 0 ? dark2BorderColor : darken1); 2679 view->AddLine(BPoint(rect.left + 1, rect.top), 2680 BPoint(rect.right - 1, rect.top), 2681 (borders & B_TOP_BORDER) != 0 ? dark2BorderColor : darken1); 2682 view->AddLine(BPoint(rect.right, rect.top + 1), 2683 BPoint(rect.right, rect.bottom - 1), 2684 (borders & B_RIGHT_BORDER) != 0 ? dark2BorderColor : darken1); 2685 view->AddLine(BPoint(rect.left + 1, rect.bottom), 2686 BPoint(rect.right - 1, rect.bottom), 2687 (borders & B_BOTTOM_BORDER) != 0 ? dark2BorderColor : darken1); 2688 2689 // inset past external border 2690 rect.InsetBy(1, 1); 2691 2692 // internal bevel 2693 view->AddLine(rect.LeftBottom(), rect.LeftTop(), bevelColor2); 2694 view->AddLine(rect.LeftTop(), rect.RightTop(), bevelColor2); 2695 view->AddLine(BPoint(rect.right, rect.top + 1), rect.RightBottom(), 2696 bevelColor1); 2697 view->AddLine(rect.RightBottom(), BPoint(rect.left + 1, rect.bottom), 2698 bevelColor1); 2699 2700 // inset past internal bevel 2701 rect.InsetBy(1, 1); 2702 2703 // internal gloss outside 2704 view->AddLine(BPoint(rect.left, rect.bottom + 1), rect.LeftTop(), 2705 lightenMax); // come down an extra pixel 2706 view->AddLine(rect.LeftTop(), rect.RightTop(), lightenMax); 2707 view->AddLine(rect.RightTop(), rect.RightBottom(), base); 2708 view->AddLine(rect.RightBottom(), BPoint(rect.left + 1, rect.bottom), 2709 base); // compensate for extra pixel 2710 2711 // inset past gloss outside 2712 rect.InsetBy(1, 1); 2713 2714 // internal gloss inside 2715 view->AddLine(BPoint(rect.left, rect.bottom + 1), rect.LeftTop(), 2716 lightenMax); // come down an extra pixel 2717 view->AddLine(rect.LeftTop(), rect.RightTop(), lightenMax); 2718 view->AddLine(rect.RightTop(), rect.RightBottom(), buttonBgColor); 2719 view->AddLine(rect.RightBottom(), BPoint(rect.left + 1, rect.bottom), 2720 buttonBgColor); // compensate for extra pixel 2721 2722 // inset past gloss inside 2723 rect.InsetBy(1, 1); 2724 2725 view->EndLineArray(); 2726 2727 view->PopState(); 2728 } 2729 2730 2731 void 2732 BeControlLook::_DrawButtonBackground(BView* view, BRect& rect, 2733 const BRect& updateRect, float, float, float, float, const rgb_color& base, 2734 bool popupIndicator, uint32 flags, uint32 borders, orientation orientation) 2735 { 2736 if (!ShouldDraw(view, rect, updateRect)) 2737 return; 2738 2739 // fill the button area 2740 view->SetHighColor(tint_color(base, B_LIGHTEN_1_TINT)); 2741 view->FillRect(rect); 2742 2743 bool isEnabled = (flags & B_DISABLED) == 0; 2744 bool isActivated = (flags & B_ACTIVATED) != 0; 2745 2746 if (isEnabled && isActivated) { 2747 // invert if clicked without altering rect 2748 BRect invertRect(rect.InsetByCopy(-3, -3)); 2749 view->SetDrawingMode(B_OP_INVERT); 2750 view->FillRect(invertRect); 2751 } 2752 } 2753 2754 2755 void 2756 BeControlLook::_DrawPopUpMarker(BView* view, const BRect& rect, 2757 const rgb_color& base, uint32 flags) 2758 { 2759 bool isEnabled = (flags & B_DISABLED) == 0; 2760 2761 BPoint position(rect.right - 8, rect.bottom - 8); 2762 BPoint triangle[3]; 2763 triangle[0] = position + BPoint(-2.5, -0.5); 2764 triangle[1] = position + BPoint(2.5, -0.5); 2765 triangle[2] = position + BPoint(0.0, 2.0); 2766 2767 uint32 viewFlags = view->Flags(); 2768 view->SetFlags(viewFlags | B_SUBPIXEL_PRECISE); 2769 2770 rgb_color markerColor = isEnabled 2771 ? tint_color(base, B_DARKEN_4_TINT) 2772 : tint_color(base, B_DARKEN_2_TINT); 2773 2774 view->SetHighColor(markerColor); 2775 view->FillTriangle(triangle[0], triangle[1], triangle[2]); 2776 2777 view->SetFlags(viewFlags); 2778 } 2779 2780 2781 void 2782 BeControlLook::_DrawMenuFieldBackgroundOutside(BView* view, BRect& rect, 2783 const BRect& updateRect, float, float, float, float, const rgb_color& base, 2784 bool popupIndicator, uint32 flags) 2785 { 2786 if (!ShouldDraw(view, rect, updateRect)) 2787 return; 2788 2789 // BeControlLook does not support rounded corners and it never will 2790 if (popupIndicator) { 2791 BRect rightRect(rect); 2792 rightRect.left = rect.right - 10; 2793 2794 _DrawMenuFieldBackgroundInside(view, rect, updateRect, 2795 0, 0, 0, 0, base, flags, B_ALL_BORDERS); 2796 _DrawPopUpMarker(view, rightRect, base, flags); 2797 } else { 2798 _DrawMenuFieldBackgroundInside(view, rect, updateRect, 0, 0, 2799 0, 0, base, flags); 2800 } 2801 } 2802 2803 2804 void 2805 BeControlLook::_DrawMenuFieldBackgroundInside(BView* view, BRect& rect, 2806 const BRect& updateRect, float, float, float, float, const rgb_color& base, 2807 uint32 flags, uint32 borders) 2808 { 2809 if (!ShouldDraw(view, rect, updateRect)) 2810 return; 2811 2812 view->PushState(); 2813 2814 view->ClipToRect(rect); 2815 2816 // flags 2817 bool isEnabled = (flags & B_DISABLED) == 0; 2818 2819 // colors 2820 rgb_color darken4; 2821 rgb_color darken1; 2822 rgb_color lighten1; 2823 rgb_color lighten2; 2824 2825 if (isEnabled) { 2826 darken4 = tint_color(base, B_DARKEN_4_TINT); 2827 darken1 = tint_color(base, B_DARKEN_1_TINT); 2828 lighten1 = tint_color(base, B_LIGHTEN_1_TINT); 2829 lighten2 = tint_color(base, B_LIGHTEN_2_TINT); 2830 } else { 2831 darken4 = tint_color(base, B_DARKEN_2_TINT); 2832 darken1 = tint_color(base, (B_NO_TINT + B_DARKEN_1_TINT) / 2.0); 2833 lighten1 = tint_color(base, (B_NO_TINT + B_LIGHTEN_1_TINT) / 2.0); 2834 lighten2 = tint_color(base, B_LIGHTEN_1_TINT); 2835 } 2836 2837 // fill background 2838 view->SetHighColor(base); 2839 view->FillRect(rect); 2840 2841 // draw shadow lines around bottom and right sides 2842 view->BeginLineArray(6); 2843 2844 // bottom below item text, darker then BMenuBar 2845 // would normaly draw it 2846 view->AddLine(BPoint(rect.left, rect.bottom), 2847 BPoint(rect.left - 1, rect.bottom), darken4); 2848 2849 // bottom below popup marker 2850 view->AddLine(BPoint(rect.left, rect.bottom), 2851 BPoint(rect.right, rect.bottom), darken4); 2852 // right of popup marker 2853 view->AddLine(BPoint(rect.right, rect.bottom - 1), 2854 BPoint(rect.right, rect.top), darken4); 2855 // top above popup marker 2856 view->AddLine(BPoint(rect.left, rect.top), 2857 BPoint(rect.right - 2, rect.top), lighten2); 2858 2859 rect.top += 1; 2860 rect.bottom -= 1; 2861 rect.right -= 1; 2862 2863 // bottom below popup marker 2864 view->AddLine(BPoint(rect.left, rect.bottom), 2865 BPoint(rect.right, rect.bottom), darken1); 2866 // right of popup marker 2867 view->AddLine(BPoint(rect.right, rect.bottom - 1), 2868 BPoint(rect.right, rect.top), darken1); 2869 2870 view->EndLineArray(); 2871 2872 rect.bottom -= 1; 2873 rect.right -= 1; 2874 view->SetHighColor(base); 2875 view->FillRect(rect); 2876 2877 view->PopState(); 2878 } 2879 2880 2881 void 2882 BeControlLook::_DrawScrollBarBackgroundFirst(BView* view, BRect& rect, 2883 const BRect& updateRect, const rgb_color& base, uint32 flags, 2884 orientation orientation) 2885 { 2886 if (!ShouldDraw(view, rect, updateRect)) 2887 return; 2888 2889 view->PushState(); 2890 2891 view->ClipToRect(rect); 2892 2893 bool isEnabled = (flags & B_DISABLED) == 0; 2894 BRect orig(rect); 2895 2896 // border = 152 2897 rgb_color border = tint_color(base, B_DARKEN_2_TINT); 2898 rgb_color shine, shadow, bg; 2899 if (isEnabled) { 2900 // shine = 216, shadow = 184, bg = 200 2901 shine = base; 2902 shadow = tint_color(base, B_DARKEN_1_TINT); 2903 bg = tint_color(base, 1.074); 2904 } else { 2905 // shine = 255, shadow = bg = 240 2906 shine = tint_color(base, B_LIGHTEN_MAX_TINT); 2907 rgb_color lighten2 = tint_color(base, B_LIGHTEN_2_TINT); 2908 lighten2.red++; lighten2.green++; lighten2.blue++; 2909 // lighten2 = 239, 240 = 239 + 1 2910 shadow = bg = lighten2; 2911 } 2912 2913 // fill background, we'll draw arrows and thumb on top 2914 view->SetDrawingMode(B_OP_COPY); 2915 2916 view->BeginLineArray(5); 2917 if (orientation == B_VERTICAL) { 2918 // left shadow 2919 view->AddLine(rect.LeftTop(), rect.LeftBottom(), 2920 isEnabled ? shadow : shine); 2921 rect.left++; 2922 view->AddLine(rect.LeftTop(), rect.LeftBottom(), shadow); 2923 rect.left++; 2924 // top shadow 2925 view->AddLine(rect.LeftTop(), rect.RightTop(), 2926 isEnabled ? shadow : shine); 2927 rect.top++; 2928 view->AddLine(rect.LeftTop(), rect.RightTop(), shadow); 2929 rect.top++; 2930 // shine 2931 view->AddLine(rect.RightTop(), rect.RightBottom(), base); 2932 rect.right--; 2933 } else { 2934 // left shadow 2935 view->AddLine(rect.LeftTop(), rect.LeftBottom(), shadow); 2936 rect.left++; 2937 view->AddLine(rect.LeftTop(), rect.LeftBottom(), shadow); 2938 rect.left++; 2939 // top shadow 2940 view->AddLine(rect.LeftTop(), rect.RightTop(), shadow); 2941 rect.top++; 2942 view->AddLine(rect.LeftTop(), rect.RightTop(), shadow); 2943 rect.top++; 2944 // shine 2945 view->AddLine(rect.LeftBottom(), rect.RightBottom(), base); 2946 rect.bottom--; 2947 } 2948 view->EndLineArray(); 2949 2950 // fill bg 2951 view->SetHighColor(bg); 2952 view->FillRect(rect); 2953 2954 rect = orig; 2955 2956 // draw border last 2957 view->BeginLineArray(2); 2958 if (orientation == B_VERTICAL) { 2959 // top border 2960 view->AddLine(rect.LeftTop(), rect.RightTop(), border); 2961 // bottom border 2962 view->AddLine(rect.LeftBottom(), rect.RightBottom(), border); 2963 } else { 2964 // left border 2965 view->AddLine(rect.LeftTop(), rect.LeftBottom(), border); 2966 // right border 2967 view->AddLine(rect.RightTop(), rect.RightBottom(), border); 2968 } 2969 view->EndLineArray(); 2970 2971 view->PopState(); 2972 } 2973 2974 2975 void 2976 BeControlLook::_DrawScrollBarBackgroundSecond(BView* view, BRect& rect, 2977 const BRect& updateRect, const rgb_color& base, uint32 flags, 2978 orientation orientation) 2979 { 2980 if (!ShouldDraw(view, rect, updateRect)) 2981 return; 2982 2983 view->PushState(); 2984 2985 view->ClipToRect(rect); 2986 2987 bool isEnabled = (flags & B_DISABLED) == 0; 2988 2989 BRect orig(rect); 2990 2991 // border = 152 2992 rgb_color border = tint_color(base, B_DARKEN_2_TINT); 2993 rgb_color darkBorder, shine, shadow, bg; 2994 if (isEnabled) { 2995 // darkBorder = 96 shine = 216, shadow = 184, bg = 200 2996 darkBorder = tint_color(base, B_DARKEN_4_TINT); 2997 shine = base; 2998 shadow = tint_color(base, B_DARKEN_1_TINT); 2999 bg = tint_color(base, 1.074); 3000 } else { 3001 // darkBorder = 184, shine = 255, shadow = bg = 240 3002 darkBorder = tint_color(base, B_DARKEN_1_TINT); 3003 shine = tint_color(base, B_LIGHTEN_MAX_TINT); 3004 rgb_color lighten2 = tint_color(base, B_LIGHTEN_2_TINT); 3005 lighten2.red++; lighten2.green++; lighten2.blue++; 3006 // lighten2 = 239, 240 = 239 + 1 3007 shadow = bg = lighten2; 3008 } 3009 3010 // fill background, we'll draw arrows and thumb on top 3011 view->SetDrawingMode(B_OP_COPY); 3012 3013 view->BeginLineArray(3); 3014 if (orientation == B_VERTICAL) { 3015 // left shadow (no top shadow on second rect) 3016 view->AddLine(rect.LeftTop(), rect.LeftBottom(), 3017 isEnabled ? shadow : shine); 3018 rect.left++; 3019 view->AddLine(rect.LeftTop(), rect.LeftBottom(), shadow); 3020 rect.left++; 3021 // shine (use base color) 3022 view->AddLine(rect.RightTop(), rect.RightBottom(), base); 3023 rect.right--; 3024 } else { 3025 // left shadow (no top shadow on second rect) 3026 view->AddLine(rect.LeftTop(), rect.RightTop(), 3027 isEnabled ? shadow : shine); 3028 rect.top++; 3029 view->AddLine(rect.LeftTop(), rect.RightTop(), shadow); 3030 rect.top++; 3031 // shine (use base color) 3032 view->AddLine(rect.LeftBottom(), rect.RightBottom(), base); 3033 rect.bottom--; 3034 } 3035 view->EndLineArray(); 3036 3037 // fill bg 3038 view->SetHighColor(bg); 3039 view->FillRect(rect); 3040 3041 rect = orig; 3042 3043 // draw border over bg 3044 view->BeginLineArray(2); 3045 if (orientation == B_VERTICAL) { 3046 // top border 3047 view->AddLine(rect.LeftTop(), rect.RightTop(), darkBorder); 3048 // bottom border 3049 view->AddLine(rect.LeftBottom(), rect.RightBottom(), border); 3050 } else { 3051 // left border 3052 view->AddLine(rect.LeftTop(), rect.LeftBottom(), darkBorder); 3053 // right border 3054 view->AddLine(rect.RightTop(), rect.RightBottom(), border); 3055 } 3056 view->EndLineArray(); 3057 3058 view->PopState(); 3059 } 3060 3061 void 3062 BeControlLook::_DrawScrollBarKnobDot(BView* view, 3063 float hcenter, float vmiddle, rgb_color dark, rgb_color light, 3064 orientation orientation) 3065 { 3066 // orientation is unused 3067 view->BeginLineArray(4); 3068 view->AddLine(BPoint(hcenter + 2, vmiddle - 2), 3069 BPoint(hcenter + 2, vmiddle + 2), dark); 3070 view->AddLine(BPoint(hcenter + 2, vmiddle + 2), 3071 BPoint(hcenter - 2, vmiddle + 2), dark); 3072 view->AddLine(BPoint(hcenter - 2, vmiddle + 1), 3073 BPoint(hcenter - 2, vmiddle - 1), light); 3074 view->AddLine(BPoint(hcenter - 2, vmiddle - 1), 3075 BPoint(hcenter - 2, vmiddle + 1), light); 3076 view->EndLineArray(); 3077 } 3078 3079 3080 void 3081 BeControlLook::_DrawScrollBarKnobLine(BView* view, 3082 float hcenter, float vmiddle, rgb_color dark, rgb_color light, 3083 orientation orientation) 3084 { 3085 if (orientation == B_HORIZONTAL) { 3086 view->BeginLineArray(4); 3087 view->AddLine(BPoint(hcenter, vmiddle + 3), 3088 BPoint(hcenter + 1, vmiddle + 3), dark); 3089 view->AddLine(BPoint(hcenter + 1, vmiddle + 3), 3090 BPoint(hcenter + 1, vmiddle - 3), dark); 3091 view->AddLine(BPoint(hcenter, vmiddle - 3), 3092 BPoint(hcenter - 1, vmiddle - 3), light); 3093 view->AddLine(BPoint(hcenter - 1, vmiddle - 3), 3094 BPoint(hcenter - 1, vmiddle + 3), light); 3095 view->EndLineArray(); 3096 } else { 3097 view->BeginLineArray(4); 3098 view->AddLine(BPoint(hcenter + 3, vmiddle), 3099 BPoint(hcenter + 3, vmiddle + 1), dark); 3100 view->AddLine(BPoint(hcenter + 3, vmiddle + 1), 3101 BPoint(hcenter - 3, vmiddle + 1), dark); 3102 view->AddLine(BPoint(hcenter - 3, vmiddle), 3103 BPoint(hcenter - 3, vmiddle - 1), light); 3104 view->AddLine(BPoint(hcenter - 3, vmiddle - 1), 3105 BPoint(hcenter + 3, vmiddle - 1), light); 3106 view->EndLineArray(); 3107 } 3108 } 3109 3110 3111 void 3112 BeControlLook::_DrawFrame(BView* view, BRect& rect, const rgb_color& left, 3113 const rgb_color& top, const rgb_color& right, const rgb_color& bottom, 3114 uint32 borders) 3115 { 3116 view->BeginLineArray(4); 3117 3118 // draw in reverse so that bottom and right corners cover top and left 3119 3120 if ((borders & B_BOTTOM_BORDER) != 0) { 3121 view->AddLine( 3122 BPoint(rect.left, rect.bottom), 3123 BPoint(rect.right, rect.bottom), bottom); 3124 rect.bottom--; 3125 } 3126 if ((borders & B_RIGHT_BORDER) != 0) { 3127 view->AddLine( 3128 BPoint(rect.right, rect.top), 3129 BPoint(rect.right, rect.bottom), right); 3130 rect.right--; 3131 } 3132 if ((borders & B_TOP_BORDER) != 0) { 3133 view->AddLine( 3134 BPoint(rect.left, rect.top), 3135 BPoint(rect.right, rect.top), top); 3136 rect.top++; 3137 } 3138 if ((borders & B_LEFT_BORDER) != 0) { 3139 view->AddLine( 3140 BPoint(rect.left, rect.bottom), 3141 BPoint(rect.left, rect.top), left); 3142 rect.left++; 3143 } 3144 3145 view->EndLineArray(); 3146 } 3147 3148 } // namespace BPrivate 3149 3150 3151 extern "C" BControlLook* (instantiate_control_look)(image_id id) 3152 { 3153 return new (std::nothrow)BPrivate::BeControlLook(id); 3154 } 3155