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