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