xref: /haiku/src/kits/interface/ControlLook.cpp (revision 4fd62caa9acc437534c41bbb7d3fc9d53e915005)
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, enum 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, enum 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, enum 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 	enum 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 	enum 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, rect.bottom + 1);
748 			tri2.Set(rect.left + rect.Width() / 1.33,
749 				(rect.top + rect.bottom + 1) / 2);
750 			tri3.Set(rect.left, 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);
761 			tri2.Set((rect.left + rect.right + 1) / 2,
762 				rect.top + rect.Height() / 1.33);
763 			tri3.Set(rect.right + 1, rect.top);
764 			break;
765 	}
766 	// offset triangle if down
767 	if ((flags & B_ACTIVATED) != 0)
768 		view->MovePenTo(BPoint(1, 1));
769 	else
770 		view->MovePenTo(BPoint(0, 0));
771 
772 	BShape arrowShape;
773 	arrowShape.MoveTo(tri1);
774 	arrowShape.LineTo(tri2);
775 	arrowShape.LineTo(tri3);
776 
777 	if ((flags & B_DISABLED) != 0)
778 		tint = (tint + B_NO_TINT + B_NO_TINT) / 3;
779 
780 	view->SetHighColor(tint_color(base, tint));
781 
782 	float penSize = view->PenSize();
783 	drawing_mode mode = view->DrawingMode();
784 
785 	view->SetPenSize(ceilf(hInset / 2.0));
786 	view->SetDrawingMode(B_OP_OVER);
787 	view->StrokeShape(&arrowShape);
788 
789 	view->SetPenSize(penSize);
790 	view->SetDrawingMode(mode);
791 }
792 
793 
794 rgb_color
795 BControlLook::SliderBarColor(const rgb_color& base)
796 {
797 	return tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_1_TINT);
798 }
799 
800 
801 void
802 BControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect,
803 	const rgb_color& base, rgb_color leftFillColor, rgb_color rightFillColor,
804 	float sliderScale, uint32 flags, enum orientation orientation)
805 {
806 	if (!rect.IsValid() || !rect.Intersects(updateRect))
807 		return;
808 
809 	// separate the bar in two sides
810 	float sliderPosition;
811 	BRect leftBarSide = rect;
812 	BRect rightBarSide = rect;
813 
814 	if (orientation == B_HORIZONTAL) {
815 		sliderPosition = floorf(rect.left + 2 + (rect.Width() - 2)
816 			* sliderScale);
817 		leftBarSide.right = sliderPosition - 1;
818 		rightBarSide.left = sliderPosition;
819 	} else {
820 		// NOTE: position is reverse of coords
821 		sliderPosition = floorf(rect.top + 2 + (rect.Height() - 2)
822 			* (1.0 - sliderScale));
823 		leftBarSide.top = sliderPosition;
824 		rightBarSide.bottom = sliderPosition - 1;
825 	}
826 
827 	// fill the background for the corners, exclude the middle bar for now
828 	BRegion region(rect);
829 	region.Exclude(rightBarSide);
830 	view->ConstrainClippingRegion(&region);
831 
832 	view->PushState();
833 
834 	DrawSliderBar(view, rect, updateRect, base, leftFillColor, flags,
835 		orientation);
836 
837 	view->PopState();
838 
839 	region.Set(rect);
840 	region.Exclude(leftBarSide);
841 	view->ConstrainClippingRegion(&region);
842 
843 	view->PushState();
844 
845 	DrawSliderBar(view, rect, updateRect, base, rightFillColor, flags,
846 		orientation);
847 
848 	view->PopState();
849 
850 	// reset clipping constraints
851 	view->ConstrainClippingRegion(NULL);
852 }
853 
854 
855 void
856 BControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect,
857 	const rgb_color& base, rgb_color fillColor, uint32 flags,
858 	enum orientation orientation)
859 {
860 	if (!rect.IsValid() || !rect.Intersects(updateRect))
861 		return;
862 
863 	// separate the rect into corners
864 	BRect leftCorner(rect);
865 	BRect rightCorner(rect);
866 	BRect barRect(rect);
867 
868 	if (orientation == B_HORIZONTAL) {
869 		leftCorner.right = leftCorner.left + leftCorner.Height();
870 		rightCorner.left = rightCorner.right - rightCorner.Height();
871 		barRect.left += ceilf(barRect.Height() / 2);
872 		barRect.right -= ceilf(barRect.Height() / 2);
873 	} else {
874 		leftCorner.bottom = leftCorner.top + leftCorner.Width();
875 		rightCorner.top = rightCorner.bottom - rightCorner.Width();
876 		barRect.top += ceilf(barRect.Width() / 2);
877 		barRect.bottom -= ceilf(barRect.Width() / 2);
878 	}
879 
880 	// fill the background for the corners, exclude the middle bar for now
881 	BRegion region(rect);
882 	region.Exclude(barRect);
883 	view->ConstrainClippingRegion(&region);
884 
885 	if ((flags & B_BLEND_FRAME) == 0) {
886 		view->SetHighColor(base);
887 		view->FillRect(rect);
888 	}
889 
890 	// figure out the tints to be used
891 	float edgeLightTint;
892 	float edgeShadowTint;
893 	float frameLightTint;
894 	float frameShadowTint;
895 	float fillLightTint;
896 	float fillShadowTint;
897 	uint8 edgeLightAlpha;
898 	uint8 edgeShadowAlpha;
899 	uint8 frameLightAlpha;
900 	uint8 frameShadowAlpha;
901 
902 	if ((flags & B_DISABLED) != 0) {
903 		edgeLightTint = 1.0;
904 		edgeShadowTint = 1.0;
905 		frameLightTint = 1.20;
906 		frameShadowTint = 1.25;
907 		fillLightTint = 0.9;
908 		fillShadowTint = 1.05;
909 		edgeLightAlpha = 12;
910 		edgeShadowAlpha = 12;
911 		frameLightAlpha = 40;
912 		frameShadowAlpha = 45;
913 
914 		fillColor.red = uint8(fillColor.red * 0.4 + base.red * 0.6);
915 		fillColor.green = uint8(fillColor.green * 0.4 + base.green * 0.6);
916 		fillColor.blue = uint8(fillColor.blue * 0.4 + base.blue * 0.6);
917 	} else {
918 		edgeLightTint = 0.65;
919 		edgeShadowTint = 1.07;
920 		frameLightTint = 1.40;
921 		frameShadowTint = 1.50;
922 		fillLightTint = 0.8;
923 		fillShadowTint = 1.1;
924 		edgeLightAlpha = 15;
925 		edgeShadowAlpha = 15;
926 		frameLightAlpha = 92;
927 		frameShadowAlpha = 107;
928 	}
929 
930 	rgb_color edgeLightColor;
931 	rgb_color edgeShadowColor;
932 	rgb_color frameLightColor;
933 	rgb_color frameShadowColor;
934 	rgb_color fillLightColor = tint_color(fillColor, fillLightTint);
935 	rgb_color fillShadowColor = tint_color(fillColor, fillShadowTint);
936 
937 	drawing_mode oldMode = view->DrawingMode();
938 
939 	if ((flags & B_BLEND_FRAME) != 0) {
940 		edgeLightColor = (rgb_color){ 255, 255, 255, edgeLightAlpha };
941 		edgeShadowColor = (rgb_color){ 0, 0, 0, edgeShadowAlpha };
942 		frameLightColor = (rgb_color){ 0, 0, 0, frameLightAlpha };
943 		frameShadowColor = (rgb_color){ 0, 0, 0, frameShadowAlpha };
944 
945 		view->SetDrawingMode(B_OP_ALPHA);
946 	} else {
947 		edgeLightColor = tint_color(base, edgeLightTint);
948 		edgeShadowColor = tint_color(base, edgeShadowTint);
949 		frameLightColor = tint_color(fillColor, frameLightTint);
950 		frameShadowColor = tint_color(fillColor, frameShadowTint);
951 	}
952 
953 	if (orientation == B_HORIZONTAL) {
954 		_DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor,
955 			edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
956 			fillShadowColor, 1.0, 1.0, 0.0, -1.0, orientation);
957 
958 		_DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor,
959 			edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
960 			fillShadowColor, 0.0, 1.0, -1.0, -1.0, orientation);
961 	} else {
962 		_DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor,
963 			edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
964 			fillShadowColor, 1.0, 1.0, -1.0, 0.0, orientation);
965 
966 		_DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor,
967 			edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
968 			fillShadowColor, 1.0, 0.0, -1.0, -1.0, orientation);
969 	}
970 
971 	view->ConstrainClippingRegion(NULL);
972 
973 	view->BeginLineArray(4);
974 	if (orientation == B_HORIZONTAL) {
975 		view->AddLine(barRect.LeftTop(), barRect.RightTop(), edgeShadowColor);
976 		view->AddLine(barRect.LeftBottom(), barRect.RightBottom(),
977 			edgeLightColor);
978 		barRect.InsetBy(0, 1);
979 		view->AddLine(barRect.LeftTop(), barRect.RightTop(), frameShadowColor);
980 		view->AddLine(barRect.LeftBottom(), barRect.RightBottom(),
981 			frameLightColor);
982 		barRect.InsetBy(0, 1);
983 	} else {
984 		view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), edgeShadowColor);
985 		view->AddLine(barRect.RightTop(), barRect.RightBottom(),
986 			edgeLightColor);
987 		barRect.InsetBy(1, 0);
988 		view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), frameShadowColor);
989 		view->AddLine(barRect.RightTop(), barRect.RightBottom(),
990 			frameLightColor);
991 		barRect.InsetBy(1, 0);
992 	}
993 	view->EndLineArray();
994 
995 	view->SetDrawingMode(oldMode);
996 
997 	_FillGradient(view, barRect, fillColor, fillShadowTint, fillLightTint,
998 		orientation);
999 }
1000 
1001 
1002 void
1003 BControlLook::DrawSliderThumb(BView* view, BRect& rect, const BRect& updateRect,
1004 	const rgb_color& base, uint32 flags, enum orientation orientation)
1005 {
1006 	if (!rect.IsValid() || !rect.Intersects(updateRect))
1007 		return;
1008 
1009 	// figure out frame color
1010 	rgb_color frameLightColor;
1011 	rgb_color frameShadowColor;
1012 	rgb_color shadowColor = (rgb_color){ 0, 0, 0, 60 };
1013 
1014 	if ((flags & B_FOCUSED) != 0) {
1015 		// focused
1016 		frameLightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1017 		frameShadowColor = frameLightColor;
1018 	} else {
1019 		// figure out the tints to be used
1020 		float frameLightTint;
1021 		float frameShadowTint;
1022 
1023 		if ((flags & B_DISABLED) != 0) {
1024 			frameLightTint = 1.30;
1025 			frameShadowTint = 1.35;
1026 			shadowColor.alpha = 30;
1027 		} else {
1028 			frameLightTint = 1.6;
1029 			frameShadowTint = 1.65;
1030 		}
1031 
1032 		frameLightColor = tint_color(base, frameLightTint);
1033 		frameShadowColor = tint_color(base, frameShadowTint);
1034 	}
1035 
1036 	BRect originalRect(rect);
1037 	rect.right--;
1038 	rect.bottom--;
1039 
1040 	_DrawFrame(view, rect, frameLightColor, frameLightColor,
1041 		frameShadowColor, frameShadowColor);
1042 
1043 	flags &= ~B_ACTIVATED;
1044 	DrawButtonBackground(view, rect, updateRect, base, flags);
1045 
1046 	// thumb shadow
1047 	view->SetDrawingMode(B_OP_ALPHA);
1048 	view->SetHighColor(shadowColor);
1049 	originalRect.left++;
1050 	originalRect.top++;
1051 	view->StrokeLine(originalRect.LeftBottom(), originalRect.RightBottom());
1052 	originalRect.bottom--;
1053 	view->StrokeLine(originalRect.RightTop(), originalRect.RightBottom());
1054 
1055 	// thumb edge
1056 	if (orientation == B_HORIZONTAL) {
1057 		rect.InsetBy(0, floorf(rect.Height() / 4));
1058 		rect.left = floorf((rect.left + rect.right) / 2);
1059 		rect.right = rect.left + 1;
1060 		shadowColor = tint_color(base, B_DARKEN_2_TINT);
1061 		shadowColor.alpha = 128;
1062 		view->SetHighColor(shadowColor);
1063 		view->StrokeLine(rect.LeftTop(), rect.LeftBottom());
1064 		rgb_color lightColor = tint_color(base, B_LIGHTEN_2_TINT);
1065 		lightColor.alpha = 128;
1066 		view->SetHighColor(lightColor);
1067 		view->StrokeLine(rect.RightTop(), rect.RightBottom());
1068 	} else {
1069 		rect.InsetBy(floorf(rect.Width() / 4), 0);
1070 		rect.top = floorf((rect.top + rect.bottom) / 2);
1071 		rect.bottom = rect.top + 1;
1072 		shadowColor = tint_color(base, B_DARKEN_2_TINT);
1073 		shadowColor.alpha = 128;
1074 		view->SetHighColor(shadowColor);
1075 		view->StrokeLine(rect.LeftTop(), rect.RightTop());
1076 		rgb_color lightColor = tint_color(base, B_LIGHTEN_2_TINT);
1077 		lightColor.alpha = 128;
1078 		view->SetHighColor(lightColor);
1079 		view->StrokeLine(rect.LeftBottom(), rect.RightBottom());
1080 	}
1081 
1082 	view->SetDrawingMode(B_OP_COPY);
1083 }
1084 
1085 
1086 void
1087 BControlLook::DrawSliderTriangle(BView* view, BRect& rect,
1088 	const BRect& updateRect, const rgb_color& base, uint32 flags,
1089 	enum orientation orientation)
1090 {
1091 	DrawSliderTriangle(view, rect, updateRect, base, base, flags, orientation);
1092 }
1093 
1094 
1095 void
1096 BControlLook::DrawSliderTriangle(BView* view, BRect& rect,
1097 	const BRect& updateRect, const rgb_color& base, const rgb_color& fill,
1098 	uint32 flags, enum orientation orientation)
1099 {
1100 	if (!rect.IsValid() || !rect.Intersects(updateRect))
1101 		return;
1102 
1103 	// figure out frame color
1104 	rgb_color frameLightColor;
1105 	rgb_color frameShadowColor;
1106 	rgb_color shadowColor = (rgb_color){ 0, 0, 0, 60 };
1107 
1108 	float topTint = 0.49;
1109 	float middleTint1 = 0.62;
1110 	float middleTint2 = 0.76;
1111 	float bottomTint = 0.90;
1112 
1113 	if ((flags & B_DISABLED) != 0) {
1114 		topTint = (topTint + B_NO_TINT) / 2;
1115 		middleTint1 = (middleTint1 + B_NO_TINT) / 2;
1116 		middleTint2 = (middleTint2 + B_NO_TINT) / 2;
1117 		bottomTint = (bottomTint + B_NO_TINT) / 2;
1118 	} else if ((flags & B_HOVER) != 0) {
1119 		static const float kHoverTintFactor = 0.85;
1120 		topTint *= kHoverTintFactor;
1121 		middleTint1 *= kHoverTintFactor;
1122 		middleTint2 *= kHoverTintFactor;
1123 		bottomTint *= kHoverTintFactor;
1124 	}
1125 
1126 	if ((flags & B_FOCUSED) != 0) {
1127 		// focused
1128 		frameLightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1129 		frameShadowColor = frameLightColor;
1130 	} else {
1131 		// figure out the tints to be used
1132 		float frameLightTint;
1133 		float frameShadowTint;
1134 
1135 		if ((flags & B_DISABLED) != 0) {
1136 			frameLightTint = 1.30;
1137 			frameShadowTint = 1.35;
1138 			shadowColor.alpha = 30;
1139 		} else {
1140 			frameLightTint = 1.6;
1141 			frameShadowTint = 1.65;
1142 		}
1143 
1144 		frameLightColor = tint_color(base, frameLightTint);
1145 		frameShadowColor = tint_color(base, frameShadowTint);
1146 	}
1147 
1148 	// make room for the shadow
1149 	rect.right--;
1150 	rect.bottom--;
1151 
1152 	uint32 viewFlags = view->Flags();
1153 	view->SetFlags(viewFlags | B_SUBPIXEL_PRECISE);
1154 	view->SetLineMode(B_ROUND_CAP, B_ROUND_JOIN);
1155 
1156 	float centerh = (rect.left + rect.right) / 2;
1157 	float centerv = (rect.top + rect.bottom) / 2;
1158 
1159 	BShape shape;
1160 	if (orientation == B_HORIZONTAL) {
1161 		shape.MoveTo(BPoint(rect.left + 0.5, rect.bottom + 0.5));
1162 		shape.LineTo(BPoint(rect.right + 0.5, rect.bottom + 0.5));
1163 		shape.LineTo(BPoint(rect.right + 0.5, rect.bottom - 1 + 0.5));
1164 		shape.LineTo(BPoint(centerh + 0.5, rect.top + 0.5));
1165 		shape.LineTo(BPoint(rect.left + 0.5, rect.bottom - 1 + 0.5));
1166 	} else {
1167 		shape.MoveTo(BPoint(rect.right + 0.5, rect.top + 0.5));
1168 		shape.LineTo(BPoint(rect.right + 0.5, rect.bottom + 0.5));
1169 		shape.LineTo(BPoint(rect.right - 1 + 0.5, rect.bottom + 0.5));
1170 		shape.LineTo(BPoint(rect.left + 0.5, centerv + 0.5));
1171 		shape.LineTo(BPoint(rect.right - 1 + 0.5, rect.top + 0.5));
1172 	}
1173 	shape.Close();
1174 
1175 	view->MovePenTo(BPoint(1, 1));
1176 
1177 	view->SetDrawingMode(B_OP_ALPHA);
1178 	view->SetHighColor(shadowColor);
1179 	view->StrokeShape(&shape);
1180 
1181 	view->MovePenTo(B_ORIGIN);
1182 
1183 	view->SetDrawingMode(B_OP_COPY);
1184 	view->SetHighColor(frameLightColor);
1185 	view->StrokeShape(&shape);
1186 
1187 	rect.InsetBy(1, 1);
1188 	shape.Clear();
1189 	if (orientation == B_HORIZONTAL) {
1190 		shape.MoveTo(BPoint(rect.left, rect.bottom + 1));
1191 		shape.LineTo(BPoint(rect.right + 1, rect.bottom + 1));
1192 		shape.LineTo(BPoint(centerh + 0.5, rect.top));
1193 	} else {
1194 		shape.MoveTo(BPoint(rect.right + 1, rect.top));
1195 		shape.LineTo(BPoint(rect.right + 1, rect.bottom + 1));
1196 		shape.LineTo(BPoint(rect.left, centerv + 0.5));
1197 	}
1198 	shape.Close();
1199 
1200 	BGradientLinear gradient;
1201 	if ((flags & B_DISABLED) != 0) {
1202 		_MakeGradient(gradient, rect, fill, topTint, bottomTint);
1203 	} else {
1204 		_MakeGlossyGradient(gradient, rect, fill, topTint, middleTint1,
1205 			middleTint2, bottomTint);
1206 	}
1207 
1208 	view->FillShape(&shape, gradient);
1209 
1210 	view->SetFlags(viewFlags);
1211 }
1212 
1213 
1214 void
1215 BControlLook::DrawSliderHashMarks(BView* view, BRect& rect,
1216 	const BRect& updateRect, const rgb_color& base, int32 count,
1217 	hash_mark_location location, uint32 flags, enum orientation orientation)
1218 {
1219 	if (!rect.IsValid() || !rect.Intersects(updateRect))
1220 		return;
1221 
1222 	rgb_color lightColor;
1223 	rgb_color darkColor;
1224 
1225 	if ((flags & B_DISABLED) != 0) {
1226 		lightColor = tint_color(base, 0.9);
1227 		darkColor = tint_color(base, 1.07);
1228 	} else {
1229 		lightColor = tint_color(base, 0.8);
1230 		darkColor = tint_color(base, 1.14);
1231 	}
1232 
1233 	int32 hashMarkCount = max_c(count, 2);
1234 		// draw at least two hashmarks at min/max if
1235 		// fHashMarks != B_HASH_MARKS_NONE
1236 	float factor;
1237 	float startPos;
1238 	if (orientation == B_HORIZONTAL) {
1239 		factor = (rect.Width() - 2) / (hashMarkCount - 1);
1240 		startPos = rect.left + 1;
1241 	} else {
1242 		factor = (rect.Height() - 2) / (hashMarkCount - 1);
1243 		startPos = rect.top + 1;
1244 	}
1245 
1246 	if (location & B_HASH_MARKS_TOP) {
1247 		view->BeginLineArray(hashMarkCount * 2);
1248 
1249 		if (orientation == B_HORIZONTAL) {
1250 			float pos = startPos;
1251 			for (int32 i = 0; i < hashMarkCount; i++) {
1252 				view->AddLine(BPoint(pos, rect.top),
1253 							  BPoint(pos, rect.top + 4), darkColor);
1254 				view->AddLine(BPoint(pos + 1, rect.top),
1255 							  BPoint(pos + 1, rect.top + 4), lightColor);
1256 
1257 				pos += factor;
1258 			}
1259 		} else {
1260 			float pos = startPos;
1261 			for (int32 i = 0; i < hashMarkCount; i++) {
1262 				view->AddLine(BPoint(rect.left, pos),
1263 							  BPoint(rect.left + 4, pos), darkColor);
1264 				view->AddLine(BPoint(rect.left, pos + 1),
1265 							  BPoint(rect.left + 4, pos + 1), lightColor);
1266 
1267 				pos += factor;
1268 			}
1269 		}
1270 
1271 		view->EndLineArray();
1272 	}
1273 
1274 	if (location & B_HASH_MARKS_BOTTOM) {
1275 
1276 		view->BeginLineArray(hashMarkCount * 2);
1277 
1278 		if (orientation == B_HORIZONTAL) {
1279 			float pos = startPos;
1280 			for (int32 i = 0; i < hashMarkCount; i++) {
1281 				view->AddLine(BPoint(pos, rect.bottom - 4),
1282 							  BPoint(pos, rect.bottom), darkColor);
1283 				view->AddLine(BPoint(pos + 1, rect.bottom - 4),
1284 							  BPoint(pos + 1, rect.bottom), lightColor);
1285 
1286 				pos += factor;
1287 			}
1288 		} else {
1289 			float pos = startPos;
1290 			for (int32 i = 0; i < hashMarkCount; i++) {
1291 				view->AddLine(BPoint(rect.right - 4, pos),
1292 							  BPoint(rect.right, pos), darkColor);
1293 				view->AddLine(BPoint(rect.right - 4, pos + 1),
1294 							  BPoint(rect.right, pos + 1), lightColor);
1295 
1296 				pos += factor;
1297 			}
1298 		}
1299 
1300 		view->EndLineArray();
1301 	}
1302 }
1303 
1304 
1305 void
1306 BControlLook::DrawActiveTab(BView* view, BRect& rect, const BRect& updateRect,
1307 	const rgb_color& base, uint32 flags, uint32 borders)
1308 {
1309 	if (!rect.IsValid() || !rect.Intersects(updateRect))
1310 		return;
1311 
1312 	// clipping constraints for the view
1313 	BRegion clipping;
1314 	view->GetClippingRegion(&clipping);
1315 
1316 	// intersect constraints with updateRect
1317 	BRegion updateClipping(updateRect);
1318 	clipping.IntersectWith(&updateClipping);
1319 
1320 	// clip to the intersection
1321 	view->ConstrainClippingRegion(&clipping);
1322 
1323 	rgb_color edgeShadowColor;
1324 	rgb_color edgeLightColor;
1325 	rgb_color frameShadowColor;
1326 	rgb_color frameLightColor;
1327 	rgb_color bevelShadowColor;
1328 	rgb_color bevelLightColor;
1329 	BGradientLinear fillGradient;
1330 	fillGradient.SetStart(rect.LeftTop() + BPoint(3, 3));
1331 	fillGradient.SetEnd(rect.LeftBottom() + BPoint(3, -3));
1332 
1333 	if ((flags & B_DISABLED) != 0) {
1334 		edgeLightColor = base;
1335 		edgeShadowColor = base;
1336 		frameLightColor = tint_color(base, 1.25);
1337 		frameShadowColor = tint_color(base, 1.30);
1338 		bevelLightColor = tint_color(base, 0.8);
1339 		bevelShadowColor = tint_color(base, 1.07);
1340 		fillGradient.AddColor(tint_color(base, 0.85), 0);
1341 		fillGradient.AddColor(base, 255);
1342 	} else {
1343 		edgeLightColor = tint_color(base, 0.80);
1344 		edgeShadowColor = tint_color(base, 1.03);
1345 		frameLightColor = tint_color(base, 1.30);
1346 		frameShadowColor = tint_color(base, 1.30);
1347 		bevelLightColor = tint_color(base, 0.6);
1348 		bevelShadowColor = tint_color(base, 1.07);
1349 		fillGradient.AddColor(tint_color(base, 0.75), 0);
1350 		fillGradient.AddColor(tint_color(base, 1.03), 255);
1351 	}
1352 
1353 	static const float kRoundCornerRadius = 4.0f;
1354 
1355 	// left top corner dimensions
1356 	BRect leftTopCorner(rect);
1357 	leftTopCorner.right = floorf(leftTopCorner.left + kRoundCornerRadius);
1358 	leftTopCorner.bottom = floorf(rect.top + kRoundCornerRadius);
1359 	clipping.Exclude(leftTopCorner);
1360 
1361 	// draw the left top corner
1362 	_DrawRoundCornerLeftTop(view, leftTopCorner, updateRect, base,
1363 		edgeShadowColor, frameLightColor, bevelLightColor,
1364 		fillGradient);
1365 
1366 	// right top corner dimensions
1367 	BRect rightTopCorner(rect);
1368 	rightTopCorner.right = floorf(rect.right);
1369 	rightTopCorner.left = floorf(rightTopCorner.right - kRoundCornerRadius);
1370 	rightTopCorner.bottom = floorf(rect.top + kRoundCornerRadius);
1371 	clipping.Exclude(rightTopCorner);
1372 
1373 	// draw the right top corner
1374 	_DrawRoundCornerRightTop(view, rightTopCorner, updateRect, base,
1375 		edgeShadowColor, edgeLightColor, frameLightColor,
1376 		frameShadowColor, bevelLightColor, bevelShadowColor,
1377 		fillGradient);
1378 
1379 	// clip out the corners
1380 	view->ConstrainClippingRegion(&clipping);
1381 
1382 	// draw the rest of frame and fill
1383 	_DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, edgeLightColor,
1384 		edgeLightColor,
1385 		borders & (B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER));
1386 	if ((borders & B_LEFT_BORDER) == 0)
1387 		rect.left++;
1388 	if ((borders & B_RIGHT_BORDER) == 0)
1389 		rect.right--;
1390 
1391 	_DrawFrame(view, rect, frameLightColor, frameLightColor, frameShadowColor,
1392 		frameShadowColor, B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER);
1393 
1394 	_DrawFrame(view, rect, bevelLightColor, bevelLightColor, bevelShadowColor,
1395 		bevelShadowColor);
1396 
1397 	view->FillRect(rect, fillGradient);
1398 
1399 	// reset clipping constraints
1400 	view->ConstrainClippingRegion(NULL);
1401 }
1402 
1403 
1404 void
1405 BControlLook::DrawInactiveTab(BView* view, BRect& rect, const BRect& updateRect,
1406 	const rgb_color& base, uint32 flags, uint32 borders)
1407 {
1408 	if (!rect.IsValid() || !rect.Intersects(updateRect))
1409 		return;
1410 
1411 	rgb_color edgeShadowColor;
1412 	rgb_color edgeLightColor;
1413 	rgb_color frameShadowColor;
1414 	rgb_color frameLightColor;
1415 	rgb_color bevelShadowColor;
1416 	rgb_color bevelLightColor;
1417 	BGradientLinear fillGradient;
1418 	fillGradient.SetStart(rect.LeftTop() + BPoint(3, 3));
1419 	fillGradient.SetEnd(rect.LeftBottom() + BPoint(3, -3));
1420 
1421 	if ((flags & B_DISABLED) != 0) {
1422 		edgeLightColor = base;
1423 		edgeShadowColor = base;
1424 		frameLightColor = tint_color(base, 1.25);
1425 		frameShadowColor = tint_color(base, 1.30);
1426 		bevelLightColor = tint_color(base, 0.8);
1427 		bevelShadowColor = tint_color(base, 1.07);
1428 		fillGradient.AddColor(tint_color(base, 0.85), 0);
1429 		fillGradient.AddColor(base, 255);
1430 	} else {
1431 		edgeLightColor = tint_color(base, 0.80);
1432 		edgeShadowColor = tint_color(base, 1.03);
1433 		frameLightColor = tint_color(base, 1.30);
1434 		frameShadowColor = tint_color(base, 1.30);
1435 		bevelLightColor = tint_color(base, 1.10);
1436 		bevelShadowColor = tint_color(base, 1.17);
1437 		fillGradient.AddColor(tint_color(base, 1.12), 0);
1438 		fillGradient.AddColor(tint_color(base, 1.08), 255);
1439 	}
1440 
1441 	// active tabs stand out at the top, but this is an inactive tab
1442 	view->SetHighColor(base);
1443 	view->FillRect(BRect(rect.left, rect.top, rect.right, rect.top + 4));
1444 	rect.top += 4;
1445 
1446 	// frame and fill
1447 	_DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, edgeLightColor,
1448 		edgeLightColor,
1449 		borders & (B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER));
1450 
1451 	_DrawFrame(view, rect, frameLightColor, frameLightColor, frameShadowColor,
1452 		frameShadowColor,
1453 		borders & (B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER));
1454 
1455 	if (rect.IsValid()) {
1456 		_DrawFrame(view, rect, bevelShadowColor, bevelShadowColor,
1457 			bevelLightColor, bevelLightColor, B_LEFT_BORDER & ~borders);
1458 	} else {
1459 		if ((B_LEFT_BORDER & ~borders) != 0)
1460 			rect.left++;
1461 	}
1462 
1463 	view->FillRect(rect, fillGradient);
1464 }
1465 
1466 
1467 void
1468 BControlLook::DrawSplitter(BView* view, BRect& rect, const BRect& updateRect,
1469 	const rgb_color& base, enum orientation orientation, uint32 flags,
1470 	uint32 borders)
1471 {
1472 	if (!rect.IsValid() || !rect.Intersects(updateRect))
1473 		return;
1474 
1475 	rgb_color background;
1476 	if ((flags & (B_CLICKED | B_ACTIVATED)) != 0)
1477 		background = tint_color(base, B_DARKEN_1_TINT);
1478 	else
1479 		background = base;
1480 
1481 	rgb_color light = tint_color(background, 0.6);
1482 	rgb_color shadow = tint_color(background, 1.21);
1483 
1484 	// frame
1485 	if (borders != 0 && rect.Width() > 3 && rect.Height() > 3)
1486 		DrawRaisedBorder(view, rect, updateRect, background, flags, borders);
1487 
1488 	// dots and rest of background
1489 	if (orientation == B_HORIZONTAL) {
1490 		if (rect.Width() > 2) {
1491 			// background on left/right
1492 			BRegion region(rect);
1493 			rect.left = floorf((rect.left + rect.right) / 2.0 - 0.5);
1494 			rect.right = rect.left + 1;
1495 			region.Exclude(rect);
1496 			view->SetHighColor(background);
1497 			view->FillRegion(&region);
1498 		}
1499 
1500 		BPoint dot = rect.LeftTop();
1501 		BPoint stop = rect.LeftBottom();
1502 		int32 num = 1;
1503 		while (dot.y <= stop.y) {
1504 			rgb_color col1;
1505 			rgb_color col2;
1506 			switch (num) {
1507 				case 1:
1508 					col1 = background;
1509 					col2 = background;
1510 					break;
1511 				case 2:
1512 					col1 = shadow;
1513 					col2 = background;
1514 					break;
1515 				case 3:
1516 				default:
1517 					col1 = background;
1518 					col2 = light;
1519 					num = 0;
1520 					break;
1521 			}
1522 			view->SetHighColor(col1);
1523 			view->StrokeLine(dot, dot, B_SOLID_HIGH);
1524 			view->SetHighColor(col2);
1525 			dot.x++;
1526 			view->StrokeLine(dot, dot, B_SOLID_HIGH);
1527 			dot.x -= 1.0;
1528 			// next pixel
1529 			num++;
1530 			dot.y++;
1531 		}
1532 	} else {
1533 		if (rect.Height() > 2) {
1534 			// background on left/right
1535 			BRegion region(rect);
1536 			rect.top = floorf((rect.top + rect.bottom) / 2.0 - 0.5);
1537 			rect.bottom = rect.top + 1;
1538 			region.Exclude(rect);
1539 			view->SetHighColor(background);
1540 			view->FillRegion(&region);
1541 		}
1542 
1543 		BPoint dot = rect.LeftTop();
1544 		BPoint stop = rect.RightTop();
1545 		int32 num = 1;
1546 		while (dot.x <= stop.x) {
1547 			rgb_color col1;
1548 			rgb_color col2;
1549 			switch (num) {
1550 				case 1:
1551 					col1 = background;
1552 					col2 = background;
1553 					break;
1554 				case 2:
1555 					col1 = shadow;
1556 					col2 = background;
1557 					break;
1558 				case 3:
1559 				default:
1560 					col1 = background;
1561 					col2 = light;
1562 					num = 0;
1563 					break;
1564 			}
1565 			view->SetHighColor(col1);
1566 			view->StrokeLine(dot, dot, B_SOLID_HIGH);
1567 			view->SetHighColor(col2);
1568 			dot.y++;
1569 			view->StrokeLine(dot, dot, B_SOLID_HIGH);
1570 			dot.y -= 1.0;
1571 			// next pixel
1572 			num++;
1573 			dot.x++;
1574 		}
1575 	}
1576 }
1577 
1578 
1579 // #pragma mark -
1580 
1581 
1582 void
1583 BControlLook::DrawBorder(BView* view, BRect& rect, const BRect& updateRect,
1584 	const rgb_color& base, border_style border, uint32 flags, uint32 borders)
1585 {
1586 	if (border == B_NO_BORDER)
1587 		return;
1588 
1589 	rgb_color scrollbarFrameColor = tint_color(base, B_DARKEN_2_TINT);
1590 	if ((flags & B_FOCUSED) != 0)
1591 		scrollbarFrameColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1592 
1593 	if (border == B_FANCY_BORDER)
1594 		_DrawOuterResessedFrame(view, rect, base, 1.0, 1.0, flags, borders);
1595 
1596 	_DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor,
1597 		scrollbarFrameColor, scrollbarFrameColor, borders);
1598 }
1599 
1600 
1601 void
1602 BControlLook::DrawRaisedBorder(BView* view, BRect& rect,
1603 	const BRect& updateRect, const rgb_color& base, uint32 flags,
1604 	uint32 borders)
1605 {
1606 	rgb_color lightColor;
1607 	rgb_color shadowColor;
1608 
1609 	if ((flags & B_DISABLED) != 0) {
1610 		lightColor = base;
1611 		shadowColor = base;
1612 	} else {
1613 		lightColor = tint_color(base, 0.85);
1614 		shadowColor = tint_color(base, 1.07);
1615 	}
1616 
1617 	_DrawFrame(view, rect, lightColor, lightColor, shadowColor, shadowColor,
1618 		borders);
1619 }
1620 
1621 
1622 void
1623 BControlLook::DrawTextControlBorder(BView* view, BRect& rect,
1624 	const BRect& updateRect, const rgb_color& base, uint32 flags,
1625 	uint32 borders)
1626 {
1627 	if (!rect.Intersects(updateRect))
1628 		return;
1629 
1630 	rgb_color dark1BorderColor;
1631 	rgb_color dark2BorderColor;
1632 	rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1633 
1634 	if ((flags & B_DISABLED) != 0) {
1635 		_DrawOuterResessedFrame(view, rect, base, 0.0, 1.0, flags, borders);
1636 
1637 		if ((flags & B_BLEND_FRAME) != 0)
1638 			dark1BorderColor = (rgb_color){ 0, 0, 0, 40 };
1639 		else
1640 			dark1BorderColor = tint_color(base, 1.15);
1641 		dark2BorderColor = dark1BorderColor;
1642 	} else if ((flags & B_CLICKED) != 0) {
1643 		dark1BorderColor = tint_color(base, 1.50);
1644 		dark2BorderColor = tint_color(base, 1.49);
1645 
1646 		// BCheckBox uses this to indicate the clicked state...
1647 		_DrawFrame(view, rect,
1648 			dark1BorderColor, dark1BorderColor,
1649 			dark2BorderColor, dark2BorderColor);
1650 
1651 		dark2BorderColor = dark1BorderColor;
1652 	} else {
1653 		_DrawOuterResessedFrame(view, rect, base, 0.6, 1.0, flags, borders);
1654 
1655 		if ((flags & B_BLEND_FRAME) != 0) {
1656 			dark1BorderColor = (rgb_color){ 0, 0, 0, 102 };
1657 			dark2BorderColor = (rgb_color){ 0, 0, 0, 97 };
1658 		} else {
1659 			dark1BorderColor = tint_color(base, 1.40);
1660 			dark2BorderColor = tint_color(base, 1.38);
1661 		}
1662 	}
1663 
1664 	if ((flags & B_DISABLED) == 0 && (flags & B_FOCUSED) != 0) {
1665 		dark1BorderColor = navigationColor;
1666 		dark2BorderColor = navigationColor;
1667 	}
1668 
1669 	if ((flags & B_BLEND_FRAME) != 0) {
1670 		drawing_mode oldMode = view->DrawingMode();
1671 		view->SetDrawingMode(B_OP_ALPHA);
1672 
1673 		_DrawFrame(view, rect,
1674 			dark1BorderColor, dark1BorderColor,
1675 			dark2BorderColor, dark2BorderColor, borders);
1676 
1677 		view->SetDrawingMode(oldMode);
1678 	} else {
1679 		_DrawFrame(view, rect,
1680 			dark1BorderColor, dark1BorderColor,
1681 			dark2BorderColor, dark2BorderColor, borders);
1682 	}
1683 }
1684 
1685 
1686 void
1687 BControlLook::DrawGroupFrame(BView* view, BRect& rect, const BRect& updateRect,
1688 	const rgb_color& base, uint32 borders)
1689 {
1690 	rgb_color frameColor = tint_color(base, 1.30);
1691 	rgb_color bevelLight = tint_color(base, 0.8);
1692 	rgb_color bevelShadow = tint_color(base, 1.03);
1693 
1694 	_DrawFrame(view, rect, bevelShadow, bevelShadow, bevelLight, bevelLight,
1695 		borders);
1696 
1697 	_DrawFrame(view, rect, frameColor, frameColor, frameColor, frameColor,
1698 		borders);
1699 
1700 	_DrawFrame(view, rect, bevelLight, bevelLight, bevelShadow, bevelShadow,
1701 		borders);
1702 }
1703 
1704 
1705 void
1706 BControlLook::DrawLabel(BView* view, const char* label, BRect rect,
1707 	const BRect& updateRect, const rgb_color& base, uint32 flags)
1708 {
1709 	DrawLabel(view, label, rect, updateRect, base, flags,
1710 		DefaultLabelAlignment());
1711 }
1712 
1713 
1714 void
1715 BControlLook::DrawLabel(BView* view, const char* label, BRect rect,
1716 	const BRect& updateRect, const rgb_color& base, uint32 flags,
1717 	const BAlignment& alignment)
1718 {
1719 	if (!rect.Intersects(updateRect))
1720 		return;
1721 
1722 	// truncate the label if necessary and get the width and height
1723 	BString truncatedLabel(label);
1724 
1725 	BFont font;
1726 	view->GetFont(&font);
1727 
1728 	float width = rect.Width();
1729 	font.TruncateString(&truncatedLabel, B_TRUNCATE_END, width);
1730 	width = font.StringWidth(truncatedLabel.String());
1731 
1732 	font_height fontHeight;
1733 	font.GetHeight(&fontHeight);
1734 	float height = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
1735 
1736 	// handle alignment
1737 	BPoint location;
1738 
1739 	switch (alignment.horizontal) {
1740 	default:
1741 		case B_ALIGN_LEFT:
1742 			location.x = rect.left;
1743 			break;
1744 		case B_ALIGN_RIGHT:
1745 			location.x = rect.right - width;
1746 			break;
1747 		case B_ALIGN_CENTER:
1748 			location.x = (rect.left + rect.right - width) / 2.0f;
1749 			break;
1750 	}
1751 
1752 	switch (alignment.vertical) {
1753 		case B_ALIGN_TOP:
1754 			location.y = rect.top + ceilf(fontHeight.ascent);
1755 			break;
1756 		default:
1757 		case B_ALIGN_MIDDLE:
1758 			location.y = floorf((rect.top + rect.bottom - height) / 2.0f + 0.5f)
1759 				+ ceilf(fontHeight.ascent);
1760 			break;
1761 		case B_ALIGN_BOTTOM:
1762 			location.y = rect.bottom - ceilf(fontHeight.descent);
1763 			break;
1764 	}
1765 
1766 	DrawLabel(view, truncatedLabel.String(), base, flags, location);
1767 }
1768 
1769 
1770 void
1771 BControlLook::DrawLabel(BView* view, const char* label, const rgb_color& base,
1772 	uint32 flags, const BPoint& where)
1773 {
1774 	// setup the text color
1775 	// TODO: Should either use the ui_color(B_CONTROL_TEXT_COLOR) here,
1776 	// or elliminate that constant alltogether (stippi: +1).
1777 
1778 	BWindow* window = view->Window();
1779 	bool isDesktop = window
1780 		&& window->Feel() == kPrivateDesktopWindowFeel
1781 		&& window->Look() == kPrivateDesktopWindowLook
1782 		&& view->Parent()
1783 		&& view->Parent()->Parent() == NULL
1784 		&& (flags & B_IGNORE_OUTLINE) == 0;
1785 
1786 	rgb_color	low;
1787 	rgb_color	color;
1788 	rgb_color	glowColor;
1789 
1790 	if (isDesktop)
1791 		low = view->Parent()->ViewColor();
1792 	else
1793 		low = base;
1794 
1795 	if (low.red + low.green + low.blue > 128 * 3) {
1796 		color = tint_color(low, B_DARKEN_MAX_TINT);
1797 		glowColor = kWhite;
1798 	} else {
1799 		color = tint_color(low, B_LIGHTEN_MAX_TINT);
1800 		glowColor = kBlack;
1801 	}
1802 
1803 	if ((flags & B_DISABLED) != 0) {
1804 		color.red = (uint8)(((int32)low.red + color.red + 1) / 2);
1805 		color.green = (uint8)(((int32)low.green + color.green + 1) / 2);
1806 		color.blue = (uint8)(((int32)low.blue + color.blue + 1) / 2);
1807 	}
1808 
1809 	drawing_mode oldMode = view->DrawingMode();
1810 
1811 	if (isDesktop) {
1812 		// drawing occurs on the desktop
1813 		if (fCachedWorkspace != current_workspace()) {
1814 			int8 indice = 0;
1815 			int32 mask;
1816 			bool tmpOutline;
1817 			while (fBackgroundInfo.FindInt32("be:bgndimginfoworkspaces",
1818 					indice, &mask) == B_OK
1819 				&& fBackgroundInfo.FindBool("be:bgndimginfoerasetext",
1820 					indice, &tmpOutline) == B_OK) {
1821 
1822 				if (((1 << current_workspace()) & mask) != 0) {
1823 					fCachedOutline = tmpOutline;
1824 					fCachedWorkspace = current_workspace();
1825 					break;
1826 				}
1827 				indice++;
1828 			}
1829 		}
1830 
1831 		if (fCachedOutline) {
1832 			BFont font;
1833 			view->GetFont(&font);
1834 
1835 			view->SetDrawingMode(B_OP_ALPHA);
1836 			view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
1837 			// Draw glow or outline
1838 			if (glowColor == kWhite) {
1839 				font.SetFalseBoldWidth(2.0);
1840 				view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1841 
1842 				glowColor.alpha = 30;
1843 				view->SetHighColor(glowColor);
1844 				view->DrawString(label, where);
1845 
1846 				font.SetFalseBoldWidth(1.0);
1847 				view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1848 
1849 				glowColor.alpha = 65;
1850 				view->SetHighColor(glowColor);
1851 				view->DrawString(label, where);
1852 
1853 				font.SetFalseBoldWidth(0.0);
1854 				view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1855 			} else if (glowColor == kBlack) {
1856 				font.SetFalseBoldWidth(1.0);
1857 				view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1858 
1859 				glowColor.alpha = 30;
1860 				view->SetHighColor(glowColor);
1861 				view->DrawString(label, where);
1862 
1863 				font.SetFalseBoldWidth(0.0);
1864 				view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1865 
1866 				glowColor.alpha = 200;
1867 				view->SetHighColor(glowColor);
1868 				view->DrawString(label, BPoint(where.x + 1, where.y + 1));
1869 			}
1870 		}
1871 	}
1872 
1873 	view->SetHighColor(color);
1874 	view->SetDrawingMode(B_OP_OVER);
1875 	view->DrawString(label, where);
1876 	view->SetDrawingMode(oldMode);
1877 }
1878 
1879 
1880 void
1881 BControlLook::SetBackgroundInfo(const BMessage& backgroundInfo)
1882 {
1883 	fBackgroundInfo = backgroundInfo;
1884 	fCachedWorkspace = -1;
1885 }
1886 
1887 
1888 // #pragma mark -
1889 
1890 
1891 void
1892 BControlLook::_DrawButtonFrame(BView* view, BRect& rect,
1893 	const BRect& updateRect, float leftTopRadius, float rightTopRadius,
1894 	float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
1895 	const rgb_color& background, float contrast, float brightness,
1896 	uint32 flags, uint32 borders)
1897 {
1898 	if (!rect.IsValid() || !rect.Intersects(updateRect))
1899 		return;
1900 
1901 	// clipping constraints for the view
1902 	BRegion clipping;
1903 	view->GetClippingRegion(&clipping);
1904 
1905 	// intersect constraints with updateRect
1906 	BRegion updateClipping(updateRect);
1907 	clipping.IntersectWith(&updateClipping);
1908 
1909 	// clip to the intersection
1910 	view->ConstrainClippingRegion(&clipping);
1911 
1912 	// outer edge colors
1913 	rgb_color edgeLightColor;
1914 	rgb_color edgeShadowColor;
1915 
1916 	// default button frame color
1917 	// TODO: B_BLEND_FRAME
1918 	float defaultIndicatorTint = 1.2;
1919 	if ((flags & B_DISABLED) != 0)
1920 		defaultIndicatorTint = (B_NO_TINT + defaultIndicatorTint) / 2;
1921 
1922 	rgb_color defaultIndicatorColor = tint_color(base, defaultIndicatorTint);
1923 	rgb_color cornerBgColor;
1924 
1925 	drawing_mode oldMode = view->DrawingMode();
1926 
1927 	if ((flags & B_DEFAULT_BUTTON) != 0) {
1928 		cornerBgColor = defaultIndicatorColor;
1929 		edgeLightColor = _EdgeLightColor(defaultIndicatorColor,
1930 			contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8),
1931 			brightness * ((flags & B_DISABLED) != 0 ? 1.0 : 0.9), flags);
1932 		edgeShadowColor = _EdgeShadowColor(defaultIndicatorColor,
1933 			contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8),
1934 			brightness * ((flags & B_DISABLED) != 0 ? 1.0 : 0.9), flags);
1935 
1936 		// draw default button indicator
1937 		view->SetHighColor(background);
1938 		view->FillRect(rect);
1939 		view->SetHighColor(base);
1940 		view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius);
1941 		rect.InsetBy(1, 1);
1942 
1943 		view->SetHighColor(defaultIndicatorColor);
1944 		view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius);
1945 		rect.InsetBy(1, 1);
1946 
1947 		view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius);
1948 		rect.InsetBy(1, 1);
1949 	} else {
1950 		cornerBgColor = background;
1951 		if ((flags & B_BLEND_FRAME) != 0) {
1952 			// set the background color to transparent for the case
1953 			// that we are on the desktop
1954 			cornerBgColor.alpha = 0;
1955 			view->SetDrawingMode(B_OP_ALPHA);
1956 		}
1957 
1958 		edgeLightColor = _EdgeLightColor(background,
1959 			contrast * ((flags & B_DISABLED) != 0 ? 0.0 : 1.0),
1960 			brightness * 1.0, flags);
1961 		edgeShadowColor = _EdgeShadowColor(background,
1962 			contrast * (flags & B_DISABLED) != 0 ? 0.0 : 1.0,
1963 			brightness * 1.0, flags);
1964 	}
1965 
1966 	// frame colors
1967 	rgb_color frameLightColor  = _FrameLightColor(base, flags);
1968 	rgb_color frameShadowColor = _FrameShadowColor(base, flags);
1969 
1970 	// rounded corners
1971 
1972 	if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0
1973 		&& leftTopRadius > 0) {
1974 		// draw left top rounded corner
1975 		BRect leftTopCorner(floorf(rect.left), floorf(rect.top),
1976 			floorf(rect.left + leftTopRadius),
1977 			floorf(rect.top + leftTopRadius));
1978 		clipping.Exclude(leftTopCorner);
1979 		_DrawRoundCornerFrameLeftTop(view, leftTopCorner, updateRect,
1980 			cornerBgColor, edgeShadowColor, frameLightColor);
1981 	}
1982 
1983 	if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0
1984 		&& rightTopRadius > 0) {
1985 		// draw right top rounded corner
1986 		BRect rightTopCorner(floorf(rect.right - rightTopRadius),
1987 			floorf(rect.top), floorf(rect.right),
1988 			floorf(rect.top + rightTopRadius));
1989 		clipping.Exclude(rightTopCorner);
1990 		_DrawRoundCornerFrameRightTop(view, rightTopCorner, updateRect,
1991 			cornerBgColor, edgeShadowColor, edgeLightColor,
1992 			frameLightColor, frameShadowColor);
1993 	}
1994 
1995 	if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
1996 		&& leftBottomRadius > 0) {
1997 		// draw left bottom rounded corner
1998 		BRect leftBottomCorner(floorf(rect.left),
1999 			floorf(rect.bottom - leftBottomRadius),
2000 			floorf(rect.left + leftBottomRadius), floorf(rect.bottom));
2001 		clipping.Exclude(leftBottomCorner);
2002 		_DrawRoundCornerFrameLeftBottom(view, leftBottomCorner, updateRect,
2003 			cornerBgColor, edgeShadowColor, edgeLightColor,
2004 			frameLightColor, frameShadowColor);
2005 	}
2006 
2007 	if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2008 		&& rightBottomRadius > 0) {
2009 		// draw right bottom rounded corner
2010 		BRect rightBottomCorner(floorf(rect.right - rightBottomRadius),
2011 			floorf(rect.bottom - rightBottomRadius), floorf(rect.right),
2012 			floorf(rect.bottom));
2013 		clipping.Exclude(rightBottomCorner);
2014 		_DrawRoundCornerFrameRightBottom(view, rightBottomCorner,
2015 			updateRect, cornerBgColor, edgeLightColor, frameShadowColor);
2016 	}
2017 
2018 	// clip out the corners
2019 	view->ConstrainClippingRegion(&clipping);
2020 
2021 	// draw outer edge
2022 	if ((flags & B_DEFAULT_BUTTON) != 0) {
2023 		_DrawOuterResessedFrame(view, rect, defaultIndicatorColor,
2024 			contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8),
2025 			brightness * ((flags & B_DISABLED) != 0 ? 1.0 : 0.9),
2026 			flags, borders);
2027 	} else {
2028 		_DrawOuterResessedFrame(view, rect, background,
2029 			contrast * ((flags & B_DISABLED) != 0 ? 0.0 : 1.0),
2030 			brightness * 1.0, flags, borders);
2031 	}
2032 
2033 	view->SetDrawingMode(oldMode);
2034 
2035 	// draw frame
2036 	if ((flags & B_BLEND_FRAME) != 0) {
2037 		drawing_mode oldDrawingMode = view->DrawingMode();
2038 		view->SetDrawingMode(B_OP_ALPHA);
2039 
2040 		_DrawFrame(view, rect, frameLightColor, frameLightColor,
2041 			frameShadowColor, frameShadowColor, borders);
2042 
2043 		view->SetDrawingMode(oldDrawingMode);
2044 	} else {
2045 		_DrawFrame(view, rect, frameLightColor, frameLightColor,
2046 			frameShadowColor, frameShadowColor, borders);
2047 	}
2048 
2049 	view->ConstrainClippingRegion(NULL);
2050 }
2051 
2052 
2053 void
2054 BControlLook::_DrawOuterResessedFrame(BView* view, BRect& rect,
2055 	const rgb_color& base, float contrast, float brightness, uint32 flags,
2056 	uint32 borders)
2057 {
2058 	rgb_color edgeLightColor = _EdgeLightColor(base, contrast,
2059 		brightness, flags);
2060 	rgb_color edgeShadowColor = _EdgeShadowColor(base, contrast,
2061 		brightness, flags);
2062 
2063 	if ((flags & B_BLEND_FRAME) != 0) {
2064 		// assumes the background has already been painted
2065 		drawing_mode oldDrawingMode = view->DrawingMode();
2066 		view->SetDrawingMode(B_OP_ALPHA);
2067 
2068 		_DrawFrame(view, rect, edgeShadowColor, edgeShadowColor,
2069 			edgeLightColor, edgeLightColor, borders);
2070 
2071 		view->SetDrawingMode(oldDrawingMode);
2072 	} else {
2073 		_DrawFrame(view, rect, edgeShadowColor, edgeShadowColor,
2074 			edgeLightColor, edgeLightColor, borders);
2075 	}
2076 }
2077 
2078 
2079 void
2080 BControlLook::_DrawFrame(BView* view, BRect& rect, const rgb_color& left,
2081 	const rgb_color& top, const rgb_color& right, const rgb_color& bottom,
2082 	uint32 borders)
2083 {
2084 	view->BeginLineArray(4);
2085 
2086 	if (borders & B_LEFT_BORDER) {
2087 		view->AddLine(
2088 			BPoint(rect.left, rect.bottom),
2089 			BPoint(rect.left, rect.top), left);
2090 		rect.left++;
2091 	}
2092 	if (borders & B_TOP_BORDER) {
2093 		view->AddLine(
2094 			BPoint(rect.left, rect.top),
2095 			BPoint(rect.right, rect.top), top);
2096 		rect.top++;
2097 	}
2098 	if (borders & B_RIGHT_BORDER) {
2099 		view->AddLine(
2100 			BPoint(rect.right, rect.top),
2101 			BPoint(rect.right, rect.bottom), right);
2102 		rect.right--;
2103 	}
2104 	if (borders & B_BOTTOM_BORDER) {
2105 		view->AddLine(
2106 			BPoint(rect.left, rect.bottom),
2107 			BPoint(rect.right, rect.bottom), bottom);
2108 		rect.bottom--;
2109 	}
2110 
2111 	view->EndLineArray();
2112 }
2113 
2114 
2115 void
2116 BControlLook::_DrawFrame(BView* view, BRect& rect, const rgb_color& left,
2117 	const rgb_color& top, const rgb_color& right, const rgb_color& bottom,
2118 	const rgb_color& rightTop, const rgb_color& leftBottom, uint32 borders)
2119 {
2120 	view->BeginLineArray(6);
2121 
2122 	if (borders & B_TOP_BORDER) {
2123 		if (borders & B_RIGHT_BORDER) {
2124 			view->AddLine(
2125 				BPoint(rect.left, rect.top),
2126 				BPoint(rect.right - 1, rect.top), top);
2127 			view->AddLine(
2128 				BPoint(rect.right, rect.top),
2129 				BPoint(rect.right, rect.top), rightTop);
2130 		} else {
2131 			view->AddLine(
2132 				BPoint(rect.left, rect.top),
2133 				BPoint(rect.right, rect.top), top);
2134 		}
2135 		rect.top++;
2136 	}
2137 
2138 	if (borders & B_LEFT_BORDER) {
2139 		view->AddLine(
2140 			BPoint(rect.left, rect.top),
2141 			BPoint(rect.left, rect.bottom - 1), left);
2142 		view->AddLine(
2143 			BPoint(rect.left, rect.bottom),
2144 			BPoint(rect.left, rect.bottom), leftBottom);
2145 		rect.left++;
2146 	}
2147 
2148 	if (borders & B_BOTTOM_BORDER) {
2149 		view->AddLine(
2150 			BPoint(rect.left, rect.bottom),
2151 			BPoint(rect.right, rect.bottom), bottom);
2152 		rect.bottom--;
2153 	}
2154 
2155 	if (borders & B_RIGHT_BORDER) {
2156 		view->AddLine(
2157 			BPoint(rect.right, rect.bottom),
2158 			BPoint(rect.right, rect.top), right);
2159 		rect.right--;
2160 	}
2161 
2162 	view->EndLineArray();
2163 }
2164 
2165 
2166 void
2167 BControlLook::_DrawButtonBackground(BView* view, BRect& rect,
2168 	const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2169 	float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2170 	uint32 flags, uint32 borders, enum orientation orientation)
2171 {
2172 	if (!rect.IsValid() || !rect.Intersects(updateRect))
2173 		return;
2174 
2175 	// clipping constraints for the view
2176 	BRegion clipping;
2177 	view->GetClippingRegion(&clipping);
2178 
2179 	// intersect constraints with updateRect
2180 	BRegion updateClipping(updateRect);
2181 	clipping.IntersectWith(&updateClipping);
2182 
2183 	// clip to the intersection
2184 	view->ConstrainClippingRegion(&clipping);
2185 
2186 	// inner bevel colors
2187 	rgb_color bevelLightColor  = _BevelLightColor(base, flags);
2188 	rgb_color bevelShadowColor = _BevelShadowColor(base, flags);
2189 
2190 	// button background color
2191 	rgb_color buttonBgColor;
2192 	if ((flags & B_DISABLED) != 0)
2193 		buttonBgColor = tint_color(base, 0.7);
2194 	else
2195 		buttonBgColor = tint_color(base, B_LIGHTEN_1_TINT);
2196 
2197 	// surface top gradient
2198 	BGradientLinear fillGradient;
2199 	_MakeButtonGradient(fillGradient, rect, base, flags, orientation);
2200 
2201 	// rounded corners
2202 
2203 	if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0
2204 		&& leftTopRadius > 0) {
2205 		// draw left top rounded corner
2206 		BRect leftTopCorner(floorf(rect.left), floorf(rect.top),
2207 			floorf(rect.left + leftTopRadius - 2.0),
2208 			floorf(rect.top + leftTopRadius - 2.0));
2209 		clipping.Exclude(leftTopCorner);
2210 		_DrawRoundCornerBackgroundLeftTop(view, leftTopCorner, updateRect,
2211 			bevelLightColor, fillGradient);
2212 	}
2213 
2214 	if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0
2215 		&& rightTopRadius > 0) {
2216 		// draw right top rounded corner
2217 		BRect rightTopCorner(floorf(rect.right - rightTopRadius + 2.0),
2218 			floorf(rect.top), floorf(rect.right),
2219 			floorf(rect.top + rightTopRadius - 2.0));
2220 		clipping.Exclude(rightTopCorner);
2221 		_DrawRoundCornerBackgroundRightTop(view, rightTopCorner,
2222 			updateRect, bevelLightColor, bevelShadowColor, fillGradient);
2223 	}
2224 
2225 	if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2226 		&& leftBottomRadius > 0) {
2227 		// draw left bottom rounded corner
2228 		BRect leftBottomCorner(floorf(rect.left),
2229 			floorf(rect.bottom - leftBottomRadius + 2.0),
2230 			floorf(rect.left + leftBottomRadius - 2.0),
2231 			floorf(rect.bottom));
2232 		clipping.Exclude(leftBottomCorner);
2233 		_DrawRoundCornerBackgroundLeftBottom(view, leftBottomCorner,
2234 			updateRect, bevelLightColor, bevelShadowColor, fillGradient);
2235 	}
2236 
2237 	if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2238 		&& rightBottomRadius > 0) {
2239 		// draw right bottom rounded corner
2240 		BRect rightBottomCorner(floorf(rect.right - rightBottomRadius + 2.0),
2241 			floorf(rect.bottom - rightBottomRadius + 2.0), floorf(rect.right),
2242 			floorf(rect.bottom));
2243 		clipping.Exclude(rightBottomCorner);
2244 		_DrawRoundCornerBackgroundRightBottom(view, rightBottomCorner,
2245 			updateRect, bevelShadowColor, fillGradient);
2246 	}
2247 
2248 	// clip out the corners
2249 	view->ConstrainClippingRegion(&clipping);
2250 
2251 	// draw inner bevel
2252 
2253 	if ((flags & B_ACTIVATED) != 0) {
2254 		view->BeginLineArray(4);
2255 
2256 		// shadow along left/top borders
2257 		if (borders & B_LEFT_BORDER) {
2258 			view->AddLine(BPoint(rect.left, rect.top),
2259 				BPoint(rect.left, rect.bottom), bevelLightColor);
2260 			rect.left++;
2261 		}
2262 		if (borders & B_TOP_BORDER) {
2263 			view->AddLine(BPoint(rect.left, rect.top),
2264 				BPoint(rect.right, rect.top), bevelLightColor);
2265 			rect.top++;
2266 		}
2267 
2268 		// softer shadow along left/top borders
2269 		if (borders & B_LEFT_BORDER) {
2270 			view->AddLine(BPoint(rect.left, rect.top),
2271 				BPoint(rect.left, rect.bottom), bevelShadowColor);
2272 			rect.left++;
2273 		}
2274 		if (borders & B_TOP_BORDER) {
2275 			view->AddLine(BPoint(rect.left, rect.top),
2276 				BPoint(rect.right, rect.top), bevelShadowColor);
2277 			rect.top++;
2278 		}
2279 
2280 		view->EndLineArray();
2281 	} else {
2282 		_DrawFrame(view, rect,
2283 			bevelLightColor, bevelLightColor,
2284 			bevelShadowColor, bevelShadowColor,
2285 			buttonBgColor, buttonBgColor, borders);
2286 	}
2287 
2288 	// fill in the background
2289 	view->FillRect(rect, fillGradient);
2290 
2291 	// reset clipping constraints
2292 	view->ConstrainClippingRegion(NULL);
2293 }
2294 
2295 
2296 void
2297 BControlLook::_DrawMenuFieldBackgroundOutside(BView* view, BRect& rect,
2298 	const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2299 	float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2300 	bool popupIndicator, uint32 flags)
2301 {
2302 	if (!rect.IsValid() || !rect.Intersects(updateRect))
2303 		return;
2304 
2305 	if (popupIndicator) {
2306 		BRect leftRect(rect);
2307 		leftRect.right -= 10;
2308 
2309 		BRect rightRect(rect);
2310 		rightRect.left = rightRect.right - 9;
2311 
2312 		_DrawMenuFieldBackgroundInside(view, leftRect, updateRect,
2313 			leftTopRadius, 0.0f, leftBottomRadius, 0.0f, base, flags,
2314 			B_LEFT_BORDER | B_TOP_BORDER | B_BOTTOM_BORDER);
2315 
2316 		_DrawMenuFieldBackgroundInside(view, rightRect, updateRect,
2317 			0.0f, rightTopRadius, 0.0f, rightBottomRadius, base, flags,
2318 			B_TOP_BORDER | B_RIGHT_BORDER | B_BOTTOM_BORDER);
2319 
2320 		// popup marker
2321 		BPoint center(roundf((rightRect.left + rightRect.right) / 2.0),
2322 					  roundf((rightRect.top + rightRect.bottom) / 2.0));
2323 		BPoint triangle[3];
2324 		triangle[0] = center + BPoint(-2.5, -0.5);
2325 		triangle[1] = center + BPoint(2.5, -0.5);
2326 		triangle[2] = center + BPoint(0.0, 2.0);
2327 
2328 		uint32 viewFlags = view->Flags();
2329 		view->SetFlags(viewFlags | B_SUBPIXEL_PRECISE);
2330 
2331 		rgb_color markColor;
2332 		if ((flags & B_DISABLED) != 0)
2333 			markColor = tint_color(base, 1.35);
2334 		else
2335 			markColor = tint_color(base, 1.65);
2336 
2337 		view->SetHighColor(markColor);
2338 		view->FillTriangle(triangle[0], triangle[1], triangle[2]);
2339 
2340 		// draw a line on the left of the popup frame
2341 		rgb_color bevelShadowColor = _BevelShadowColor(base, flags);
2342 		view->SetHighColor(bevelShadowColor);
2343 		BPoint leftTopCorner(floorf(rightRect.left - 1.0),
2344 			floorf(rightRect.top - 1.0));
2345 		BPoint leftBottomCorner(floorf(rightRect.left - 1.0),
2346 			floorf(rightRect.bottom + 1.0));
2347 		view->StrokeLine(leftTopCorner, leftBottomCorner);
2348 
2349 		view->SetFlags(viewFlags);
2350 
2351 		rect = leftRect;
2352 	} else {
2353 		_DrawMenuFieldBackgroundInside(view, rect, updateRect, leftTopRadius,
2354 			rightTopRadius, leftBottomRadius, rightBottomRadius, base, flags);
2355 	}
2356 }
2357 
2358 
2359 void
2360 BControlLook::_DrawMenuFieldBackgroundInside(BView* view, BRect& rect,
2361 	const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2362 	float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2363 	uint32 flags, uint32 borders)
2364 {
2365 	if (!rect.IsValid() || !rect.Intersects(updateRect))
2366 		return;
2367 
2368 	// clipping constraints for the view
2369 	BRegion clipping;
2370 	view->GetClippingRegion(&clipping);
2371 
2372 	// intersect constraints with updateRect
2373 	BRegion updateClipping(updateRect);
2374 	clipping.IntersectWith(&updateClipping);
2375 
2376 	// clip to the intersection
2377 	view->ConstrainClippingRegion(&clipping);
2378 
2379 	// frame colors
2380 	rgb_color frameLightColor  = _FrameLightColor(base, flags);
2381 	rgb_color frameShadowColor = _FrameShadowColor(base, flags);
2382 
2383 	// indicator background color
2384 	rgb_color indicatorBase;
2385 	if ((borders & B_LEFT_BORDER) != 0)
2386 		indicatorBase = base;
2387 	else {
2388 		if ((flags & B_DISABLED) != 0)
2389 			indicatorBase = tint_color(base, 1.05);
2390 		else
2391 			indicatorBase = tint_color(base, 1.12);
2392 	}
2393 
2394 	// bevel colors
2395 	rgb_color cornerColor = tint_color(indicatorBase, 0.85);
2396 	rgb_color bevelColor1 = tint_color(indicatorBase, 0.3);
2397 	rgb_color bevelColor2 = tint_color(indicatorBase, 0.5);
2398 	rgb_color bevelColor3 = tint_color(indicatorBase, 1.03);
2399 
2400 	if ((flags & B_DISABLED) != 0) {
2401 		cornerColor = tint_color(indicatorBase, 0.8);
2402 		bevelColor1 = tint_color(indicatorBase, 0.7);
2403 		bevelColor2 = tint_color(indicatorBase, 0.8);
2404 		bevelColor3 = tint_color(indicatorBase, 1.01);
2405 	} else {
2406 		cornerColor = tint_color(indicatorBase, 0.85);
2407 		bevelColor1 = tint_color(indicatorBase, 0.3);
2408 		bevelColor2 = tint_color(indicatorBase, 0.5);
2409 		bevelColor3 = tint_color(indicatorBase, 1.03);
2410 	}
2411 
2412 	// surface top gradient
2413 	BGradientLinear fillGradient;
2414 	_MakeButtonGradient(fillGradient, rect, indicatorBase, flags);
2415 
2416 	// rounded corners
2417 
2418 	if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0
2419 		&& leftTopRadius > 0) {
2420 		// draw left top rounded corner
2421 		BRect leftTopCorner(floorf(rect.left), floorf(rect.top),
2422 			floorf(rect.left + leftTopRadius - 2.0),
2423 			floorf(rect.top + leftTopRadius - 2.0));
2424 		clipping.Exclude(leftTopCorner);
2425 
2426 		BRegion cornerClipping(leftTopCorner);
2427 		view->ConstrainClippingRegion(&cornerClipping);
2428 
2429 		BRect ellipseRect(leftTopCorner);
2430 		ellipseRect.InsetBy(-1.0, -1.0);
2431 		ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2432 		ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2433 
2434 		// draw the frame (again)
2435 		view->SetHighColor(frameLightColor);
2436 		view->FillEllipse(ellipseRect);
2437 
2438 		// draw the bevel and background
2439 		_DrawRoundCornerBackgroundLeftTop(view, leftTopCorner, updateRect,
2440 			bevelColor1, fillGradient);
2441 	}
2442 
2443 	if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0
2444 		&& rightTopRadius > 0) {
2445 		// draw right top rounded corner
2446 		BRect rightTopCorner(floorf(rect.right - rightTopRadius + 2.0),
2447 			floorf(rect.top), floorf(rect.right),
2448 			floorf(rect.top + rightTopRadius - 2.0));
2449 		clipping.Exclude(rightTopCorner);
2450 
2451 		BRegion cornerClipping(rightTopCorner);
2452 		view->ConstrainClippingRegion(&cornerClipping);
2453 
2454 		BRect ellipseRect(rightTopCorner);
2455 		ellipseRect.InsetBy(-1.0, -1.0);
2456 		ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
2457 		ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2458 
2459 		// draw the frame (again)
2460 		if (frameLightColor == frameShadowColor) {
2461 			view->SetHighColor(frameLightColor);
2462 			view->FillEllipse(ellipseRect);
2463 		} else {
2464 			BGradientLinear gradient;
2465 			gradient.AddColor(frameLightColor, 0);
2466 			gradient.AddColor(frameShadowColor, 255);
2467 			gradient.SetStart(rightTopCorner.LeftTop());
2468 			gradient.SetEnd(rightTopCorner.RightBottom());
2469 			view->FillEllipse(ellipseRect, gradient);
2470 		}
2471 
2472 		// draw the bevel and background
2473 		_DrawRoundCornerBackgroundRightTop(view, rightTopCorner, updateRect,
2474 			bevelColor1, bevelColor3, fillGradient);
2475 	}
2476 
2477 	if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2478 		&& leftBottomRadius > 0) {
2479 		// draw left bottom rounded corner
2480 		BRect leftBottomCorner(floorf(rect.left),
2481 			floorf(rect.bottom - leftBottomRadius + 2.0),
2482 			floorf(rect.left + leftBottomRadius - 2.0),
2483 			floorf(rect.bottom));
2484 		clipping.Exclude(leftBottomCorner);
2485 
2486 		BRegion cornerClipping(leftBottomCorner);
2487 		view->ConstrainClippingRegion(&cornerClipping);
2488 
2489 		BRect ellipseRect(leftBottomCorner);
2490 		ellipseRect.InsetBy(-1.0, -1.0);
2491 		ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2492 		ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
2493 
2494 		// draw the frame (again)
2495 		if (frameLightColor == frameShadowColor) {
2496 			view->SetHighColor(frameLightColor);
2497 			view->FillEllipse(ellipseRect);
2498 		} else {
2499 			BGradientLinear gradient;
2500 			gradient.AddColor(frameLightColor, 0);
2501 			gradient.AddColor(frameShadowColor, 255);
2502 			gradient.SetStart(leftBottomCorner.LeftTop());
2503 			gradient.SetEnd(leftBottomCorner.RightBottom());
2504 			view->FillEllipse(ellipseRect, gradient);
2505 		}
2506 
2507 		// draw the bevel and background
2508 		_DrawRoundCornerBackgroundLeftBottom(view, leftBottomCorner,
2509 			updateRect, bevelColor2, bevelColor3, fillGradient);
2510 	}
2511 
2512 	if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2513 		&& rightBottomRadius > 0) {
2514 		// draw right bottom rounded corner
2515 		BRect rightBottomCorner(floorf(rect.right - rightBottomRadius + 2.0),
2516 			floorf(rect.bottom - rightBottomRadius + 2.0), floorf(rect.right),
2517 			floorf(rect.bottom));
2518 		clipping.Exclude(rightBottomCorner);
2519 
2520 		BRegion cornerClipping(rightBottomCorner);
2521 		view->ConstrainClippingRegion(&cornerClipping);
2522 
2523 		BRect ellipseRect(rightBottomCorner);
2524 		ellipseRect.InsetBy(-1.0, -1.0);
2525 		ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
2526 		ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
2527 
2528 		// draw the frame (again)
2529 		view->SetHighColor(frameShadowColor);
2530 		view->FillEllipse(ellipseRect);
2531 
2532 		// draw the bevel and background
2533 		_DrawRoundCornerBackgroundRightBottom(view, rightBottomCorner,
2534 			updateRect, bevelColor3, fillGradient);
2535 	}
2536 
2537 	// clip out the corners
2538 	view->ConstrainClippingRegion(&clipping);
2539 
2540 	// draw the bevel
2541 	_DrawFrame(view, rect,
2542 		bevelColor2, bevelColor1,
2543 		bevelColor3, bevelColor3,
2544 		cornerColor, cornerColor,
2545 		borders);
2546 
2547 	// fill in the background
2548 	view->FillRect(rect, fillGradient);
2549 
2550 	// reset clipping constraints
2551 	view->ConstrainClippingRegion(NULL);
2552 }
2553 
2554 
2555 void
2556 BControlLook::_DrawRoundCornerLeftTop(BView* view, BRect& cornerRect,
2557 	const BRect& updateRect, const rgb_color& background,
2558 	const rgb_color& edgeColor, const rgb_color& frameColor,
2559 	const rgb_color& bevelColor, const BGradientLinear& fillGradient)
2560 {
2561 	_DrawRoundCornerFrameLeftTop(view, cornerRect, updateRect,
2562 		background, edgeColor, frameColor);
2563 	_DrawRoundCornerBackgroundLeftTop(view, cornerRect, updateRect,
2564 		bevelColor, fillGradient);
2565 }
2566 
2567 
2568 void
2569 BControlLook::_DrawRoundCornerFrameLeftTop(BView* view, BRect& cornerRect,
2570 	const BRect& updateRect, const rgb_color& background,
2571 	const rgb_color& edgeColor, const rgb_color& frameColor)
2572 {
2573 	// constrain clipping region to corner
2574 	BRegion clipping(cornerRect);
2575 	view->ConstrainClippingRegion(&clipping);
2576 
2577 	// background
2578 	view->SetHighColor(background);
2579 	view->FillRect(cornerRect);
2580 
2581 	// outer edge
2582 	BRect ellipseRect(cornerRect);
2583 	ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2584 	ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2585 
2586 	view->SetHighColor(edgeColor);
2587 	view->FillEllipse(ellipseRect);
2588 
2589 	// frame
2590 	ellipseRect.InsetBy(1, 1);
2591 	cornerRect.left++;
2592 	cornerRect.top++;
2593 	view->SetHighColor(frameColor);
2594 	view->FillEllipse(ellipseRect);
2595 
2596 	// prepare for bevel
2597 	cornerRect.left++;
2598 	cornerRect.top++;
2599 }
2600 
2601 
2602 void
2603 BControlLook::_DrawRoundCornerBackgroundLeftTop(BView* view, BRect& cornerRect,
2604 	const BRect& updateRect, const rgb_color& bevelColor,
2605 	const BGradientLinear& fillGradient)
2606 {
2607 	// constrain clipping region to corner
2608 	BRegion clipping(cornerRect);
2609 	view->ConstrainClippingRegion(&clipping);
2610 
2611 	BRect ellipseRect(cornerRect);
2612 	ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2613 	ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2614 
2615 	// bevel
2616 	view->SetHighColor(bevelColor);
2617 	view->FillEllipse(ellipseRect);
2618 
2619 	// gradient
2620 	ellipseRect.InsetBy(1, 1);
2621 	view->FillEllipse(ellipseRect, fillGradient);
2622 }
2623 
2624 
2625 void
2626 BControlLook::_DrawRoundCornerRightTop(BView* view, BRect& cornerRect,
2627 	const BRect& updateRect, const rgb_color& background,
2628 	const rgb_color& edgeTopColor, const rgb_color& edgeRightColor,
2629 	const rgb_color& frameTopColor, const rgb_color& frameRightColor,
2630 	const rgb_color& bevelTopColor, const rgb_color& bevelRightColor,
2631 	const BGradientLinear& fillGradient)
2632 {
2633 	_DrawRoundCornerFrameRightTop(view, cornerRect, updateRect,
2634 		background, edgeTopColor, edgeRightColor, frameTopColor,
2635 		frameRightColor);
2636 	_DrawRoundCornerBackgroundRightTop(view, cornerRect, updateRect,
2637 		bevelTopColor, bevelRightColor, fillGradient);
2638 }
2639 
2640 
2641 void
2642 BControlLook::_DrawRoundCornerFrameRightTop(BView* view, BRect& cornerRect,
2643 	const BRect& updateRect, const rgb_color& background,
2644 	const rgb_color& edgeTopColor, const rgb_color& edgeRightColor,
2645 	const rgb_color& frameTopColor, const rgb_color& frameRightColor)
2646 {
2647 	// constrain clipping region to corner
2648 	BRegion clipping(cornerRect);
2649 	view->ConstrainClippingRegion(&clipping);
2650 
2651 	// background
2652 	view->SetHighColor(background);
2653 	view->FillRect(cornerRect);
2654 
2655 	// outer edge
2656 	BRect ellipseRect(cornerRect);
2657 	ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
2658 	ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2659 
2660 	BGradientLinear gradient;
2661 	gradient.AddColor(edgeTopColor, 0);
2662 	gradient.AddColor(edgeRightColor, 255);
2663 	gradient.SetStart(cornerRect.LeftTop());
2664 	gradient.SetEnd(cornerRect.RightBottom());
2665 	view->FillEllipse(ellipseRect, gradient);
2666 
2667 	// frame
2668 	ellipseRect.InsetBy(1, 1);
2669 	cornerRect.right--;
2670 	cornerRect.top++;
2671 	if (frameTopColor == frameRightColor) {
2672 		view->SetHighColor(frameTopColor);
2673 		view->FillEllipse(ellipseRect);
2674 	} else {
2675 		gradient.SetColor(0, frameTopColor);
2676 		gradient.SetColor(1, frameRightColor);
2677 		gradient.SetStart(cornerRect.LeftTop());
2678 		gradient.SetEnd(cornerRect.RightBottom());
2679 		view->FillEllipse(ellipseRect, gradient);
2680 	}
2681 
2682 	// prepare for bevel
2683 	cornerRect.right--;
2684 	cornerRect.top++;
2685 }
2686 
2687 
2688 void
2689 BControlLook::_DrawRoundCornerBackgroundRightTop(BView* view, BRect& cornerRect,
2690 	const BRect& updateRect, const rgb_color& bevelTopColor,
2691 	const rgb_color& bevelRightColor, const BGradientLinear& fillGradient)
2692 {
2693 	// constrain clipping region to corner
2694 	BRegion clipping(cornerRect);
2695 	view->ConstrainClippingRegion(&clipping);
2696 
2697 	BRect ellipseRect(cornerRect);
2698 	ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
2699 	ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2700 
2701 	// bevel
2702 	BGradientLinear gradient;
2703 	gradient.AddColor(bevelTopColor, 0);
2704 	gradient.AddColor(bevelRightColor, 255);
2705 	gradient.SetStart(cornerRect.LeftTop());
2706 	gradient.SetEnd(cornerRect.RightBottom());
2707 	view->FillEllipse(ellipseRect, gradient);
2708 
2709 	// gradient
2710 	ellipseRect.InsetBy(1, 1);
2711 	view->FillEllipse(ellipseRect, fillGradient);
2712 }
2713 
2714 
2715 void
2716 BControlLook::_DrawRoundCornerLeftBottom(BView* view, BRect& cornerRect,
2717 	const BRect& updateRect, const rgb_color& background,
2718 	const rgb_color& edgeLeftColor, const rgb_color& edgeBottomColor,
2719 	const rgb_color& frameLeftColor, const rgb_color& frameBottomColor,
2720 	const rgb_color& bevelLeftColor, const rgb_color& bevelBottomColor,
2721 	const BGradientLinear& fillGradient)
2722 {
2723 	_DrawRoundCornerFrameLeftBottom(view, cornerRect, updateRect,
2724 		background, edgeLeftColor, edgeBottomColor, frameLeftColor,
2725 		frameBottomColor);
2726 	_DrawRoundCornerBackgroundLeftBottom(view, cornerRect, updateRect,
2727 		bevelLeftColor, bevelBottomColor, fillGradient);
2728 }
2729 
2730 
2731 void
2732 BControlLook::_DrawRoundCornerFrameLeftBottom(BView* view, BRect& cornerRect,
2733 	const BRect& updateRect, const rgb_color& background,
2734 	const rgb_color& edgeLeftColor, const rgb_color& edgeBottomColor,
2735 	const rgb_color& frameLeftColor, const rgb_color& frameBottomColor)
2736 {
2737 	// constrain clipping region to corner
2738 	BRegion clipping(cornerRect);
2739 	view->ConstrainClippingRegion(&clipping);
2740 
2741 	// background
2742 	view->SetHighColor(background);
2743 	view->FillRect(cornerRect);
2744 
2745 	// outer edge
2746 	BRect ellipseRect(cornerRect);
2747 	ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2748 	ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
2749 
2750 	BGradientLinear gradient;
2751 	gradient.AddColor(edgeLeftColor, 0);
2752 	gradient.AddColor(edgeBottomColor, 255);
2753 	gradient.SetStart(cornerRect.LeftTop());
2754 	gradient.SetEnd(cornerRect.RightBottom());
2755 	view->FillEllipse(ellipseRect, gradient);
2756 
2757 	// frame
2758 	ellipseRect.InsetBy(1, 1);
2759 	cornerRect.left++;
2760 	cornerRect.bottom--;
2761 	if (frameLeftColor == frameBottomColor) {
2762 		view->SetHighColor(frameLeftColor);
2763 		view->FillEllipse(ellipseRect);
2764 	} else {
2765 		gradient.SetColor(0, frameLeftColor);
2766 		gradient.SetColor(1, frameBottomColor);
2767 		gradient.SetStart(cornerRect.LeftTop());
2768 		gradient.SetEnd(cornerRect.RightBottom());
2769 		view->FillEllipse(ellipseRect, gradient);
2770 	}
2771 
2772 	// prepare for bevel
2773 	cornerRect.left++;
2774 	cornerRect.bottom--;
2775 }
2776 
2777 
2778 void
2779 BControlLook::_DrawRoundCornerBackgroundLeftBottom(BView* view, BRect& cornerRect,
2780 	const BRect& updateRect, const rgb_color& bevelLeftColor,
2781 	const rgb_color& bevelBottomColor, const BGradientLinear& fillGradient)
2782 {
2783 	// constrain clipping region to corner
2784 	BRegion clipping(cornerRect);
2785 	view->ConstrainClippingRegion(&clipping);
2786 
2787 	BRect ellipseRect(cornerRect);
2788 	ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2789 	ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
2790 
2791 	// bevel
2792 	BGradientLinear gradient;
2793 	gradient.AddColor(bevelLeftColor, 0);
2794 	gradient.AddColor(bevelBottomColor, 255);
2795 	gradient.SetStart(cornerRect.LeftTop());
2796 	gradient.SetEnd(cornerRect.RightBottom());
2797 	view->FillEllipse(ellipseRect, gradient);
2798 
2799 	// gradient
2800 	ellipseRect.InsetBy(1, 1);
2801 	view->FillEllipse(ellipseRect, fillGradient);
2802 
2803 	view->PopState();
2804 }
2805 
2806 
2807 void
2808 BControlLook::_DrawRoundCornerRightBottom(BView* view, BRect& cornerRect,
2809 	const BRect& updateRect, const rgb_color& background,
2810 	const rgb_color& edgeColor, const rgb_color& frameColor,
2811 	const rgb_color& bevelColor, const BGradientLinear& fillGradient)
2812 {
2813 	_DrawRoundCornerFrameRightBottom(view, cornerRect, updateRect,
2814 		background, edgeColor, frameColor);
2815 	_DrawRoundCornerBackgroundRightBottom(view, cornerRect, updateRect,
2816 		bevelColor, fillGradient);
2817 }
2818 
2819 
2820 void
2821 BControlLook::_DrawRoundCornerFrameRightBottom(BView* view, BRect& cornerRect,
2822 	const BRect& updateRect, const rgb_color& background,
2823 	const rgb_color& edgeColor, const rgb_color& frameColor)
2824 {
2825 	// constrain clipping region to corner
2826 	BRegion clipping(cornerRect);
2827 	view->ConstrainClippingRegion(&clipping);
2828 
2829 	// background
2830 	view->SetHighColor(background);
2831 	view->FillRect(cornerRect);
2832 
2833 	// outer edge
2834 	BRect ellipseRect(cornerRect);
2835 	ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
2836 	ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
2837 
2838 	view->SetHighColor(edgeColor);
2839 	view->FillEllipse(ellipseRect);
2840 
2841 	// frame
2842 	ellipseRect.InsetBy(1, 1);
2843 	cornerRect.right--;
2844 	cornerRect.bottom++;
2845 	view->SetHighColor(frameColor);
2846 	view->FillEllipse(ellipseRect);
2847 
2848 	// prepare for bevel
2849 	cornerRect.left++;
2850 	cornerRect.bottom--;
2851 }
2852 
2853 
2854 void
2855 BControlLook::_DrawRoundCornerBackgroundRightBottom(BView* view,
2856 	BRect& cornerRect, const BRect& updateRect, const rgb_color& bevelColor,
2857 	const BGradientLinear& fillGradient)
2858 {
2859 	// constrain clipping region to corner
2860 	BRegion clipping(cornerRect);
2861 	view->ConstrainClippingRegion(&clipping);
2862 
2863 	BRect ellipseRect(cornerRect);
2864 	ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
2865 	ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
2866 
2867 	// bevel
2868 	view->SetHighColor(bevelColor);
2869 	view->FillEllipse(ellipseRect);
2870 
2871 	// gradient
2872 	ellipseRect.InsetBy(1, 1);
2873 	view->FillEllipse(ellipseRect, fillGradient);
2874 }
2875 
2876 
2877 void
2878 BControlLook::_DrawRoundBarCorner(BView* view, BRect& rect,
2879 	const BRect& updateRect,
2880 	const rgb_color& edgeLightColor, const rgb_color& edgeShadowColor,
2881 	const rgb_color& frameLightColor, const rgb_color& frameShadowColor,
2882 	const rgb_color& fillLightColor, const rgb_color& fillShadowColor,
2883 	float leftInset, float topInset, float rightInset, float bottomInset,
2884 	enum orientation orientation)
2885 {
2886 	if (!rect.IsValid() || !rect.Intersects(updateRect))
2887 		return;
2888 
2889 	BGradientLinear gradient;
2890 	gradient.AddColor(edgeShadowColor, 0);
2891 	gradient.AddColor(edgeLightColor, 255);
2892 	gradient.SetStart(rect.LeftTop());
2893 	if (orientation == B_HORIZONTAL)
2894 		gradient.SetEnd(rect.LeftBottom());
2895 	else
2896 		gradient.SetEnd(rect.RightTop());
2897 
2898 	view->FillEllipse(rect, gradient);
2899 
2900 	rect.left += leftInset;
2901 	rect.top += topInset;
2902 	rect.right += rightInset;
2903 	rect.bottom += bottomInset;
2904 
2905 	gradient.MakeEmpty();
2906 	gradient.AddColor(frameShadowColor, 0);
2907 	gradient.AddColor(frameLightColor, 255);
2908 	gradient.SetStart(rect.LeftTop());
2909 	if (orientation == B_HORIZONTAL)
2910 		gradient.SetEnd(rect.LeftBottom());
2911 	else
2912 		gradient.SetEnd(rect.RightTop());
2913 
2914 	view->FillEllipse(rect, gradient);
2915 
2916 	rect.left += leftInset;
2917 	rect.top += topInset;
2918 	rect.right += rightInset;
2919 	rect.bottom += bottomInset;
2920 
2921 	gradient.MakeEmpty();
2922 	gradient.AddColor(fillShadowColor, 0);
2923 	gradient.AddColor(fillLightColor, 255);
2924 	gradient.SetStart(rect.LeftTop());
2925 	if (orientation == B_HORIZONTAL)
2926 		gradient.SetEnd(rect.LeftBottom());
2927 	else
2928 		gradient.SetEnd(rect.RightTop());
2929 
2930 	view->FillEllipse(rect, gradient);
2931 }
2932 
2933 
2934 rgb_color
2935 BControlLook::_EdgeLightColor(const rgb_color& base, float contrast,
2936 	float brightness, uint32 flags)
2937 {
2938 	rgb_color edgeLightColor;
2939 
2940 	if ((flags & B_BLEND_FRAME) != 0) {
2941 		uint8 alpha = uint8(20 * contrast);
2942 		uint32 white = uint8(255 * brightness);
2943 
2944 		edgeLightColor = (rgb_color){ white, white, white, alpha };
2945 	} else {
2946 		// colors
2947 		float tintLight = kEdgeBevelLightTint;
2948 
2949 		if (contrast == 0.0)
2950 			tintLight = B_NO_TINT;
2951 		else if (contrast != 1.0)
2952 			tintLight = B_NO_TINT + (tintLight - B_NO_TINT) * contrast;
2953 
2954 		edgeLightColor = tint_color(base, tintLight);
2955 
2956 		if (brightness < 1.0) {
2957 			edgeLightColor.red = uint8(edgeLightColor.red * brightness);
2958 			edgeLightColor.green = uint8(edgeLightColor.green * brightness);
2959 			edgeLightColor.blue = uint8(edgeLightColor.blue * brightness);
2960 		}
2961 	}
2962 
2963 	return edgeLightColor;
2964 }
2965 
2966 
2967 rgb_color
2968 BControlLook::_EdgeShadowColor(const rgb_color& base, float contrast,
2969 	float brightness, uint32 flags)
2970 {
2971 	rgb_color edgeShadowColor;
2972 
2973 	if ((flags & B_BLEND_FRAME) != 0) {
2974 		uint8 alpha = uint8(20 * contrast);
2975 		edgeShadowColor = (rgb_color){ 0, 0, 0, alpha };
2976 	} else {
2977 		float tintShadow = kEdgeBevelShadowTint;
2978 
2979 		if (contrast == 0.0)
2980 			tintShadow = B_NO_TINT;
2981 		else if (contrast != 1.0)
2982 			tintShadow = B_NO_TINT + (tintShadow - B_NO_TINT) * contrast;
2983 
2984 		edgeShadowColor = tint_color(base, tintShadow);
2985 
2986 		if (brightness < 1.0) {
2987 			edgeShadowColor.red = uint8(edgeShadowColor.red * brightness);
2988 			edgeShadowColor.green = uint8(edgeShadowColor.green * brightness);
2989 			edgeShadowColor.blue = uint8(edgeShadowColor.blue * brightness);
2990 		}
2991 	}
2992 
2993 	return edgeShadowColor;
2994 }
2995 
2996 
2997 rgb_color
2998 BControlLook::_FrameLightColor(const rgb_color& base, uint32 flags)
2999 {
3000 	if ((flags & B_FOCUSED) != 0)
3001 		return ui_color(B_KEYBOARD_NAVIGATION_COLOR);
3002 
3003 	if ((flags & B_ACTIVATED) != 0)
3004 		return _FrameShadowColor(base, flags & ~B_ACTIVATED);
3005 
3006 	rgb_color frameLightColor;
3007 
3008 	if ((flags & B_DISABLED) != 0) {
3009 		// TODO: B_BLEND_FRAME
3010 		frameLightColor = tint_color(base, 1.145);
3011 
3012 		if ((flags & B_DEFAULT_BUTTON) != 0)
3013 			frameLightColor = tint_color(frameLightColor, 1.14);
3014 	} else {
3015 		if ((flags & B_BLEND_FRAME) != 0)
3016 			frameLightColor = (rgb_color){ 0, 0, 0, 75 };
3017 		else
3018 			frameLightColor = tint_color(base, 1.33);
3019 
3020 		if ((flags & B_DEFAULT_BUTTON) != 0)
3021 			frameLightColor = tint_color(frameLightColor, 1.35);
3022 	}
3023 
3024 	return frameLightColor;
3025 }
3026 
3027 
3028 rgb_color
3029 BControlLook::_FrameShadowColor(const rgb_color& base, uint32 flags)
3030 {
3031 	if ((flags & B_FOCUSED) != 0)
3032 		return ui_color(B_KEYBOARD_NAVIGATION_COLOR);
3033 
3034 	if ((flags & B_ACTIVATED) != 0)
3035 		return _FrameLightColor(base, flags & ~B_ACTIVATED);
3036 
3037 	rgb_color frameShadowColor;
3038 
3039 	if ((flags & B_DISABLED) != 0) {
3040 		// TODO: B_BLEND_FRAME
3041 		frameShadowColor = tint_color(base, 1.24);
3042 
3043 		if ((flags & B_DEFAULT_BUTTON) != 0) {
3044 			frameShadowColor = tint_color(base, 1.145);
3045 			frameShadowColor = tint_color(frameShadowColor, 1.12);
3046 		}
3047 	} else {
3048 		if ((flags & B_DEFAULT_BUTTON) != 0) {
3049 			if ((flags & B_BLEND_FRAME) != 0)
3050 				frameShadowColor = (rgb_color){ 0, 0, 0, 75 };
3051 			else
3052 				frameShadowColor = tint_color(base, 1.33);
3053 
3054 			frameShadowColor = tint_color(frameShadowColor, 1.5);
3055 		} else {
3056 			if ((flags & B_BLEND_FRAME) != 0)
3057 				frameShadowColor = (rgb_color){ 0, 0, 0, 95 };
3058 			else
3059 				frameShadowColor = tint_color(base, 1.47);
3060 		}
3061 	}
3062 
3063 	return frameShadowColor;
3064 }
3065 
3066 
3067 rgb_color
3068 BControlLook::_BevelLightColor(const rgb_color& base, uint32 flags)
3069 {
3070 	rgb_color bevelLightColor = tint_color(base, 0.2);
3071 
3072 	if ((flags & B_DISABLED) != 0)
3073 		bevelLightColor = tint_color(base, B_LIGHTEN_1_TINT);
3074 
3075 	if ((flags & B_ACTIVATED) != 0)
3076 		bevelLightColor = tint_color(base, B_DARKEN_1_TINT);
3077 
3078 	return bevelLightColor;
3079 }
3080 
3081 
3082 rgb_color
3083 BControlLook::_BevelShadowColor(const rgb_color& base, uint32 flags)
3084 {
3085 	rgb_color bevelShadowColor = tint_color(base, 1.08);
3086 
3087 	if ((flags & B_DISABLED) != 0)
3088 		bevelShadowColor = base;
3089 
3090 	if ((flags & B_ACTIVATED) != 0)
3091 		bevelShadowColor = tint_color(base, B_DARKEN_1_TINT);
3092 
3093 	return bevelShadowColor;
3094 }
3095 
3096 
3097 void
3098 BControlLook::_FillGradient(BView* view, const BRect& rect,
3099 	const rgb_color& base, float topTint, float bottomTint,
3100 	enum orientation orientation)
3101 {
3102 	BGradientLinear gradient;
3103 	_MakeGradient(gradient, rect, base, topTint, bottomTint, orientation);
3104 	view->FillRect(rect, gradient);
3105 }
3106 
3107 
3108 void
3109 BControlLook::_FillGlossyGradient(BView* view, const BRect& rect,
3110 	const rgb_color& base, float topTint, float middle1Tint,
3111 	float middle2Tint, float bottomTint, enum orientation orientation)
3112 {
3113 	BGradientLinear gradient;
3114 	_MakeGlossyGradient(gradient, rect, base, topTint, middle1Tint,
3115 		middle2Tint, bottomTint, orientation);
3116 	view->FillRect(rect, gradient);
3117 }
3118 
3119 
3120 void
3121 BControlLook::_MakeGradient(BGradientLinear& gradient, const BRect& rect,
3122 	const rgb_color& base, float topTint, float bottomTint,
3123 	enum orientation orientation) const
3124 {
3125 	gradient.AddColor(tint_color(base, topTint), 0);
3126 	gradient.AddColor(tint_color(base, bottomTint), 255);
3127 	gradient.SetStart(rect.LeftTop());
3128 	if (orientation == B_HORIZONTAL)
3129 		gradient.SetEnd(rect.LeftBottom());
3130 	else
3131 		gradient.SetEnd(rect.RightTop());
3132 }
3133 
3134 
3135 void
3136 BControlLook::_MakeGlossyGradient(BGradientLinear& gradient, const BRect& rect,
3137 	const rgb_color& base, float topTint, float middle1Tint,
3138 	float middle2Tint, float bottomTint,
3139 	enum orientation orientation) const
3140 {
3141 	gradient.AddColor(tint_color(base, topTint), 0);
3142 	gradient.AddColor(tint_color(base, middle1Tint), 132);
3143 	gradient.AddColor(tint_color(base, middle2Tint), 136);
3144 	gradient.AddColor(tint_color(base, bottomTint), 255);
3145 	gradient.SetStart(rect.LeftTop());
3146 	if (orientation == B_HORIZONTAL)
3147 		gradient.SetEnd(rect.LeftBottom());
3148 	else
3149 		gradient.SetEnd(rect.RightTop());
3150 }
3151 
3152 
3153 void
3154 BControlLook::_MakeButtonGradient(BGradientLinear& gradient, BRect& rect,
3155 	const rgb_color& base, uint32 flags, enum orientation orientation) const
3156 {
3157 	float topTint = 0.49;
3158 	float middleTint1 = 0.62;
3159 	float middleTint2 = 0.76;
3160 	float bottomTint = 0.90;
3161 
3162 	if ((flags & B_ACTIVATED) != 0) {
3163 		topTint = 1.11;
3164 		bottomTint = 1.08;
3165 	}
3166 
3167 	if ((flags & B_DISABLED) != 0) {
3168 		topTint = (topTint + B_NO_TINT) / 2;
3169 		middleTint1 = (middleTint1 + B_NO_TINT) / 2;
3170 		middleTint2 = (middleTint2 + B_NO_TINT) / 2;
3171 		bottomTint = (bottomTint + B_NO_TINT) / 2;
3172 	} else if ((flags & B_HOVER) != 0) {
3173 		static const float kHoverTintFactor = 0.85;
3174 		topTint *= kHoverTintFactor;
3175 		middleTint1 *= kHoverTintFactor;
3176 		middleTint2 *= kHoverTintFactor;
3177 		bottomTint *= kHoverTintFactor;
3178 	}
3179 
3180 	if ((flags & B_ACTIVATED) != 0) {
3181 		_MakeGradient(gradient, rect, base, topTint, bottomTint, orientation);
3182 	} else {
3183 		_MakeGlossyGradient(gradient, rect, base, topTint, middleTint1,
3184 			middleTint2, bottomTint, orientation);
3185 	}
3186 }
3187 
3188 
3189 
3190 bool
3191 BControlLook::_RadioButtonAndCheckBoxMarkColor(const rgb_color& base,
3192 	rgb_color& color, uint32 flags) const
3193 {
3194 	if ((flags & (B_ACTIVATED | B_CLICKED)) == 0) {
3195 		// no mark to be drawn at all
3196 		return false;
3197 	}
3198 
3199 	color = ui_color(B_CONTROL_MARK_COLOR);
3200 
3201 	float mix = 1.0;
3202 
3203 	if ((flags & B_DISABLED) != 0) {
3204 		// activated, but disabled
3205 		mix = 0.4;
3206 	} else if ((flags & B_CLICKED) != 0) {
3207 		if ((flags & B_ACTIVATED) != 0) {
3208 			// loosing activation
3209 			mix = 0.7;
3210 		} else {
3211 			// becoming activated
3212 			mix = 0.3;
3213 		}
3214 	} else {
3215 		// simply activated
3216 	}
3217 
3218 	color.red = uint8(color.red * mix + base.red * (1.0 - mix));
3219 	color.green = uint8(color.green * mix + base.green * (1.0 - mix));
3220 	color.blue = uint8(color.blue * mix + base.blue * (1.0 - mix));
3221 
3222 	return true;
3223 }
3224 
3225 
3226 // NOTE: May come from a add-on in the future. Initialized in
3227 // InterfaceDefs.cpp
3228 BControlLook* be_control_look = NULL;
3229 
3230 
3231 } // namespace BPrivate
3232