xref: /haiku/src/kits/interface/ControlLook.cpp (revision f0650dc98fed895fc134a359aab99c27de6a0c6a)
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 <Control.h>
17 #include <GradientLinear.h>
18 #include <LayoutUtils.h>
19 #include <Region.h>
20 #include <Shape.h>
21 #include <String.h>
22 #include <View.h>
23 #include <Window.h>
24 
25 #include "ContainerWindow.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 border, 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 (border == B_NO_BORDER) {
696 		if (scrollCornerFillRect.IsValid()) {
697 			view->SetHighColor(base);
698 			view->FillRect(scrollCornerFillRect);
699 		}
700 		return;
701 	}
702 
703 	bool excludeScrollCorner = border == 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 (border == 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 border, uint32 flags, uint32 borders)
1638 {
1639 	if (border == B_NO_BORDER)
1640 		return;
1641 
1642 	rgb_color scrollbarFrameColor = tint_color(base, B_DARKEN_2_TINT);
1643 	if ((flags & B_FOCUSED) != 0)
1644 		scrollbarFrameColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1645 
1646 	if (border == B_FANCY_BORDER)
1647 		_DrawOuterResessedFrame(view, rect, base, 1.0, 1.0, flags, borders);
1648 
1649 	_DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor,
1650 		scrollbarFrameColor, scrollbarFrameColor, borders);
1651 }
1652 
1653 
1654 void
1655 BControlLook::DrawRaisedBorder(BView* view, BRect& rect,
1656 	const BRect& updateRect, const rgb_color& base, uint32 flags,
1657 	uint32 borders)
1658 {
1659 	rgb_color lightColor;
1660 	rgb_color shadowColor;
1661 
1662 	if ((flags & B_DISABLED) != 0) {
1663 		lightColor = base;
1664 		shadowColor = base;
1665 	} else {
1666 		lightColor = tint_color(base, 0.85);
1667 		shadowColor = tint_color(base, 1.07);
1668 	}
1669 
1670 	_DrawFrame(view, rect, lightColor, lightColor, shadowColor, shadowColor,
1671 		borders);
1672 }
1673 
1674 
1675 void
1676 BControlLook::DrawTextControlBorder(BView* view, BRect& rect,
1677 	const BRect& updateRect, const rgb_color& base, uint32 flags,
1678 	uint32 borders)
1679 {
1680 	if (!rect.Intersects(updateRect))
1681 		return;
1682 
1683 	rgb_color dark1BorderColor;
1684 	rgb_color dark2BorderColor;
1685 	rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1686 	rgb_color invalidColor = ui_color(B_FAILURE_COLOR);
1687 
1688 	if ((flags & B_DISABLED) != 0) {
1689 		_DrawOuterResessedFrame(view, rect, base, 0.0, 1.0, flags, borders);
1690 
1691 		if ((flags & B_BLEND_FRAME) != 0)
1692 			dark1BorderColor = (rgb_color){ 0, 0, 0, 40 };
1693 		else
1694 			dark1BorderColor = tint_color(base, 1.15);
1695 		dark2BorderColor = dark1BorderColor;
1696 	} else if ((flags & B_CLICKED) != 0) {
1697 		dark1BorderColor = tint_color(base, 1.50);
1698 		dark2BorderColor = tint_color(base, 1.49);
1699 
1700 		// BCheckBox uses this to indicate the clicked state...
1701 		_DrawFrame(view, rect,
1702 			dark1BorderColor, dark1BorderColor,
1703 			dark2BorderColor, dark2BorderColor);
1704 
1705 		dark2BorderColor = dark1BorderColor;
1706 	} else {
1707 		_DrawOuterResessedFrame(view, rect, base, 0.6, 1.0, flags, borders);
1708 
1709 		if ((flags & B_BLEND_FRAME) != 0) {
1710 			dark1BorderColor = (rgb_color){ 0, 0, 0, 102 };
1711 			dark2BorderColor = (rgb_color){ 0, 0, 0, 97 };
1712 		} else {
1713 			dark1BorderColor = tint_color(base, 1.40);
1714 			dark2BorderColor = tint_color(base, 1.38);
1715 		}
1716 	}
1717 
1718 	if ((flags & B_DISABLED) == 0 && (flags & B_FOCUSED) != 0) {
1719 		dark1BorderColor = navigationColor;
1720 		dark2BorderColor = navigationColor;
1721 	}
1722 
1723 	if ((flags & B_DISABLED) == 0 && (flags & B_INVALID) != 0) {
1724 		dark1BorderColor = invalidColor;
1725 		dark2BorderColor = invalidColor;
1726 	}
1727 
1728 	if ((flags & B_BLEND_FRAME) != 0) {
1729 		drawing_mode oldMode = view->DrawingMode();
1730 		view->SetDrawingMode(B_OP_ALPHA);
1731 
1732 		_DrawFrame(view, rect,
1733 			dark1BorderColor, dark1BorderColor,
1734 			dark2BorderColor, dark2BorderColor, borders);
1735 
1736 		view->SetDrawingMode(oldMode);
1737 	} else {
1738 		_DrawFrame(view, rect,
1739 			dark1BorderColor, dark1BorderColor,
1740 			dark2BorderColor, dark2BorderColor, borders);
1741 	}
1742 }
1743 
1744 
1745 void
1746 BControlLook::DrawGroupFrame(BView* view, BRect& rect, const BRect& updateRect,
1747 	const rgb_color& base, uint32 borders)
1748 {
1749 	rgb_color frameColor = tint_color(base, 1.30);
1750 	rgb_color bevelLight = tint_color(base, 0.8);
1751 	rgb_color bevelShadow = tint_color(base, 1.03);
1752 
1753 	_DrawFrame(view, rect, bevelShadow, bevelShadow, bevelLight, bevelLight,
1754 		borders);
1755 
1756 	_DrawFrame(view, rect, frameColor, frameColor, frameColor, frameColor,
1757 		borders);
1758 
1759 	_DrawFrame(view, rect, bevelLight, bevelLight, bevelShadow, bevelShadow,
1760 		borders);
1761 }
1762 
1763 
1764 void
1765 BControlLook::DrawLabel(BView* view, const char* label, BRect rect,
1766 	const BRect& updateRect, const rgb_color& base, uint32 flags,
1767 	const rgb_color* textColor)
1768 {
1769 	DrawLabel(view, label, NULL, rect, updateRect, base, flags,
1770 		DefaultLabelAlignment(), textColor);
1771 }
1772 
1773 
1774 void
1775 BControlLook::DrawLabel(BView* view, const char* label, BRect rect,
1776 	const BRect& updateRect, const rgb_color& base, uint32 flags,
1777 	const BAlignment& alignment, const rgb_color* textColor)
1778 {
1779 	DrawLabel(view, label, NULL, rect, updateRect, base, flags, alignment,
1780 			textColor);
1781 }
1782 
1783 
1784 void
1785 BControlLook::DrawLabel(BView* view, const char* label, const rgb_color& base,
1786 	uint32 flags, const BPoint& where, const rgb_color* textColor)
1787 {
1788 	// setup the text color
1789 
1790 	BWindow* window = view->Window();
1791 	bool isDesktop = window
1792 		&& window->Feel() == kPrivateDesktopWindowFeel
1793 		&& window->Look() == kPrivateDesktopWindowLook
1794 		&& view->Parent()
1795 		&& view->Parent()->Parent() == NULL
1796 		&& (flags & B_IGNORE_OUTLINE) == 0;
1797 
1798 	rgb_color	low;
1799 	rgb_color	color;
1800 	rgb_color	glowColor;
1801 
1802 	if (textColor != NULL)
1803 		glowColor = *textColor;
1804 	else if ((flags & B_IS_CONTROL) != 0)
1805 		glowColor = ui_color(B_CONTROL_TEXT_COLOR);
1806 	else
1807 		glowColor = ui_color(B_PANEL_TEXT_COLOR);
1808 
1809 	color = glowColor;
1810 
1811 	if (isDesktop)
1812 		low = view->Parent()->ViewColor();
1813 	else
1814 		low = base;
1815 
1816 	if ((flags & B_DISABLED) != 0) {
1817 		color.red = (uint8)(((int32)low.red + color.red + 1) / 2);
1818 		color.green = (uint8)(((int32)low.green + color.green + 1) / 2);
1819 		color.blue = (uint8)(((int32)low.blue + color.blue + 1) / 2);
1820 	}
1821 
1822 	drawing_mode oldMode = view->DrawingMode();
1823 
1824 	if (isDesktop) {
1825 		// drawing occurs on the desktop
1826 		if (fCachedWorkspace != current_workspace()) {
1827 			int8 indice = 0;
1828 			int32 mask;
1829 			bool tmpOutline;
1830 			while (fBackgroundInfo.FindInt32("be:bgndimginfoworkspaces",
1831 					indice, &mask) == B_OK
1832 				&& fBackgroundInfo.FindBool("be:bgndimginfoerasetext",
1833 					indice, &tmpOutline) == B_OK) {
1834 
1835 				if (((1 << current_workspace()) & mask) != 0) {
1836 					fCachedOutline = tmpOutline;
1837 					fCachedWorkspace = current_workspace();
1838 					break;
1839 				}
1840 				indice++;
1841 			}
1842 		}
1843 
1844 		if (fCachedOutline) {
1845 			BFont font;
1846 			view->GetFont(&font);
1847 
1848 			view->SetDrawingMode(B_OP_ALPHA);
1849 			view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
1850 			// Draw glow or outline
1851 			if (glowColor.Brightness() > 128) {
1852 				font.SetFalseBoldWidth(2.0);
1853 				view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1854 
1855 				glowColor.alpha = 30;
1856 				view->SetHighColor(glowColor);
1857 				view->DrawString(label, where);
1858 
1859 				font.SetFalseBoldWidth(1.0);
1860 				view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1861 
1862 				glowColor.alpha = 65;
1863 				view->SetHighColor(glowColor);
1864 				view->DrawString(label, where);
1865 
1866 				font.SetFalseBoldWidth(0.0);
1867 				view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1868 			} else {
1869 				font.SetFalseBoldWidth(1.0);
1870 				view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1871 
1872 				glowColor.alpha = 30;
1873 				view->SetHighColor(glowColor);
1874 				view->DrawString(label, where);
1875 
1876 				font.SetFalseBoldWidth(0.0);
1877 				view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1878 
1879 				glowColor.alpha = 200;
1880 				view->SetHighColor(glowColor);
1881 				view->DrawString(label, BPoint(where.x + 1, where.y + 1));
1882 			}
1883 		}
1884 	}
1885 
1886 	view->SetHighColor(color);
1887 	view->SetDrawingMode(B_OP_OVER);
1888 	view->DrawString(label, where);
1889 	view->SetDrawingMode(oldMode);
1890 }
1891 
1892 
1893 void
1894 BControlLook::DrawLabel(BView* view, const char* label, const BBitmap* icon,
1895 	BRect rect, const BRect& updateRect, const rgb_color& base, uint32 flags,
1896 	const rgb_color* textColor)
1897 {
1898 	DrawLabel(view, label, icon, rect, updateRect, base, flags,
1899 		DefaultLabelAlignment(), textColor);
1900 }
1901 
1902 
1903 void
1904 BControlLook::DrawLabel(BView* view, const char* label, const BBitmap* icon,
1905 	BRect rect, const BRect& updateRect, const rgb_color& base, uint32 flags,
1906 	const BAlignment& alignment, const rgb_color* textColor)
1907 {
1908 	if (!rect.Intersects(updateRect))
1909 		return;
1910 
1911 	if (label == NULL && icon == NULL)
1912 		return;
1913 
1914 	if (label == NULL) {
1915 		// icon only
1916 		BRect alignedRect = BLayoutUtils::AlignInFrame(rect,
1917 			icon->Bounds().Size(), alignment);
1918 		drawing_mode oldMode = view->DrawingMode();
1919 		view->SetDrawingMode(B_OP_OVER);
1920 		view->DrawBitmap(icon, alignedRect.LeftTop());
1921 		view->SetDrawingMode(oldMode);
1922 		return;
1923 	}
1924 
1925 	// label, possibly with icon
1926 	float availableWidth = rect.Width() + 1;
1927 	float width = 0;
1928 	float textOffset = 0;
1929 	float height = 0;
1930 
1931 	if (icon != NULL) {
1932 		width = icon->Bounds().Width() + DefaultLabelSpacing() + 1;
1933 		height = icon->Bounds().Height() + 1;
1934 		textOffset = width;
1935 		availableWidth -= textOffset;
1936 	}
1937 
1938 	// truncate the label if necessary and get the width and height
1939 	BString truncatedLabel(label);
1940 
1941 	BFont font;
1942 	view->GetFont(&font);
1943 
1944 	font.TruncateString(&truncatedLabel, B_TRUNCATE_END, availableWidth);
1945 	width += ceilf(font.StringWidth(truncatedLabel.String()));
1946 
1947 	font_height fontHeight;
1948 	font.GetHeight(&fontHeight);
1949 	float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
1950 	height = std::max(height, textHeight);
1951 
1952 	// handle alignment
1953 	BRect alignedRect(BLayoutUtils::AlignOnRect(rect,
1954 		BSize(width - 1, height - 1), alignment));
1955 
1956 	if (icon != NULL) {
1957 		BPoint location(alignedRect.LeftTop());
1958 		if (icon->Bounds().Height() + 1 < height)
1959 			location.y += ceilf((height - icon->Bounds().Height() - 1) / 2);
1960 
1961 		drawing_mode oldMode = view->DrawingMode();
1962 		view->SetDrawingMode(B_OP_OVER);
1963 		view->DrawBitmap(icon, location);
1964 		view->SetDrawingMode(oldMode);
1965 	}
1966 
1967 	BPoint location(alignedRect.left + textOffset,
1968 		alignedRect.top + ceilf(fontHeight.ascent));
1969 	if (textHeight < height)
1970 		location.y += ceilf((height - textHeight) / 2);
1971 
1972 	DrawLabel(view, truncatedLabel.String(), base, flags, location, textColor);
1973 }
1974 
1975 
1976 void
1977 BControlLook::GetFrameInsets(frame_type frameType, uint32 flags, float& _left,
1978 	float& _top, float& _right, float& _bottom)
1979 {
1980 	// All frames have the same inset on each side.
1981 	float inset = 0;
1982 
1983 	switch (frameType) {
1984 		case B_BUTTON_FRAME:
1985 			inset = (flags & B_DEFAULT_BUTTON) != 0 ? 5 : 2;
1986 			break;
1987 		case B_GROUP_FRAME:
1988 		case B_MENU_FIELD_FRAME:
1989 			inset = 3;
1990 			break;
1991 		case B_SCROLL_VIEW_FRAME:
1992 		case B_TEXT_CONTROL_FRAME:
1993 			inset = 2;
1994 			break;
1995 	}
1996 
1997 	_left = inset;
1998 	_top = inset;
1999 	_right = inset;
2000 	_bottom = inset;
2001 }
2002 
2003 
2004 void
2005 BControlLook::GetBackgroundInsets(background_type backgroundType,
2006 	uint32 flags, float& _left, float& _top, float& _right, float& _bottom)
2007 {
2008 	// Most backgrounds have the same inset on each side.
2009 	float inset = 0;
2010 
2011 	switch (backgroundType) {
2012 		case B_BUTTON_BACKGROUND:
2013 		case B_MENU_BACKGROUND:
2014 		case B_MENU_BAR_BACKGROUND:
2015 		case B_MENU_FIELD_BACKGROUND:
2016 		case B_MENU_ITEM_BACKGROUND:
2017 			inset = 1;
2018 			break;
2019 		case B_BUTTON_WITH_POP_UP_BACKGROUND:
2020 			_left = 1;
2021 			_top = 1;
2022 			_right = 1 + kButtonPopUpIndicatorWidth;
2023 			_bottom = 1;
2024 			return;
2025 		case B_HORIZONTAL_SCROLL_BAR_BACKGROUND:
2026 			_left = 2;
2027 			_top = 0;
2028 			_right = 1;
2029 			_bottom = 0;
2030 			return;
2031 		case B_VERTICAL_SCROLL_BAR_BACKGROUND:
2032 			_left = 0;
2033 			_top = 2;
2034 			_right = 0;
2035 			_bottom = 1;
2036 			return;
2037 	}
2038 
2039 	_left = inset;
2040 	_top = inset;
2041 	_right = inset;
2042 	_bottom = inset;
2043 }
2044 
2045 
2046 void
2047 BControlLook::GetInsets(frame_type frameType, background_type backgroundType,
2048 	uint32 flags, float& _left, float& _top, float& _right, float& _bottom)
2049 {
2050 	GetFrameInsets(frameType, flags, _left, _top, _right, _bottom);
2051 
2052 	float left, top, right, bottom;
2053 	GetBackgroundInsets(backgroundType, flags, left, top, right, bottom);
2054 
2055 	_left += left;
2056 	_top += top;
2057 	_right += right;
2058 	_bottom += bottom;
2059 }
2060 
2061 
2062 void
2063 BControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect,
2064 	const BRect& updateRect, const rgb_color& base, uint32 flags,
2065 	uint32 borders, orientation orientation)
2066 {
2067 	_DrawButtonBackground(view, rect, updateRect, 0.0f, 0.0f, 0.0f, 0.0f,
2068 		base, true, flags, borders, orientation);
2069 }
2070 
2071 
2072 void
2073 BControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect,
2074 	const BRect& updateRect, float radius, const rgb_color& base, uint32 flags,
2075 	uint32 borders, orientation orientation)
2076 {
2077 	_DrawButtonBackground(view, rect, updateRect, radius, radius, radius,
2078 		radius, base, true, flags, borders, orientation);
2079 }
2080 
2081 
2082 void
2083 BControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect,
2084 	const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2085 	float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2086 	uint32 flags, uint32 borders, orientation orientation)
2087 {
2088 	_DrawButtonBackground(view, rect, updateRect, leftTopRadius,
2089 		rightTopRadius, leftBottomRadius, rightBottomRadius, base, true, flags,
2090 		borders, orientation);
2091 }
2092 
2093 
2094 void
2095 BControlLook::SetBackgroundInfo(const BMessage& backgroundInfo)
2096 {
2097 	fBackgroundInfo = backgroundInfo;
2098 	fCachedWorkspace = -1;
2099 }
2100 
2101 
2102 // #pragma mark -
2103 
2104 
2105 void
2106 BControlLook::_DrawButtonFrame(BView* view, BRect& rect,
2107 	const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2108 	float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2109 	const rgb_color& background, float contrast, float brightness,
2110 	uint32 flags, uint32 borders)
2111 {
2112 	if (!rect.IsValid() || !rect.Intersects(updateRect))
2113 		return;
2114 
2115 	// save the clipping constraints of the view
2116 	view->PushState();
2117 
2118 	// set clipping constraints to updateRect
2119 	BRegion clipping(updateRect);
2120 	view->ConstrainClippingRegion(&clipping);
2121 
2122 	// If the button is flat and neither activated nor otherwise highlighted
2123 	// (mouse hovering or focussed), draw it flat.
2124 	if ((flags & B_FLAT) != 0
2125 		&& (flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED)) == 0
2126 		&& ((flags & (B_HOVER | B_FOCUSED)) == 0
2127 			|| (flags & B_DISABLED) != 0)) {
2128 		_DrawFrame(view, rect, background, background, background,
2129 			background, borders);
2130 		_DrawFrame(view, rect, background, background, background,
2131 			background, borders);
2132 		view->PopState();
2133 		return;
2134 	}
2135 
2136 	// outer edge colors
2137 	rgb_color edgeLightColor;
2138 	rgb_color edgeShadowColor;
2139 
2140 	// default button frame color
2141 	// TODO: B_BLEND_FRAME
2142 	float defaultIndicatorTint = 1.2;
2143 	if ((flags & B_DISABLED) != 0)
2144 		defaultIndicatorTint = (B_NO_TINT + defaultIndicatorTint) / 2;
2145 
2146 	rgb_color defaultIndicatorColor = tint_color(base, defaultIndicatorTint);
2147 	rgb_color cornerBgColor;
2148 
2149 	drawing_mode oldMode = view->DrawingMode();
2150 
2151 	if ((flags & B_DEFAULT_BUTTON) != 0) {
2152 		defaultIndicatorColor = ui_color(B_CONTROL_HIGHLIGHT_COLOR);
2153 		cornerBgColor = defaultIndicatorColor;
2154 		edgeLightColor = _EdgeLightColor(defaultIndicatorColor,
2155 			contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8),
2156 			brightness * ((flags & B_DISABLED) != 0 ? 1.0 : 0.9), flags);
2157 		edgeShadowColor = _EdgeShadowColor(defaultIndicatorColor,
2158 			contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8),
2159 			brightness * ((flags & B_DISABLED) != 0 ? 1.0 : 0.9), flags);
2160 
2161 		// draw default button indicator
2162 		view->SetHighColor(background);
2163 		view->FillRect(rect);
2164 		view->SetHighColor(base);
2165 		view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius);
2166 		rect.InsetBy(1, 1);
2167 
2168 		view->SetHighColor(defaultIndicatorColor);
2169 		view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius);
2170 		rect.InsetBy(1, 1);
2171 
2172 		view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius);
2173 		rect.InsetBy(1, 1);
2174 	} else {
2175 		cornerBgColor = background;
2176 		if ((flags & B_BLEND_FRAME) != 0) {
2177 			// set the background color to transparent for the case
2178 			// that we are on the desktop
2179 			cornerBgColor.alpha = 0;
2180 			view->SetDrawingMode(B_OP_ALPHA);
2181 		}
2182 
2183 		edgeLightColor = _EdgeLightColor(background,
2184 			contrast * ((flags & B_DISABLED) != 0 ? 0.0 : 1.0),
2185 			brightness * 1.0, flags);
2186 		edgeShadowColor = _EdgeShadowColor(background,
2187 			contrast * (flags & B_DISABLED) != 0 ? 0.0 : 1.0,
2188 			brightness * 1.0, flags);
2189 	}
2190 
2191 	// frame colors
2192 	rgb_color frameLightColor  = _FrameLightColor(base, flags);
2193 	rgb_color frameShadowColor = _FrameShadowColor(base, flags);
2194 
2195 	// rounded corners
2196 
2197 	if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0
2198 		&& leftTopRadius > 0) {
2199 		// draw left top rounded corner
2200 		BRect leftTopCorner(floorf(rect.left), floorf(rect.top),
2201 			floorf(rect.left + leftTopRadius),
2202 			floorf(rect.top + leftTopRadius));
2203 		clipping.Exclude(leftTopCorner);
2204 		_DrawRoundCornerFrameLeftTop(view, leftTopCorner, updateRect,
2205 			cornerBgColor, edgeShadowColor, frameLightColor);
2206 	}
2207 
2208 	if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0
2209 		&& rightTopRadius > 0) {
2210 		// draw right top rounded corner
2211 		BRect rightTopCorner(floorf(rect.right - rightTopRadius),
2212 			floorf(rect.top), floorf(rect.right),
2213 			floorf(rect.top + rightTopRadius));
2214 		clipping.Exclude(rightTopCorner);
2215 		_DrawRoundCornerFrameRightTop(view, rightTopCorner, updateRect,
2216 			cornerBgColor, edgeShadowColor, edgeLightColor,
2217 			frameLightColor, frameShadowColor);
2218 	}
2219 
2220 	if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2221 		&& leftBottomRadius > 0) {
2222 		// draw left bottom rounded corner
2223 		BRect leftBottomCorner(floorf(rect.left),
2224 			floorf(rect.bottom - leftBottomRadius),
2225 			floorf(rect.left + leftBottomRadius), floorf(rect.bottom));
2226 		clipping.Exclude(leftBottomCorner);
2227 		_DrawRoundCornerFrameLeftBottom(view, leftBottomCorner, updateRect,
2228 			cornerBgColor, edgeShadowColor, edgeLightColor,
2229 			frameLightColor, frameShadowColor);
2230 	}
2231 
2232 	if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2233 		&& rightBottomRadius > 0) {
2234 		// draw right bottom rounded corner
2235 		BRect rightBottomCorner(floorf(rect.right - rightBottomRadius),
2236 			floorf(rect.bottom - rightBottomRadius), floorf(rect.right),
2237 			floorf(rect.bottom));
2238 		clipping.Exclude(rightBottomCorner);
2239 		_DrawRoundCornerFrameRightBottom(view, rightBottomCorner,
2240 			updateRect, cornerBgColor, edgeLightColor, frameShadowColor);
2241 	}
2242 
2243 	// clip out the corners
2244 	view->ConstrainClippingRegion(&clipping);
2245 
2246 	// draw outer edge
2247 	if ((flags & B_DEFAULT_BUTTON) != 0) {
2248 		_DrawOuterResessedFrame(view, rect, defaultIndicatorColor,
2249 			contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8),
2250 			brightness * ((flags & B_DISABLED) != 0 ? 1.0 : 0.9),
2251 			flags, borders);
2252 	} else {
2253 		_DrawOuterResessedFrame(view, rect, background,
2254 			contrast * ((flags & B_DISABLED) != 0 ? 0.0 : 1.0),
2255 			brightness * 1.0, flags, borders);
2256 	}
2257 
2258 	view->SetDrawingMode(oldMode);
2259 
2260 	// draw frame
2261 	if ((flags & B_BLEND_FRAME) != 0) {
2262 		drawing_mode oldDrawingMode = view->DrawingMode();
2263 		view->SetDrawingMode(B_OP_ALPHA);
2264 
2265 		_DrawFrame(view, rect, frameLightColor, frameLightColor,
2266 			frameShadowColor, frameShadowColor, borders);
2267 
2268 		view->SetDrawingMode(oldDrawingMode);
2269 	} else {
2270 		_DrawFrame(view, rect, frameLightColor, frameLightColor,
2271 			frameShadowColor, frameShadowColor, borders);
2272 	}
2273 
2274 	// restore the clipping constraints of the view
2275 	view->PopState();
2276 }
2277 
2278 
2279 void
2280 BControlLook::_DrawOuterResessedFrame(BView* view, BRect& rect,
2281 	const rgb_color& base, float contrast, float brightness, uint32 flags,
2282 	uint32 borders)
2283 {
2284 	rgb_color edgeLightColor = _EdgeLightColor(base, contrast,
2285 		brightness, flags);
2286 	rgb_color edgeShadowColor = _EdgeShadowColor(base, contrast,
2287 		brightness, flags);
2288 
2289 	if ((flags & B_BLEND_FRAME) != 0) {
2290 		// assumes the background has already been painted
2291 		drawing_mode oldDrawingMode = view->DrawingMode();
2292 		view->SetDrawingMode(B_OP_ALPHA);
2293 
2294 		_DrawFrame(view, rect, edgeShadowColor, edgeShadowColor,
2295 			edgeLightColor, edgeLightColor, borders);
2296 
2297 		view->SetDrawingMode(oldDrawingMode);
2298 	} else {
2299 		_DrawFrame(view, rect, edgeShadowColor, edgeShadowColor,
2300 			edgeLightColor, edgeLightColor, borders);
2301 	}
2302 }
2303 
2304 
2305 void
2306 BControlLook::_DrawFrame(BView* view, BRect& rect, const rgb_color& left,
2307 	const rgb_color& top, const rgb_color& right, const rgb_color& bottom,
2308 	uint32 borders)
2309 {
2310 	view->BeginLineArray(4);
2311 
2312 	if (borders & B_LEFT_BORDER) {
2313 		view->AddLine(
2314 			BPoint(rect.left, rect.bottom),
2315 			BPoint(rect.left, rect.top), left);
2316 		rect.left++;
2317 	}
2318 	if (borders & B_TOP_BORDER) {
2319 		view->AddLine(
2320 			BPoint(rect.left, rect.top),
2321 			BPoint(rect.right, rect.top), top);
2322 		rect.top++;
2323 	}
2324 	if (borders & B_RIGHT_BORDER) {
2325 		view->AddLine(
2326 			BPoint(rect.right, rect.top),
2327 			BPoint(rect.right, rect.bottom), right);
2328 		rect.right--;
2329 	}
2330 	if (borders & B_BOTTOM_BORDER) {
2331 		view->AddLine(
2332 			BPoint(rect.left, rect.bottom),
2333 			BPoint(rect.right, rect.bottom), bottom);
2334 		rect.bottom--;
2335 	}
2336 
2337 	view->EndLineArray();
2338 }
2339 
2340 
2341 void
2342 BControlLook::_DrawFrame(BView* view, BRect& rect, const rgb_color& left,
2343 	const rgb_color& top, const rgb_color& right, const rgb_color& bottom,
2344 	const rgb_color& rightTop, const rgb_color& leftBottom, uint32 borders)
2345 {
2346 	view->BeginLineArray(6);
2347 
2348 	if (borders & B_TOP_BORDER) {
2349 		if (borders & B_RIGHT_BORDER) {
2350 			view->AddLine(
2351 				BPoint(rect.left, rect.top),
2352 				BPoint(rect.right - 1, rect.top), top);
2353 			view->AddLine(
2354 				BPoint(rect.right, rect.top),
2355 				BPoint(rect.right, rect.top), rightTop);
2356 		} else {
2357 			view->AddLine(
2358 				BPoint(rect.left, rect.top),
2359 				BPoint(rect.right, rect.top), top);
2360 		}
2361 		rect.top++;
2362 	}
2363 
2364 	if (borders & B_LEFT_BORDER) {
2365 		view->AddLine(
2366 			BPoint(rect.left, rect.top),
2367 			BPoint(rect.left, rect.bottom - 1), left);
2368 		view->AddLine(
2369 			BPoint(rect.left, rect.bottom),
2370 			BPoint(rect.left, rect.bottom), leftBottom);
2371 		rect.left++;
2372 	}
2373 
2374 	if (borders & B_BOTTOM_BORDER) {
2375 		view->AddLine(
2376 			BPoint(rect.left, rect.bottom),
2377 			BPoint(rect.right, rect.bottom), bottom);
2378 		rect.bottom--;
2379 	}
2380 
2381 	if (borders & B_RIGHT_BORDER) {
2382 		view->AddLine(
2383 			BPoint(rect.right, rect.bottom),
2384 			BPoint(rect.right, rect.top), right);
2385 		rect.right--;
2386 	}
2387 
2388 	view->EndLineArray();
2389 }
2390 
2391 
2392 void
2393 BControlLook::_DrawButtonBackground(BView* view, BRect& rect,
2394 	const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2395 	float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2396 	bool popupIndicator, uint32 flags, uint32 borders, orientation orientation)
2397 {
2398 	if (!rect.IsValid() || !rect.Intersects(updateRect))
2399 		return;
2400 
2401 	// save the clipping constraints of the view
2402 	view->PushState();
2403 
2404 	// set clipping constraints to updateRect
2405 	BRegion clipping(updateRect);
2406 	view->ConstrainClippingRegion(&clipping);
2407 
2408 	// If the button is flat and neither activated nor otherwise highlighted
2409 	// (mouse hovering or focussed), draw it flat.
2410 	if ((flags & B_FLAT) != 0
2411 		&& (flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED)) == 0
2412 		&& ((flags & (B_HOVER | B_FOCUSED)) == 0
2413 			|| (flags & B_DISABLED) != 0)) {
2414 		_DrawFlatButtonBackground(view, rect, updateRect, base, popupIndicator,
2415 			flags, borders, orientation);
2416 	} else {
2417 		_DrawNonFlatButtonBackground(view, rect, updateRect, clipping,
2418 			leftTopRadius, rightTopRadius, leftBottomRadius, rightBottomRadius,
2419 			base, popupIndicator, flags, borders, orientation);
2420 	}
2421 
2422 	// restore the clipping constraints of the view
2423 	view->PopState();
2424 }
2425 
2426 
2427 void
2428 BControlLook::_DrawFlatButtonBackground(BView* view, BRect& rect,
2429 	const BRect& updateRect, const rgb_color& base, bool popupIndicator,
2430 	uint32 flags, uint32 borders, orientation orientation)
2431 {
2432 	_DrawFrame(view, rect, base, base, base, base, borders);
2433 		// Not an actual frame, but the method insets our rect as needed.
2434 
2435 	view->SetHighColor(base);
2436 	view->FillRect(rect);
2437 
2438 	if (popupIndicator) {
2439 		BRect indicatorRect(rect);
2440 		rect.right -= kButtonPopUpIndicatorWidth;
2441 		indicatorRect.left = rect.right + 3;
2442 			// 2 pixels for the separator
2443 
2444 		view->SetHighColor(base);
2445 		view->FillRect(indicatorRect);
2446 
2447 		_DrawPopUpMarker(view, indicatorRect, base, flags);
2448 	}
2449 }
2450 
2451 
2452 void
2453 BControlLook::_DrawNonFlatButtonBackground(BView* view, BRect& rect,
2454 	const BRect& updateRect, BRegion& clipping, float leftTopRadius,
2455 	float rightTopRadius, float leftBottomRadius, float rightBottomRadius,
2456 	const rgb_color& base, bool popupIndicator, uint32 flags, uint32 borders,
2457 	orientation orientation)
2458 {
2459 	// inner bevel colors
2460 	rgb_color bevelLightColor  = _BevelLightColor(base, flags);
2461 	rgb_color bevelShadowColor = _BevelShadowColor(base, flags);
2462 
2463 	// button background color
2464 	rgb_color buttonBgColor;
2465 	if ((flags & B_DISABLED) != 0)
2466 		buttonBgColor = tint_color(base, 0.7);
2467 	else
2468 		buttonBgColor = tint_color(base, B_LIGHTEN_1_TINT);
2469 
2470 	// surface top gradient
2471 	BGradientLinear fillGradient;
2472 	_MakeButtonGradient(fillGradient, rect, base, flags, orientation);
2473 
2474 	// rounded corners
2475 
2476 	if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0
2477 		&& leftTopRadius > 0) {
2478 		// draw left top rounded corner
2479 		BRect leftTopCorner(floorf(rect.left), floorf(rect.top),
2480 			floorf(rect.left + leftTopRadius - 2.0),
2481 			floorf(rect.top + leftTopRadius - 2.0));
2482 		clipping.Exclude(leftTopCorner);
2483 		_DrawRoundCornerBackgroundLeftTop(view, leftTopCorner, updateRect,
2484 			bevelLightColor, fillGradient);
2485 	}
2486 
2487 	if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0
2488 		&& rightTopRadius > 0) {
2489 		// draw right top rounded corner
2490 		BRect rightTopCorner(floorf(rect.right - rightTopRadius + 2.0),
2491 			floorf(rect.top), floorf(rect.right),
2492 			floorf(rect.top + rightTopRadius - 2.0));
2493 		clipping.Exclude(rightTopCorner);
2494 		_DrawRoundCornerBackgroundRightTop(view, rightTopCorner,
2495 			updateRect, bevelLightColor, bevelShadowColor, fillGradient);
2496 	}
2497 
2498 	if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2499 		&& leftBottomRadius > 0) {
2500 		// draw left bottom rounded corner
2501 		BRect leftBottomCorner(floorf(rect.left),
2502 			floorf(rect.bottom - leftBottomRadius + 2.0),
2503 			floorf(rect.left + leftBottomRadius - 2.0),
2504 			floorf(rect.bottom));
2505 		clipping.Exclude(leftBottomCorner);
2506 		_DrawRoundCornerBackgroundLeftBottom(view, leftBottomCorner,
2507 			updateRect, bevelLightColor, bevelShadowColor, fillGradient);
2508 	}
2509 
2510 	if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2511 		&& rightBottomRadius > 0) {
2512 		// draw right bottom rounded corner
2513 		BRect rightBottomCorner(floorf(rect.right - rightBottomRadius + 2.0),
2514 			floorf(rect.bottom - rightBottomRadius + 2.0), floorf(rect.right),
2515 			floorf(rect.bottom));
2516 		clipping.Exclude(rightBottomCorner);
2517 		_DrawRoundCornerBackgroundRightBottom(view, rightBottomCorner,
2518 			updateRect, bevelShadowColor, fillGradient);
2519 	}
2520 
2521 	// clip out the corners
2522 	view->ConstrainClippingRegion(&clipping);
2523 
2524 	// draw inner bevel
2525 
2526 	if ((flags & B_ACTIVATED) != 0) {
2527 		view->BeginLineArray(4);
2528 
2529 		// shadow along left/top borders
2530 		if (borders & B_LEFT_BORDER) {
2531 			view->AddLine(BPoint(rect.left, rect.top),
2532 				BPoint(rect.left, rect.bottom), bevelLightColor);
2533 			rect.left++;
2534 		}
2535 		if (borders & B_TOP_BORDER) {
2536 			view->AddLine(BPoint(rect.left, rect.top),
2537 				BPoint(rect.right, rect.top), bevelLightColor);
2538 			rect.top++;
2539 		}
2540 
2541 		// softer shadow along left/top borders
2542 		if (borders & B_LEFT_BORDER) {
2543 			view->AddLine(BPoint(rect.left, rect.top),
2544 				BPoint(rect.left, rect.bottom), bevelShadowColor);
2545 			rect.left++;
2546 		}
2547 		if (borders & B_TOP_BORDER) {
2548 			view->AddLine(BPoint(rect.left, rect.top),
2549 				BPoint(rect.right, rect.top), bevelShadowColor);
2550 			rect.top++;
2551 		}
2552 
2553 		view->EndLineArray();
2554 	} else {
2555 		_DrawFrame(view, rect,
2556 			bevelLightColor, bevelLightColor,
2557 			bevelShadowColor, bevelShadowColor,
2558 			buttonBgColor, buttonBgColor, borders);
2559 	}
2560 
2561 	if (popupIndicator) {
2562 		BRect indicatorRect(rect);
2563 		rect.right -= kButtonPopUpIndicatorWidth;
2564 		indicatorRect.left = rect.right + 3;
2565 			// 2 pixels for the separator
2566 
2567 		// Even when depressed we want the pop-up indicator background and
2568 		// separator to cover the area up to the top.
2569 		if ((flags & B_ACTIVATED) != 0)
2570 			indicatorRect.top--;
2571 
2572 		// draw the separator
2573 		rgb_color separatorBaseColor = base;
2574 		if ((flags & B_ACTIVATED) != 0)
2575 			separatorBaseColor = tint_color(base, B_DARKEN_1_TINT);
2576 
2577 		rgb_color separatorLightColor = _EdgeLightColor(separatorBaseColor,
2578 			(flags & B_DISABLED) != 0 ? 0.7 : 1.0, 1.0, flags);
2579 		rgb_color separatorShadowColor = _EdgeShadowColor(separatorBaseColor,
2580 			(flags & B_DISABLED) != 0 ? 0.7 : 1.0, 1.0, flags);
2581 
2582 		view->BeginLineArray(2);
2583 
2584 		view->AddLine(BPoint(indicatorRect.left - 2, indicatorRect.top),
2585 			BPoint(indicatorRect.left - 2, indicatorRect.bottom),
2586 			separatorShadowColor);
2587 		view->AddLine(BPoint(indicatorRect.left - 1, indicatorRect.top),
2588 			BPoint(indicatorRect.left - 1, indicatorRect.bottom),
2589 			separatorLightColor);
2590 
2591 		view->EndLineArray();
2592 
2593 		// draw background and pop-up marker
2594 		_DrawMenuFieldBackgroundInside(view, indicatorRect, updateRect,
2595 			0.0f, rightTopRadius, 0.0f, rightBottomRadius, base, flags, 0);
2596 
2597 		if ((flags & B_ACTIVATED) != 0)
2598 			indicatorRect.top++;
2599 
2600 		_DrawPopUpMarker(view, indicatorRect, base, flags);
2601 	}
2602 
2603 	// fill in the background
2604 	view->FillRect(rect, fillGradient);
2605 }
2606 
2607 
2608 void
2609 BControlLook::_DrawPopUpMarker(BView* view, const BRect& rect,
2610 	const rgb_color& base, uint32 flags)
2611 {
2612 	BPoint center(roundf((rect.left + rect.right) / 2.0),
2613 		roundf((rect.top + rect.bottom) / 2.0));
2614 	BPoint triangle[3];
2615 	triangle[0] = center + BPoint(-2.5, -0.5);
2616 	triangle[1] = center + BPoint(2.5, -0.5);
2617 	triangle[2] = center + BPoint(0.0, 2.0);
2618 
2619 	uint32 viewFlags = view->Flags();
2620 	view->SetFlags(viewFlags | B_SUBPIXEL_PRECISE);
2621 
2622 	rgb_color markColor;
2623 	if ((flags & B_DISABLED) != 0)
2624 		markColor = tint_color(base, 1.35);
2625 	else
2626 		markColor = tint_color(base, 1.65);
2627 
2628 	view->SetHighColor(markColor);
2629 	view->FillTriangle(triangle[0], triangle[1], triangle[2]);
2630 
2631 	view->SetFlags(viewFlags);
2632 }
2633 
2634 
2635 void
2636 BControlLook::_DrawMenuFieldBackgroundOutside(BView* view, BRect& rect,
2637 	const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2638 	float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2639 	bool popupIndicator, uint32 flags)
2640 {
2641 	if (!rect.IsValid() || !rect.Intersects(updateRect))
2642 		return;
2643 
2644 	if (popupIndicator) {
2645 		BRect leftRect(rect);
2646 		leftRect.right -= 10;
2647 
2648 		BRect rightRect(rect);
2649 		rightRect.left = rightRect.right - 9;
2650 
2651 		_DrawMenuFieldBackgroundInside(view, leftRect, updateRect,
2652 			leftTopRadius, 0.0f, leftBottomRadius, 0.0f, base, flags,
2653 			B_LEFT_BORDER | B_TOP_BORDER | B_BOTTOM_BORDER);
2654 
2655 		_DrawMenuFieldBackgroundInside(view, rightRect, updateRect,
2656 			0.0f, rightTopRadius, 0.0f, rightBottomRadius, base, flags,
2657 			B_TOP_BORDER | B_RIGHT_BORDER | B_BOTTOM_BORDER);
2658 
2659 		_DrawPopUpMarker(view, rightRect, base, flags);
2660 
2661 		// draw a line on the left of the popup frame
2662 		rgb_color bevelShadowColor = _BevelShadowColor(base, flags);
2663 		view->SetHighColor(bevelShadowColor);
2664 		BPoint leftTopCorner(floorf(rightRect.left - 1.0),
2665 			floorf(rightRect.top - 1.0));
2666 		BPoint leftBottomCorner(floorf(rightRect.left - 1.0),
2667 			floorf(rightRect.bottom + 1.0));
2668 		view->StrokeLine(leftTopCorner, leftBottomCorner);
2669 
2670 		rect = leftRect;
2671 	} else {
2672 		_DrawMenuFieldBackgroundInside(view, rect, updateRect, leftTopRadius,
2673 			rightTopRadius, leftBottomRadius, rightBottomRadius, base, flags);
2674 	}
2675 }
2676 
2677 
2678 void
2679 BControlLook::_DrawMenuFieldBackgroundInside(BView* view, BRect& rect,
2680 	const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2681 	float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2682 	uint32 flags, uint32 borders)
2683 {
2684 	if (!rect.IsValid() || !rect.Intersects(updateRect))
2685 		return;
2686 
2687 	// save the clipping constraints of the view
2688 	view->PushState();
2689 
2690 	// set clipping constraints to updateRect
2691 	BRegion clipping(updateRect);
2692 	view->ConstrainClippingRegion(&clipping);
2693 
2694 	// frame colors
2695 	rgb_color frameLightColor  = _FrameLightColor(base, flags);
2696 	rgb_color frameShadowColor = _FrameShadowColor(base, flags);
2697 
2698 	// indicator background color
2699 	rgb_color indicatorBase;
2700 	if ((borders & B_LEFT_BORDER) != 0)
2701 		indicatorBase = base;
2702 	else {
2703 		if ((flags & B_DISABLED) != 0)
2704 			indicatorBase = tint_color(base, 1.05);
2705 		else
2706 			indicatorBase = tint_color(base, 1.12);
2707 	}
2708 
2709 	// bevel colors
2710 	rgb_color cornerColor = tint_color(indicatorBase, 0.85);
2711 	rgb_color bevelColor1 = tint_color(indicatorBase, 0.3);
2712 	rgb_color bevelColor2 = tint_color(indicatorBase, 0.5);
2713 	rgb_color bevelColor3 = tint_color(indicatorBase, 1.03);
2714 
2715 	if ((flags & B_DISABLED) != 0) {
2716 		cornerColor = tint_color(indicatorBase, 0.8);
2717 		bevelColor1 = tint_color(indicatorBase, 0.7);
2718 		bevelColor2 = tint_color(indicatorBase, 0.8);
2719 		bevelColor3 = tint_color(indicatorBase, 1.01);
2720 	} else {
2721 		cornerColor = tint_color(indicatorBase, 0.85);
2722 		bevelColor1 = tint_color(indicatorBase, 0.3);
2723 		bevelColor2 = tint_color(indicatorBase, 0.5);
2724 		bevelColor3 = tint_color(indicatorBase, 1.03);
2725 	}
2726 
2727 	// surface top gradient
2728 	BGradientLinear fillGradient;
2729 	_MakeButtonGradient(fillGradient, rect, indicatorBase, flags);
2730 
2731 	// rounded corners
2732 
2733 	if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0
2734 		&& leftTopRadius > 0) {
2735 		// draw left top rounded corner
2736 		BRect leftTopCorner(floorf(rect.left), floorf(rect.top),
2737 			floorf(rect.left + leftTopRadius - 2.0),
2738 			floorf(rect.top + leftTopRadius - 2.0));
2739 		clipping.Exclude(leftTopCorner);
2740 
2741 		BRegion cornerClipping(leftTopCorner);
2742 		view->ConstrainClippingRegion(&cornerClipping);
2743 
2744 		BRect ellipseRect(leftTopCorner);
2745 		ellipseRect.InsetBy(-1.0, -1.0);
2746 		ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2747 		ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2748 
2749 		// draw the frame (again)
2750 		view->SetHighColor(frameLightColor);
2751 		view->FillEllipse(ellipseRect);
2752 
2753 		// draw the bevel and background
2754 		_DrawRoundCornerBackgroundLeftTop(view, leftTopCorner, updateRect,
2755 			bevelColor1, fillGradient);
2756 	}
2757 
2758 	if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0
2759 		&& rightTopRadius > 0) {
2760 		// draw right top rounded corner
2761 		BRect rightTopCorner(floorf(rect.right - rightTopRadius + 2.0),
2762 			floorf(rect.top), floorf(rect.right),
2763 			floorf(rect.top + rightTopRadius - 2.0));
2764 		clipping.Exclude(rightTopCorner);
2765 
2766 		BRegion cornerClipping(rightTopCorner);
2767 		view->ConstrainClippingRegion(&cornerClipping);
2768 
2769 		BRect ellipseRect(rightTopCorner);
2770 		ellipseRect.InsetBy(-1.0, -1.0);
2771 		ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
2772 		ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2773 
2774 		// draw the frame (again)
2775 		if (frameLightColor == frameShadowColor) {
2776 			view->SetHighColor(frameLightColor);
2777 			view->FillEllipse(ellipseRect);
2778 		} else {
2779 			BGradientLinear gradient;
2780 			gradient.AddColor(frameLightColor, 0);
2781 			gradient.AddColor(frameShadowColor, 255);
2782 			gradient.SetStart(rightTopCorner.LeftTop());
2783 			gradient.SetEnd(rightTopCorner.RightBottom());
2784 			view->FillEllipse(ellipseRect, gradient);
2785 		}
2786 
2787 		// draw the bevel and background
2788 		_DrawRoundCornerBackgroundRightTop(view, rightTopCorner, updateRect,
2789 			bevelColor1, bevelColor3, fillGradient);
2790 	}
2791 
2792 	if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2793 		&& leftBottomRadius > 0) {
2794 		// draw left bottom rounded corner
2795 		BRect leftBottomCorner(floorf(rect.left),
2796 			floorf(rect.bottom - leftBottomRadius + 2.0),
2797 			floorf(rect.left + leftBottomRadius - 2.0),
2798 			floorf(rect.bottom));
2799 		clipping.Exclude(leftBottomCorner);
2800 
2801 		BRegion cornerClipping(leftBottomCorner);
2802 		view->ConstrainClippingRegion(&cornerClipping);
2803 
2804 		BRect ellipseRect(leftBottomCorner);
2805 		ellipseRect.InsetBy(-1.0, -1.0);
2806 		ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2807 		ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
2808 
2809 		// draw the frame (again)
2810 		if (frameLightColor == frameShadowColor) {
2811 			view->SetHighColor(frameLightColor);
2812 			view->FillEllipse(ellipseRect);
2813 		} else {
2814 			BGradientLinear gradient;
2815 			gradient.AddColor(frameLightColor, 0);
2816 			gradient.AddColor(frameShadowColor, 255);
2817 			gradient.SetStart(leftBottomCorner.LeftTop());
2818 			gradient.SetEnd(leftBottomCorner.RightBottom());
2819 			view->FillEllipse(ellipseRect, gradient);
2820 		}
2821 
2822 		// draw the bevel and background
2823 		_DrawRoundCornerBackgroundLeftBottom(view, leftBottomCorner,
2824 			updateRect, bevelColor2, bevelColor3, fillGradient);
2825 	}
2826 
2827 	if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2828 		&& rightBottomRadius > 0) {
2829 		// draw right bottom rounded corner
2830 		BRect rightBottomCorner(floorf(rect.right - rightBottomRadius + 2.0),
2831 			floorf(rect.bottom - rightBottomRadius + 2.0), floorf(rect.right),
2832 			floorf(rect.bottom));
2833 		clipping.Exclude(rightBottomCorner);
2834 
2835 		BRegion cornerClipping(rightBottomCorner);
2836 		view->ConstrainClippingRegion(&cornerClipping);
2837 
2838 		BRect ellipseRect(rightBottomCorner);
2839 		ellipseRect.InsetBy(-1.0, -1.0);
2840 		ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
2841 		ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
2842 
2843 		// draw the frame (again)
2844 		view->SetHighColor(frameShadowColor);
2845 		view->FillEllipse(ellipseRect);
2846 
2847 		// draw the bevel and background
2848 		_DrawRoundCornerBackgroundRightBottom(view, rightBottomCorner,
2849 			updateRect, bevelColor3, fillGradient);
2850 	}
2851 
2852 	// clip out the corners
2853 	view->ConstrainClippingRegion(&clipping);
2854 
2855 	// draw the bevel
2856 	_DrawFrame(view, rect,
2857 		bevelColor2, bevelColor1,
2858 		bevelColor3, bevelColor3,
2859 		cornerColor, cornerColor,
2860 		borders);
2861 
2862 	// fill in the background
2863 	view->FillRect(rect, fillGradient);
2864 
2865 	// restore the clipping constraints of the view
2866 	view->PopState();
2867 }
2868 
2869 
2870 void
2871 BControlLook::_DrawRoundCornerLeftTop(BView* view, BRect& cornerRect,
2872 	const BRect& updateRect, const rgb_color& background,
2873 	const rgb_color& edgeColor, const rgb_color& frameColor,
2874 	const rgb_color& bevelColor, const BGradientLinear& fillGradient)
2875 {
2876 	_DrawRoundCornerFrameLeftTop(view, cornerRect, updateRect,
2877 		background, edgeColor, frameColor);
2878 	_DrawRoundCornerBackgroundLeftTop(view, cornerRect, updateRect,
2879 		bevelColor, fillGradient);
2880 }
2881 
2882 
2883 void
2884 BControlLook::_DrawRoundCornerFrameLeftTop(BView* view, BRect& cornerRect,
2885 	const BRect& updateRect, const rgb_color& background,
2886 	const rgb_color& edgeColor, const rgb_color& frameColor)
2887 {
2888 	// constrain clipping region to corner
2889 	BRegion clipping(cornerRect);
2890 	view->ConstrainClippingRegion(&clipping);
2891 
2892 	// background
2893 	view->SetHighColor(background);
2894 	view->FillRect(cornerRect);
2895 
2896 	// outer edge
2897 	BRect ellipseRect(cornerRect);
2898 	ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2899 	ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2900 
2901 	view->SetHighColor(edgeColor);
2902 	view->FillEllipse(ellipseRect);
2903 
2904 	// frame
2905 	ellipseRect.InsetBy(1, 1);
2906 	cornerRect.left++;
2907 	cornerRect.top++;
2908 	view->SetHighColor(frameColor);
2909 	view->FillEllipse(ellipseRect);
2910 
2911 	// prepare for bevel
2912 	cornerRect.left++;
2913 	cornerRect.top++;
2914 }
2915 
2916 
2917 void
2918 BControlLook::_DrawRoundCornerBackgroundLeftTop(BView* view, BRect& cornerRect,
2919 	const BRect& updateRect, const rgb_color& bevelColor,
2920 	const BGradientLinear& fillGradient)
2921 {
2922 	// constrain clipping region to corner
2923 	BRegion clipping(cornerRect);
2924 	view->ConstrainClippingRegion(&clipping);
2925 
2926 	BRect ellipseRect(cornerRect);
2927 	ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2928 	ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2929 
2930 	// bevel
2931 	view->SetHighColor(bevelColor);
2932 	view->FillEllipse(ellipseRect);
2933 
2934 	// gradient
2935 	ellipseRect.InsetBy(1, 1);
2936 	view->FillEllipse(ellipseRect, fillGradient);
2937 }
2938 
2939 
2940 void
2941 BControlLook::_DrawRoundCornerRightTop(BView* view, BRect& cornerRect,
2942 	const BRect& updateRect, const rgb_color& background,
2943 	const rgb_color& edgeTopColor, const rgb_color& edgeRightColor,
2944 	const rgb_color& frameTopColor, const rgb_color& frameRightColor,
2945 	const rgb_color& bevelTopColor, const rgb_color& bevelRightColor,
2946 	const BGradientLinear& fillGradient)
2947 {
2948 	_DrawRoundCornerFrameRightTop(view, cornerRect, updateRect,
2949 		background, edgeTopColor, edgeRightColor, frameTopColor,
2950 		frameRightColor);
2951 	_DrawRoundCornerBackgroundRightTop(view, cornerRect, updateRect,
2952 		bevelTopColor, bevelRightColor, fillGradient);
2953 }
2954 
2955 
2956 void
2957 BControlLook::_DrawRoundCornerFrameRightTop(BView* view, BRect& cornerRect,
2958 	const BRect& updateRect, const rgb_color& background,
2959 	const rgb_color& edgeTopColor, const rgb_color& edgeRightColor,
2960 	const rgb_color& frameTopColor, const rgb_color& frameRightColor)
2961 {
2962 	// constrain clipping region to corner
2963 	BRegion clipping(cornerRect);
2964 	view->ConstrainClippingRegion(&clipping);
2965 
2966 	// background
2967 	view->SetHighColor(background);
2968 	view->FillRect(cornerRect);
2969 
2970 	// outer edge
2971 	BRect ellipseRect(cornerRect);
2972 	ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
2973 	ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2974 
2975 	BGradientLinear gradient;
2976 	gradient.AddColor(edgeTopColor, 0);
2977 	gradient.AddColor(edgeRightColor, 255);
2978 	gradient.SetStart(cornerRect.LeftTop());
2979 	gradient.SetEnd(cornerRect.RightBottom());
2980 	view->FillEllipse(ellipseRect, gradient);
2981 
2982 	// frame
2983 	ellipseRect.InsetBy(1, 1);
2984 	cornerRect.right--;
2985 	cornerRect.top++;
2986 	if (frameTopColor == frameRightColor) {
2987 		view->SetHighColor(frameTopColor);
2988 		view->FillEllipse(ellipseRect);
2989 	} else {
2990 		gradient.SetColor(0, frameTopColor);
2991 		gradient.SetColor(1, frameRightColor);
2992 		gradient.SetStart(cornerRect.LeftTop());
2993 		gradient.SetEnd(cornerRect.RightBottom());
2994 		view->FillEllipse(ellipseRect, gradient);
2995 	}
2996 
2997 	// prepare for bevel
2998 	cornerRect.right--;
2999 	cornerRect.top++;
3000 }
3001 
3002 
3003 void
3004 BControlLook::_DrawRoundCornerBackgroundRightTop(BView* view, BRect& cornerRect,
3005 	const BRect& updateRect, const rgb_color& bevelTopColor,
3006 	const rgb_color& bevelRightColor, const BGradientLinear& fillGradient)
3007 {
3008 	// constrain clipping region to corner
3009 	BRegion clipping(cornerRect);
3010 	view->ConstrainClippingRegion(&clipping);
3011 
3012 	BRect ellipseRect(cornerRect);
3013 	ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
3014 	ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
3015 
3016 	// bevel
3017 	BGradientLinear gradient;
3018 	gradient.AddColor(bevelTopColor, 0);
3019 	gradient.AddColor(bevelRightColor, 255);
3020 	gradient.SetStart(cornerRect.LeftTop());
3021 	gradient.SetEnd(cornerRect.RightBottom());
3022 	view->FillEllipse(ellipseRect, gradient);
3023 
3024 	// gradient
3025 	ellipseRect.InsetBy(1, 1);
3026 	view->FillEllipse(ellipseRect, fillGradient);
3027 }
3028 
3029 
3030 void
3031 BControlLook::_DrawRoundCornerLeftBottom(BView* view, BRect& cornerRect,
3032 	const BRect& updateRect, const rgb_color& background,
3033 	const rgb_color& edgeLeftColor, const rgb_color& edgeBottomColor,
3034 	const rgb_color& frameLeftColor, const rgb_color& frameBottomColor,
3035 	const rgb_color& bevelLeftColor, const rgb_color& bevelBottomColor,
3036 	const BGradientLinear& fillGradient)
3037 {
3038 	_DrawRoundCornerFrameLeftBottom(view, cornerRect, updateRect,
3039 		background, edgeLeftColor, edgeBottomColor, frameLeftColor,
3040 		frameBottomColor);
3041 	_DrawRoundCornerBackgroundLeftBottom(view, cornerRect, updateRect,
3042 		bevelLeftColor, bevelBottomColor, fillGradient);
3043 }
3044 
3045 
3046 void
3047 BControlLook::_DrawRoundCornerFrameLeftBottom(BView* view, BRect& cornerRect,
3048 	const BRect& updateRect, const rgb_color& background,
3049 	const rgb_color& edgeLeftColor, const rgb_color& edgeBottomColor,
3050 	const rgb_color& frameLeftColor, const rgb_color& frameBottomColor)
3051 {
3052 	// constrain clipping region to corner
3053 	BRegion clipping(cornerRect);
3054 	view->ConstrainClippingRegion(&clipping);
3055 
3056 	// background
3057 	view->SetHighColor(background);
3058 	view->FillRect(cornerRect);
3059 
3060 	// outer edge
3061 	BRect ellipseRect(cornerRect);
3062 	ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
3063 	ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
3064 
3065 	BGradientLinear gradient;
3066 	gradient.AddColor(edgeLeftColor, 0);
3067 	gradient.AddColor(edgeBottomColor, 255);
3068 	gradient.SetStart(cornerRect.LeftTop());
3069 	gradient.SetEnd(cornerRect.RightBottom());
3070 	view->FillEllipse(ellipseRect, gradient);
3071 
3072 	// frame
3073 	ellipseRect.InsetBy(1, 1);
3074 	cornerRect.left++;
3075 	cornerRect.bottom--;
3076 	if (frameLeftColor == frameBottomColor) {
3077 		view->SetHighColor(frameLeftColor);
3078 		view->FillEllipse(ellipseRect);
3079 	} else {
3080 		gradient.SetColor(0, frameLeftColor);
3081 		gradient.SetColor(1, frameBottomColor);
3082 		gradient.SetStart(cornerRect.LeftTop());
3083 		gradient.SetEnd(cornerRect.RightBottom());
3084 		view->FillEllipse(ellipseRect, gradient);
3085 	}
3086 
3087 	// prepare for bevel
3088 	cornerRect.left++;
3089 	cornerRect.bottom--;
3090 }
3091 
3092 
3093 void
3094 BControlLook::_DrawRoundCornerBackgroundLeftBottom(BView* view, BRect& cornerRect,
3095 	const BRect& updateRect, const rgb_color& bevelLeftColor,
3096 	const rgb_color& bevelBottomColor, const BGradientLinear& fillGradient)
3097 {
3098 	// constrain clipping region to corner
3099 	BRegion clipping(cornerRect);
3100 	view->ConstrainClippingRegion(&clipping);
3101 
3102 	BRect ellipseRect(cornerRect);
3103 	ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
3104 	ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
3105 
3106 	// bevel
3107 	BGradientLinear gradient;
3108 	gradient.AddColor(bevelLeftColor, 0);
3109 	gradient.AddColor(bevelBottomColor, 255);
3110 	gradient.SetStart(cornerRect.LeftTop());
3111 	gradient.SetEnd(cornerRect.RightBottom());
3112 	view->FillEllipse(ellipseRect, gradient);
3113 
3114 	// gradient
3115 	ellipseRect.InsetBy(1, 1);
3116 	view->FillEllipse(ellipseRect, fillGradient);
3117 }
3118 
3119 
3120 void
3121 BControlLook::_DrawRoundCornerRightBottom(BView* view, BRect& cornerRect,
3122 	const BRect& updateRect, const rgb_color& background,
3123 	const rgb_color& edgeColor, const rgb_color& frameColor,
3124 	const rgb_color& bevelColor, const BGradientLinear& fillGradient)
3125 {
3126 	_DrawRoundCornerFrameRightBottom(view, cornerRect, updateRect,
3127 		background, edgeColor, frameColor);
3128 	_DrawRoundCornerBackgroundRightBottom(view, cornerRect, updateRect,
3129 		bevelColor, fillGradient);
3130 }
3131 
3132 
3133 void
3134 BControlLook::_DrawRoundCornerFrameRightBottom(BView* view, BRect& cornerRect,
3135 	const BRect& updateRect, const rgb_color& background,
3136 	const rgb_color& edgeColor, const rgb_color& frameColor)
3137 {
3138 	// constrain clipping region to corner
3139 	BRegion clipping(cornerRect);
3140 	view->ConstrainClippingRegion(&clipping);
3141 
3142 	// background
3143 	view->SetHighColor(background);
3144 	view->FillRect(cornerRect);
3145 
3146 	// outer edge
3147 	BRect ellipseRect(cornerRect);
3148 	ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
3149 	ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
3150 
3151 	view->SetHighColor(edgeColor);
3152 	view->FillEllipse(ellipseRect);
3153 
3154 	// frame
3155 	ellipseRect.InsetBy(1, 1);
3156 	cornerRect.right--;
3157 	cornerRect.bottom++;
3158 	view->SetHighColor(frameColor);
3159 	view->FillEllipse(ellipseRect);
3160 
3161 	// prepare for bevel
3162 	cornerRect.left++;
3163 	cornerRect.bottom--;
3164 }
3165 
3166 
3167 void
3168 BControlLook::_DrawRoundCornerBackgroundRightBottom(BView* view,
3169 	BRect& cornerRect, const BRect& updateRect, const rgb_color& bevelColor,
3170 	const BGradientLinear& fillGradient)
3171 {
3172 	// constrain clipping region to corner
3173 	BRegion clipping(cornerRect);
3174 	view->ConstrainClippingRegion(&clipping);
3175 
3176 	BRect ellipseRect(cornerRect);
3177 	ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
3178 	ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
3179 
3180 	// bevel
3181 	view->SetHighColor(bevelColor);
3182 	view->FillEllipse(ellipseRect);
3183 
3184 	// gradient
3185 	ellipseRect.InsetBy(1, 1);
3186 	view->FillEllipse(ellipseRect, fillGradient);
3187 }
3188 
3189 
3190 void
3191 BControlLook::_DrawRoundBarCorner(BView* view, BRect& rect,
3192 	const BRect& updateRect,
3193 	const rgb_color& edgeLightColor, const rgb_color& edgeShadowColor,
3194 	const rgb_color& frameLightColor, const rgb_color& frameShadowColor,
3195 	const rgb_color& fillLightColor, const rgb_color& fillShadowColor,
3196 	float leftInset, float topInset, float rightInset, float bottomInset,
3197 	orientation orientation)
3198 {
3199 	if (!rect.IsValid() || !rect.Intersects(updateRect))
3200 		return;
3201 
3202 	BGradientLinear gradient;
3203 	gradient.AddColor(edgeShadowColor, 0);
3204 	gradient.AddColor(edgeLightColor, 255);
3205 	gradient.SetStart(rect.LeftTop());
3206 	if (orientation == B_HORIZONTAL)
3207 		gradient.SetEnd(rect.LeftBottom());
3208 	else
3209 		gradient.SetEnd(rect.RightTop());
3210 
3211 	view->FillEllipse(rect, gradient);
3212 
3213 	rect.left += leftInset;
3214 	rect.top += topInset;
3215 	rect.right += rightInset;
3216 	rect.bottom += bottomInset;
3217 
3218 	gradient.MakeEmpty();
3219 	gradient.AddColor(frameShadowColor, 0);
3220 	gradient.AddColor(frameLightColor, 255);
3221 	gradient.SetStart(rect.LeftTop());
3222 	if (orientation == B_HORIZONTAL)
3223 		gradient.SetEnd(rect.LeftBottom());
3224 	else
3225 		gradient.SetEnd(rect.RightTop());
3226 
3227 	view->FillEllipse(rect, gradient);
3228 
3229 	rect.left += leftInset;
3230 	rect.top += topInset;
3231 	rect.right += rightInset;
3232 	rect.bottom += bottomInset;
3233 
3234 	gradient.MakeEmpty();
3235 	gradient.AddColor(fillShadowColor, 0);
3236 	gradient.AddColor(fillLightColor, 255);
3237 	gradient.SetStart(rect.LeftTop());
3238 	if (orientation == B_HORIZONTAL)
3239 		gradient.SetEnd(rect.LeftBottom());
3240 	else
3241 		gradient.SetEnd(rect.RightTop());
3242 
3243 	view->FillEllipse(rect, gradient);
3244 }
3245 
3246 
3247 rgb_color
3248 BControlLook::_EdgeLightColor(const rgb_color& base, float contrast,
3249 	float brightness, uint32 flags)
3250 {
3251 	rgb_color edgeLightColor;
3252 
3253 	if ((flags & B_BLEND_FRAME) != 0) {
3254 		uint8 alpha = uint8(20 * contrast);
3255 		uint8 white = uint8(255 * brightness);
3256 
3257 		edgeLightColor = (rgb_color){ white, white, white, alpha };
3258 	} else {
3259 		// colors
3260 		float tintLight = kEdgeBevelLightTint;
3261 
3262 		if (contrast == 0.0)
3263 			tintLight = B_NO_TINT;
3264 		else if (contrast != 1.0)
3265 			tintLight = B_NO_TINT + (tintLight - B_NO_TINT) * contrast;
3266 
3267 		edgeLightColor = tint_color(base, tintLight);
3268 
3269 		if (brightness < 1.0) {
3270 			edgeLightColor.red = uint8(edgeLightColor.red * brightness);
3271 			edgeLightColor.green = uint8(edgeLightColor.green * brightness);
3272 			edgeLightColor.blue = uint8(edgeLightColor.blue * brightness);
3273 		}
3274 	}
3275 
3276 	return edgeLightColor;
3277 }
3278 
3279 
3280 rgb_color
3281 BControlLook::_EdgeShadowColor(const rgb_color& base, float contrast,
3282 	float brightness, uint32 flags)
3283 {
3284 	rgb_color edgeShadowColor;
3285 
3286 	if ((flags & B_BLEND_FRAME) != 0) {
3287 		uint8 alpha = uint8(20 * contrast);
3288 		edgeShadowColor = (rgb_color){ 0, 0, 0, alpha };
3289 	} else {
3290 		float tintShadow = kEdgeBevelShadowTint;
3291 
3292 		if (contrast == 0.0)
3293 			tintShadow = B_NO_TINT;
3294 		else if (contrast != 1.0)
3295 			tintShadow = B_NO_TINT + (tintShadow - B_NO_TINT) * contrast;
3296 
3297 		edgeShadowColor = tint_color(base, tintShadow);
3298 
3299 		if (brightness < 1.0) {
3300 			edgeShadowColor.red = uint8(edgeShadowColor.red * brightness);
3301 			edgeShadowColor.green = uint8(edgeShadowColor.green * brightness);
3302 			edgeShadowColor.blue = uint8(edgeShadowColor.blue * brightness);
3303 		}
3304 	}
3305 
3306 	return edgeShadowColor;
3307 }
3308 
3309 
3310 rgb_color
3311 BControlLook::_FrameLightColor(const rgb_color& base, uint32 flags)
3312 {
3313 	if ((flags & B_FOCUSED) != 0)
3314 		return ui_color(B_KEYBOARD_NAVIGATION_COLOR);
3315 
3316 	if ((flags & B_ACTIVATED) != 0)
3317 		return _FrameShadowColor(base, flags & ~B_ACTIVATED);
3318 
3319 	rgb_color frameLightColor;
3320 
3321 	if ((flags & B_DISABLED) != 0) {
3322 		// TODO: B_BLEND_FRAME
3323 		frameLightColor = tint_color(base, 1.145);
3324 
3325 		if ((flags & B_DEFAULT_BUTTON) != 0)
3326 			frameLightColor = tint_color(frameLightColor, 1.14);
3327 	} else {
3328 		if ((flags & B_BLEND_FRAME) != 0)
3329 			frameLightColor = (rgb_color){ 0, 0, 0, 75 };
3330 		else
3331 			frameLightColor = tint_color(base, 1.33);
3332 
3333 		if ((flags & B_DEFAULT_BUTTON) != 0)
3334 			frameLightColor = tint_color(frameLightColor, 1.35);
3335 	}
3336 
3337 	return frameLightColor;
3338 }
3339 
3340 
3341 rgb_color
3342 BControlLook::_FrameShadowColor(const rgb_color& base, uint32 flags)
3343 {
3344 	if ((flags & B_FOCUSED) != 0)
3345 		return ui_color(B_KEYBOARD_NAVIGATION_COLOR);
3346 
3347 	if ((flags & B_ACTIVATED) != 0)
3348 		return _FrameLightColor(base, flags & ~B_ACTIVATED);
3349 
3350 	rgb_color frameShadowColor;
3351 
3352 	if ((flags & B_DISABLED) != 0) {
3353 		// TODO: B_BLEND_FRAME
3354 		frameShadowColor = tint_color(base, 1.24);
3355 
3356 		if ((flags & B_DEFAULT_BUTTON) != 0) {
3357 			frameShadowColor = tint_color(base, 1.145);
3358 			frameShadowColor = tint_color(frameShadowColor, 1.12);
3359 		}
3360 	} else {
3361 		if ((flags & B_DEFAULT_BUTTON) != 0) {
3362 			if ((flags & B_BLEND_FRAME) != 0)
3363 				frameShadowColor = (rgb_color){ 0, 0, 0, 75 };
3364 			else
3365 				frameShadowColor = tint_color(base, 1.33);
3366 
3367 			frameShadowColor = tint_color(frameShadowColor, 1.5);
3368 		} else {
3369 			if ((flags & B_BLEND_FRAME) != 0)
3370 				frameShadowColor = (rgb_color){ 0, 0, 0, 95 };
3371 			else
3372 				frameShadowColor = tint_color(base, 1.47);
3373 		}
3374 	}
3375 
3376 	return frameShadowColor;
3377 }
3378 
3379 
3380 rgb_color
3381 BControlLook::_BevelLightColor(const rgb_color& base, uint32 flags)
3382 {
3383 	rgb_color bevelLightColor = tint_color(base, 0.2);
3384 
3385 	if ((flags & B_DISABLED) != 0)
3386 		bevelLightColor = tint_color(base, B_LIGHTEN_1_TINT);
3387 
3388 	if ((flags & B_ACTIVATED) != 0)
3389 		bevelLightColor = tint_color(base, B_DARKEN_1_TINT);
3390 
3391 	return bevelLightColor;
3392 }
3393 
3394 
3395 rgb_color
3396 BControlLook::_BevelShadowColor(const rgb_color& base, uint32 flags)
3397 {
3398 	rgb_color bevelShadowColor = tint_color(base, 1.08);
3399 
3400 	if ((flags & B_DISABLED) != 0)
3401 		bevelShadowColor = base;
3402 
3403 	if ((flags & B_ACTIVATED) != 0)
3404 		bevelShadowColor = tint_color(base, B_DARKEN_1_TINT);
3405 
3406 	return bevelShadowColor;
3407 }
3408 
3409 
3410 void
3411 BControlLook::_FillGradient(BView* view, const BRect& rect,
3412 	const rgb_color& base, float topTint, float bottomTint,
3413 	orientation orientation)
3414 {
3415 	BGradientLinear gradient;
3416 	_MakeGradient(gradient, rect, base, topTint, bottomTint, orientation);
3417 	view->FillRect(rect, gradient);
3418 }
3419 
3420 
3421 void
3422 BControlLook::_FillGlossyGradient(BView* view, const BRect& rect,
3423 	const rgb_color& base, float topTint, float middle1Tint,
3424 	float middle2Tint, float bottomTint, orientation orientation)
3425 {
3426 	BGradientLinear gradient;
3427 	_MakeGlossyGradient(gradient, rect, base, topTint, middle1Tint,
3428 		middle2Tint, bottomTint, orientation);
3429 	view->FillRect(rect, gradient);
3430 }
3431 
3432 
3433 void
3434 BControlLook::_MakeGradient(BGradientLinear& gradient, const BRect& rect,
3435 	const rgb_color& base, float topTint, float bottomTint,
3436 	orientation orientation) const
3437 {
3438 	gradient.AddColor(tint_color(base, topTint), 0);
3439 	gradient.AddColor(tint_color(base, bottomTint), 255);
3440 	gradient.SetStart(rect.LeftTop());
3441 	if (orientation == B_HORIZONTAL)
3442 		gradient.SetEnd(rect.LeftBottom());
3443 	else
3444 		gradient.SetEnd(rect.RightTop());
3445 }
3446 
3447 
3448 void
3449 BControlLook::_MakeGlossyGradient(BGradientLinear& gradient, const BRect& rect,
3450 	const rgb_color& base, float topTint, float middle1Tint,
3451 	float middle2Tint, float bottomTint,
3452 	orientation orientation) const
3453 {
3454 	gradient.AddColor(tint_color(base, topTint), 0);
3455 	gradient.AddColor(tint_color(base, middle1Tint), 132);
3456 	gradient.AddColor(tint_color(base, middle2Tint), 136);
3457 	gradient.AddColor(tint_color(base, bottomTint), 255);
3458 	gradient.SetStart(rect.LeftTop());
3459 	if (orientation == B_HORIZONTAL)
3460 		gradient.SetEnd(rect.LeftBottom());
3461 	else
3462 		gradient.SetEnd(rect.RightTop());
3463 }
3464 
3465 
3466 void
3467 BControlLook::_MakeButtonGradient(BGradientLinear& gradient, BRect& rect,
3468 	const rgb_color& base, uint32 flags, orientation orientation) const
3469 {
3470 	float topTint = 0.49;
3471 	float middleTint1 = 0.62;
3472 	float middleTint2 = 0.76;
3473 	float bottomTint = 0.90;
3474 
3475 	if ((flags & B_ACTIVATED) != 0) {
3476 		topTint = 1.11;
3477 		bottomTint = 1.08;
3478 	}
3479 
3480 	if ((flags & B_DISABLED) != 0) {
3481 		topTint = (topTint + B_NO_TINT) / 2;
3482 		middleTint1 = (middleTint1 + B_NO_TINT) / 2;
3483 		middleTint2 = (middleTint2 + B_NO_TINT) / 2;
3484 		bottomTint = (bottomTint + B_NO_TINT) / 2;
3485 	} else if ((flags & B_HOVER) != 0) {
3486 		topTint *= kHoverTintFactor;
3487 		middleTint1 *= kHoverTintFactor;
3488 		middleTint2 *= kHoverTintFactor;
3489 		bottomTint *= kHoverTintFactor;
3490 	}
3491 
3492 	if ((flags & B_ACTIVATED) != 0) {
3493 		_MakeGradient(gradient, rect, base, topTint, bottomTint, orientation);
3494 	} else {
3495 		_MakeGlossyGradient(gradient, rect, base, topTint, middleTint1,
3496 			middleTint2, bottomTint, orientation);
3497 	}
3498 }
3499 
3500 
3501 
3502 bool
3503 BControlLook::_RadioButtonAndCheckBoxMarkColor(const rgb_color& base,
3504 	rgb_color& color, uint32 flags) const
3505 {
3506 	if ((flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED | B_CLICKED)) == 0) {
3507 		// no mark to be drawn at all
3508 		return false;
3509 	}
3510 
3511 	color = ui_color(B_CONTROL_MARK_COLOR);
3512 
3513 	float mix = 1.0;
3514 
3515 	if ((flags & B_DISABLED) != 0) {
3516 		// activated, but disabled
3517 		mix = 0.4;
3518 	} else if ((flags & B_CLICKED) != 0) {
3519 		if ((flags & B_ACTIVATED) != 0) {
3520 			// losing activation
3521 			mix = 0.7;
3522 		} else {
3523 			// becoming activated (or losing partial activation)
3524 			mix = 0.3;
3525 		}
3526 	} else if ((flags & B_PARTIALLY_ACTIVATED) != 0) {
3527 		// partially activated
3528 		mix = 0.5;
3529 	} else {
3530 		// simply activated
3531 	}
3532 
3533 	color.red = uint8(color.red * mix + base.red * (1.0 - mix));
3534 	color.green = uint8(color.green * mix + base.green * (1.0 - mix));
3535 	color.blue = uint8(color.blue * mix + base.blue * (1.0 - mix));
3536 
3537 	return true;
3538 }
3539 
3540 
3541 // NOTE: May come from a add-on in the future. Initialized in
3542 // InterfaceDefs.cpp
3543 BControlLook* be_control_look = NULL;
3544 
3545 
3546 } // namespace BPrivate
3547