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