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