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