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