xref: /haiku/src/kits/interface/ControlLook.cpp (revision d2bef01cc4a3dc4b82562186cd636ca1794a6682)
1 /*
2  * Copyright 2009, Stephan Aßmus <superstippi@gmx.de>
3  * Distributed under the terms of the MIT License.
4  */
5 #include <ControlLook.h>
6 
7 #include <stdio.h>
8 
9 #include <Control.h>
10 #include <GradientLinear.h>
11 #include <Region.h>
12 #include <Shape.h>
13 #include <String.h>
14 #include <View.h>
15 
16 namespace BPrivate {
17 
18 static const float kEdgeBevelLightTint = 0.59;
19 static const float kEdgeBevelShadowTint = 1.0735;
20 
21 
22 BControlLook::BControlLook()
23 {
24 }
25 
26 
27 BControlLook::~BControlLook()
28 {
29 }
30 
31 
32 BAlignment
33 BControlLook::DefaultLabelAlignment() const
34 {
35 	return BAlignment(B_ALIGN_LEFT, B_ALIGN_VERTICAL_CENTER);
36 }
37 
38 
39 float
40 BControlLook::DefaultLabelSpacing() const
41 {
42 	return 4.0;//ceilf(be_plain_font->Size() / 4.0);
43 }
44 
45 
46 uint32
47 BControlLook::Flags(BControl* control) const
48 {
49 	uint32 flags = 0;
50 
51 	if (!control->IsEnabled())
52 		flags |= B_DISABLED;
53 
54 	if (control->IsFocus())
55 		flags |= B_FOCUSED;
56 
57 	if (control->Value() == B_CONTROL_ON)
58 		flags |= B_ACTIVATED;
59 
60 	return flags;
61 }
62 
63 
64 // #pragma mark -
65 
66 
67 void
68 BControlLook::DrawButtonFrame(BView* view, BRect& rect, const BRect& updateRect,
69 	const rgb_color& base, const rgb_color& background, uint32 flags,
70 	uint32 borders)
71 {
72 	_DrawButtonFrame(view, rect, updateRect, base, background, 1.0, 1.0, flags,
73 		borders);
74 }
75 
76 
77 void
78 BControlLook::DrawButtonBackground(BView* view, BRect& rect,
79 	const BRect& updateRect, const rgb_color& base, uint32 flags,
80 	uint32 borders, enum orientation orientation)
81 {
82 	if (!rect.IsValid() || !updateRect.Intersects(rect))
83 		return;
84 
85 	// the surface edges
86 
87 	// colors
88 	rgb_color buttonBgColor = tint_color(base, B_LIGHTEN_1_TINT);
89 	rgb_color maxLightColor;
90 
91 	rgb_color bevelColor1;
92 	rgb_color bevelColor2;
93 
94 	if ((flags & B_DISABLED) == 0) {
95 		maxLightColor = tint_color(base, 0.2);
96 		bevelColor1 = tint_color(base, 1.08);
97 		bevelColor2 = base;
98 	} else {
99 		maxLightColor = tint_color(base, 0.7);
100 		bevelColor1 = base;
101 		bevelColor2 = buttonBgColor;
102 		buttonBgColor = maxLightColor;
103 	}
104 
105 	if (flags & B_ACTIVATED) {
106 		view->BeginLineArray(4);
107 
108 		bevelColor1 = tint_color(bevelColor1, B_DARKEN_1_TINT);
109 		bevelColor2 = tint_color(bevelColor2, B_DARKEN_1_TINT);
110 
111 		// shadow along left/top borders
112 		if (borders & B_LEFT_BORDER) {
113 			view->AddLine(BPoint(rect.left, rect.top),
114 				BPoint(rect.left, rect.bottom), bevelColor1);
115 			rect.left++;
116 		}
117 		if (borders & B_TOP_BORDER) {
118 			view->AddLine(BPoint(rect.left, rect.top),
119 				BPoint(rect.right, rect.top), bevelColor1);
120 			rect.top++;
121 		}
122 
123 		// softer shadow along left/top borders
124 		if (borders & B_LEFT_BORDER) {
125 			view->AddLine(BPoint(rect.left, rect.top),
126 				BPoint(rect.left, rect.bottom), bevelColor2);
127 			rect.left++;
128 		}
129 		if (borders & B_TOP_BORDER) {
130 			view->AddLine(BPoint(rect.left, rect.top),
131 				BPoint(rect.right, rect.top), bevelColor2);
132 			rect.top++;
133 		}
134 
135 		view->EndLineArray();
136 	} else {
137 		_DrawFrame(view, rect,
138 			maxLightColor, maxLightColor,
139 			bevelColor1, bevelColor1,
140 			buttonBgColor, buttonBgColor, borders);
141 	}
142 
143 	// the actual surface top
144 
145 	float topTint = 0.49;
146 	float middleTint1 = 0.62;
147 	float middleTint2 = 0.76;
148 	float bottomTint = 0.90;
149 
150 	if (flags & B_ACTIVATED) {
151 		topTint = 1.11;
152 		bottomTint = 1.08;
153 	}
154 
155 	if (flags & B_DISABLED) {
156 		topTint = (topTint + B_NO_TINT) / 2;
157 		middleTint1 = (middleTint1 + B_NO_TINT) / 2;
158 		middleTint2 = (middleTint2 + B_NO_TINT) / 2;
159 		bottomTint = (bottomTint + B_NO_TINT) / 2;
160 	} else if (flags & B_HOVER) {
161 		static const float kHoverTintFactor = 0.85;
162 		topTint *= kHoverTintFactor;
163 		middleTint1 *= kHoverTintFactor;
164 		middleTint2 *= kHoverTintFactor;
165 		bottomTint *= kHoverTintFactor;
166 	}
167 
168 	if (flags & B_ACTIVATED) {
169 		_FillGradient(view, rect, base, topTint, bottomTint, orientation);
170 	} else {
171 		_FillGlossyGradient(view, rect, base, topTint, middleTint1,
172 			middleTint2, bottomTint, orientation);
173 	}
174 }
175 
176 
177 void
178 BControlLook::DrawMenuBarBackground(BView* view, BRect& rect,
179 	const BRect& updateRect, const rgb_color& base, uint32 flags,
180 	uint32 borders)
181 {
182 	if (!rect.IsValid() || !updateRect.Intersects(rect))
183 		return;
184 
185 	// the surface edges
186 
187 	// colors
188 	float topTint;
189 	float bottomTint;
190 
191 	if (flags & B_ACTIVATED) {
192 		rgb_color bevelColor1 = tint_color(base, 1.40);
193 		rgb_color bevelColor2 = tint_color(base, 1.25);
194 
195 		topTint = 1.25;
196 		bottomTint = 1.20;
197 
198 		_DrawFrame(view, rect,
199 			bevelColor1, bevelColor1,
200 			bevelColor2, bevelColor2,
201 			borders & B_TOP_BORDER);
202 	} else {
203 		rgb_color cornerColor = tint_color(base, 0.9);
204 		rgb_color bevelColorTop = tint_color(base, 0.5);
205 		rgb_color bevelColorLeft = tint_color(base, 0.7);
206 		rgb_color bevelColorRightBottom = tint_color(base, 1.08);
207 
208 		topTint = 0.69;
209 		bottomTint = 1.03;
210 
211 		_DrawFrame(view, rect,
212 			bevelColorLeft, bevelColorTop,
213 			bevelColorRightBottom, bevelColorRightBottom,
214 			cornerColor, cornerColor,
215 			borders);
216 	}
217 
218 	// the actual surface top
219 
220 	_FillGradient(view, rect, base, topTint, bottomTint);
221 }
222 
223 
224 void
225 BControlLook::DrawMenuFieldFrame(BView* view, BRect& rect,
226 	const BRect& updateRect, const rgb_color& base,
227 	const rgb_color& background, uint32 flags, uint32 borders)
228 {
229 	_DrawButtonFrame(view, rect, updateRect, base, background, 0.6, 1.0, flags,
230 		borders);
231 }
232 
233 
234 void
235 BControlLook::DrawMenuFieldBackground(BView* view, BRect& rect,
236 	const BRect& updateRect, const rgb_color& base, bool popupIndicator,
237 	uint32 flags)
238 {
239 	if (popupIndicator) {
240 		BRect leftRect(rect);
241 		leftRect.right -= 10;
242 
243 		BRect rightRect(rect);
244 		rightRect.left = rightRect.right - 9;
245 
246 		DrawMenuFieldBackground(view, leftRect, updateRect, base, flags,
247 			B_LEFT_BORDER | B_TOP_BORDER | B_BOTTOM_BORDER);
248 
249 		rgb_color indicatorBase;
250 		rgb_color markColor;
251 		if (flags & B_DISABLED) {
252 			indicatorBase = tint_color(base, 1.05);
253 			markColor = tint_color(base, 1.35);
254 		} else {
255 			indicatorBase = tint_color(base, 1.12);
256 			markColor = tint_color(base, 1.65);
257 		}
258 
259 		DrawMenuFieldBackground(view, rightRect, updateRect, indicatorBase,
260 			flags, B_RIGHT_BORDER | B_TOP_BORDER | B_BOTTOM_BORDER);
261 
262 		// popup marker
263 		BPoint center(roundf((rightRect.left + rightRect.right) / 2.0),
264 					  roundf((rightRect.top + rightRect.bottom) / 2.0));
265 		BPoint triangle[3];
266 		triangle[0] = center + BPoint(-2.5, -0.5);
267 		triangle[1] = center + BPoint(2.5, -0.5);
268 		triangle[2] = center + BPoint(0.0, 2.0);
269 
270 		uint32 viewFlags = view->Flags();
271 		view->SetFlags(viewFlags | B_SUBPIXEL_PRECISE);
272 
273 		view->SetHighColor(markColor);
274 		view->FillTriangle(triangle[0], triangle[1], triangle[2]);
275 
276 		view->SetFlags(viewFlags);
277 
278 		rect = leftRect;
279 	} else {
280 		DrawMenuFieldBackground(view, rect, updateRect, base, flags);
281 	}
282 }
283 
284 void
285 BControlLook::DrawMenuFieldBackground(BView* view, BRect& rect,
286 	const BRect& updateRect, const rgb_color& base, uint32 flags,
287 	uint32 borders)
288 {
289 	if (!rect.IsValid() || !updateRect.Intersects(rect))
290 		return;
291 
292 	// the surface edges
293 
294 	// colors
295 	rgb_color cornerColor = tint_color(base, 0.85);
296 	rgb_color bevelColor1 = tint_color(base, 0.3);
297 	rgb_color bevelColor2 = tint_color(base, 0.5);
298 	rgb_color bevelColor3 = tint_color(base, 1.03);
299 
300 	if (flags & B_DISABLED) {
301 		cornerColor = tint_color(base, 0.8);
302 		bevelColor1 = tint_color(base, 0.7);
303 		bevelColor2 = tint_color(base, 0.8);
304 		bevelColor3 = tint_color(base, 1.01);
305 	} else {
306 		cornerColor = tint_color(base, 0.85);
307 		bevelColor1 = tint_color(base, 0.3);
308 		bevelColor2 = tint_color(base, 0.5);
309 		bevelColor3 = tint_color(base, 1.03);
310 	}
311 
312 	_DrawFrame(view, rect,
313 		bevelColor2, bevelColor1,
314 		bevelColor3, bevelColor3,
315 		cornerColor, cornerColor,
316 		borders);
317 
318 	// the actual surface top
319 
320 	float topTint = 0.49;
321 	float middleTint1 = 0.62;
322 	float middleTint2 = 0.76;
323 	float bottomTint = 0.90;
324 
325 	if (flags & B_DISABLED) {
326 		topTint = (topTint + B_NO_TINT) / 2;
327 		middleTint1 = (middleTint1 + B_NO_TINT) / 2;
328 		middleTint2 = (middleTint2 + B_NO_TINT) / 2;
329 		bottomTint = (bottomTint + B_NO_TINT) / 2;
330 	} else if (flags & B_HOVER) {
331 		static const float kHoverTintFactor = 0.85;
332 		topTint *= kHoverTintFactor;
333 		middleTint1 *= kHoverTintFactor;
334 		middleTint2 *= kHoverTintFactor;
335 		bottomTint *= kHoverTintFactor;
336 	}
337 
338 	_FillGlossyGradient(view, rect, base, topTint, middleTint1,
339 		middleTint2, bottomTint);
340 }
341 
342 void
343 BControlLook::DrawMenuBackground(BView* view, BRect& rect,
344 	const BRect& updateRect, const rgb_color& base, uint32 flags,
345 	uint32 borders)
346 {
347 	if (!rect.IsValid() || !updateRect.Intersects(rect))
348 		return;
349 
350 	// the surface edges
351 
352 	rgb_color bevelLightColor;
353 	rgb_color bevelShadowColor;
354 	rgb_color background = tint_color(base, 0.75);
355 
356 	if (flags & B_DISABLED) {
357 		bevelLightColor = tint_color(background, 0.80);
358 		bevelShadowColor = tint_color(background, 1.07);
359 	} else {
360 		bevelLightColor = tint_color(background, 0.6);
361 		bevelShadowColor = tint_color(background, 1.12);
362 	}
363 
364 	_DrawFrame(view, rect,
365 		bevelLightColor, bevelLightColor,
366 		bevelShadowColor, bevelShadowColor,
367 		borders);
368 
369 	// the actual surface top
370 
371 	view->SetHighColor(background);
372 	view->FillRect(rect);
373 }
374 
375 
376 void
377 BControlLook::DrawMenuItemBackground(BView* view, BRect& rect,
378 	const BRect& updateRect, const rgb_color& base, uint32 flags,
379 	uint32 borders)
380 {
381 	if (!rect.IsValid() || !updateRect.Intersects(rect))
382 		return;
383 
384 	// the surface edges
385 
386 	float topTint;
387 	float bottomTint;
388 	rgb_color selectedColor = base;
389 
390 	if (flags & B_ACTIVATED) {
391 		topTint = 0.9;
392 		bottomTint = 1.05;
393 		selectedColor = tint_color(base, 1.26);
394 	} else if (flags & B_DISABLED) {
395 		topTint = 0.80;
396 		bottomTint = 1.07;
397 	} else {
398 		topTint = 0.6;
399 		bottomTint = 1.12;
400 	}
401 
402 	rgb_color bevelLightColor = tint_color(selectedColor, topTint);
403 	rgb_color bevelShadowColor = tint_color(selectedColor, bottomTint);
404 
405 	_DrawFrame(view, rect,
406 		bevelLightColor, bevelLightColor,
407 		bevelShadowColor, bevelShadowColor,
408 		borders);
409 
410 	// the actual surface top
411 
412 	view->SetLowColor(selectedColor);
413 //	_FillGradient(view, rect, selectedColor, topTint, bottomTint);
414 	_FillGradient(view, rect, selectedColor, bottomTint, topTint);
415 }
416 
417 
418 void
419 BControlLook::DrawStatusBar(BView* view, BRect& rect, const BRect& updateRect,
420 	const rgb_color& base, const rgb_color& barColor, float progressPosition)
421 {
422 	if (!rect.Intersects(updateRect))
423 		return;
424 
425 	_DrawOuterResessedFrame(view, rect, base, 0.6);
426 
427 	// colors
428 	rgb_color dark1BorderColor = tint_color(base, 1.3);
429 	rgb_color dark2BorderColor = tint_color(base, 1.2);
430 	rgb_color dark1FilledBorderColor = tint_color(barColor, 1.20);
431 	rgb_color dark2FilledBorderColor = tint_color(barColor, 1.45);
432 
433 	BRect filledRect(rect);
434 	filledRect.right = progressPosition - 1;
435 
436 	BRect nonfilledRect(rect);
437 	nonfilledRect.left = progressPosition;
438 
439 	bool filledSurface = filledRect.Width() > 0;
440 	bool nonfilledSurface = nonfilledRect.Width() > 0;
441 
442 	if (filledSurface) {
443 		_DrawFrame(view, filledRect,
444 			dark1FilledBorderColor, dark1FilledBorderColor,
445 			dark2FilledBorderColor, dark2FilledBorderColor);
446 
447 		_FillGlossyGradient(view, filledRect, barColor, 0.55, 0.68, 0.76, 0.90);
448 	}
449 
450 	if (nonfilledSurface) {
451 		_DrawFrame(view, nonfilledRect, dark1BorderColor, dark1BorderColor,
452 			dark2BorderColor, dark2BorderColor,
453 			B_TOP_BORDER | B_BOTTOM_BORDER | B_RIGHT_BORDER);
454 
455 		if (nonfilledRect.left < nonfilledRect.right) {
456 			// shadow from fill bar, or left border
457 			rgb_color leftBorder = dark1BorderColor;
458 			if (filledSurface)
459 				leftBorder = tint_color(base, 0.50);
460 			view->SetHighColor(leftBorder);
461 			view->StrokeLine(nonfilledRect.LeftTop(),
462 				nonfilledRect.LeftBottom());
463 			nonfilledRect.left++;
464 		}
465 
466 		_FillGradient(view, nonfilledRect, base, 0.25, 0.06);
467 	}
468 }
469 
470 
471 void
472 BControlLook::DrawCheckBox(BView* view, BRect& rect, const BRect& updateRect,
473 	const rgb_color& base, uint32 flags)
474 {
475 	if (!rect.Intersects(updateRect))
476 		return;
477 
478 	rgb_color dark1BorderColor;
479 	rgb_color dark2BorderColor;
480 	rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
481 
482 	if (flags & B_DISABLED) {
483 		_DrawOuterResessedFrame(view, rect, base, 0.0, 1.0, flags);
484 
485 		dark1BorderColor = tint_color(base, 1.15);
486 		dark2BorderColor = tint_color(base, 1.15);
487 	} else if (flags & B_CLICKED) {
488 		dark1BorderColor = tint_color(base, 1.50);
489 		dark2BorderColor = tint_color(base, 1.48);
490 
491 		_DrawFrame(view, rect,
492 			dark1BorderColor, dark1BorderColor,
493 			dark2BorderColor, dark2BorderColor);
494 
495 		dark2BorderColor = dark1BorderColor;
496 	} else {
497 		_DrawOuterResessedFrame(view, rect, base, 0.6, 1.0, flags);
498 
499 		dark1BorderColor = tint_color(base, 1.40);
500 		dark2BorderColor = tint_color(base, 1.38);
501 	}
502 
503 	if (flags & B_FOCUSED) {
504 		dark1BorderColor = navigationColor;
505 		dark2BorderColor = navigationColor;
506 	}
507 
508 	_DrawFrame(view, rect,
509 		dark1BorderColor, dark1BorderColor,
510 		dark2BorderColor, dark2BorderColor);
511 
512 	if (flags & B_DISABLED) {
513 		_FillGradient(view, rect, base, 0.4, 0.2);
514 	} else {
515 		_FillGradient(view, rect, base, 0.15, 0.0);
516 	}
517 
518 	rgb_color markColor;
519 	if (_RadioButtonAndCheckBoxMarkColor(base, markColor, flags)) {
520 		view->SetHighColor(markColor);
521 
522 		rect.InsetBy(2, 2);
523 		view->SetPenSize(max_c(1.0, ceilf(rect.Width() / 3.5)));
524 		view->SetDrawingMode(B_OP_OVER);
525 
526 		view->StrokeLine(rect.LeftTop(), rect.RightBottom());
527 		view->StrokeLine(rect.LeftBottom(), rect.RightTop());
528 	}
529 }
530 
531 
532 void
533 BControlLook::DrawRadioButton(BView* view, BRect& rect, const BRect& updateRect,
534 	const rgb_color& base, uint32 flags)
535 {
536 	if (!rect.Intersects(updateRect))
537 		return;
538 
539 	rgb_color borderColor;
540 	rgb_color bevelLight;
541 	rgb_color bevelShadow;
542 	rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
543 
544 	if (flags & B_DISABLED) {
545 		borderColor = tint_color(base, 1.15);
546 		bevelLight = base;
547 		bevelShadow = base;
548 	} else if (flags & B_CLICKED) {
549 		borderColor = tint_color(base, 1.50);
550 		bevelLight = borderColor;
551 		bevelShadow = borderColor;
552 	} else {
553 		borderColor = tint_color(base, 1.45);
554 		bevelLight = tint_color(base, 0.55);
555 		bevelShadow = tint_color(base, 1.11);
556 	}
557 
558 	if (flags & B_FOCUSED) {
559 		borderColor = navigationColor;
560 	}
561 
562 	BGradientLinear bevelGradient;
563 	bevelGradient.AddColor(bevelShadow, 0);
564 	bevelGradient.AddColor(bevelLight, 255);
565 	bevelGradient.SetStart(rect.LeftTop());
566 	bevelGradient.SetEnd(rect.RightBottom());
567 
568 	view->FillEllipse(rect, bevelGradient);
569 	rect.InsetBy(1, 1);
570 
571 	bevelGradient.MakeEmpty();
572 	bevelGradient.AddColor(borderColor, 0);
573 	bevelGradient.AddColor(tint_color(borderColor, 0.8), 255);
574 	view->FillEllipse(rect, bevelGradient);
575 	rect.InsetBy(1, 1);
576 
577 	float topTint;
578 	float bottomTint;
579 	if (flags & B_DISABLED) {
580 		topTint = 0.4;
581 		bottomTint = 0.2;
582 	} else {
583 		topTint = 0.15;
584 		bottomTint = 0.0;
585 	}
586 
587 	BGradientLinear gradient;
588 	_MakeGradient(gradient, rect, base, topTint, bottomTint);
589 	view->FillEllipse(rect, gradient);
590 
591 	rgb_color markColor;
592 	if (_RadioButtonAndCheckBoxMarkColor(base, markColor, flags)) {
593 		view->SetHighColor(markColor);
594 		rect.InsetBy(3, 3);
595 		view->FillEllipse(rect);
596 	}
597 }
598 
599 
600 void
601 BControlLook::DrawScrollBarBackground(BView* view, BRect& rect1, BRect& rect2,
602 	const BRect& updateRect, const rgb_color& base, uint32 flags,
603 	enum orientation orientation)
604 {
605 	DrawScrollBarBackground(view, rect1, updateRect, base, flags, orientation);
606 	DrawScrollBarBackground(view, rect2, updateRect, base, flags, orientation);
607 }
608 
609 void
610 BControlLook::DrawScrollBarBackground(BView* view, BRect& rect,
611 	const BRect& updateRect, const rgb_color& base, uint32 flags,
612 	enum orientation orientation)
613 {
614 	if (!rect.IsValid() || !rect.Intersects(updateRect))
615 		return;
616 
617 	float gradient1Tint;
618 	float gradient2Tint;
619 	float darkEdge1Tint;
620 	float darkEdge2Tint;
621 	float shadowTint;
622 
623 	if (flags & B_DISABLED) {
624 		gradient1Tint = 0.9;
625 		gradient2Tint = 0.8;
626 		darkEdge1Tint = B_DARKEN_2_TINT;
627 		darkEdge2Tint = B_DARKEN_2_TINT;
628 		shadowTint = gradient1Tint;
629 	} else {
630 		gradient1Tint = 1.10;
631 		gradient2Tint = 1.05;
632 		darkEdge1Tint = B_DARKEN_3_TINT;
633 		darkEdge2Tint = B_DARKEN_2_TINT;
634 		shadowTint = gradient1Tint;
635 	}
636 
637 	rgb_color darkEdge1 = tint_color(base, darkEdge1Tint);
638 	rgb_color darkEdge2 = tint_color(base, darkEdge2Tint);
639 	rgb_color shadow = tint_color(base, shadowTint);
640 
641 	if (orientation == B_HORIZONTAL) {
642 		// dark vertical line on left edge
643 		if (rect.Width() > 0) {
644 			view->SetHighColor(darkEdge1);
645 			view->StrokeLine(rect.LeftTop(), rect.LeftBottom());
646 			rect.left++;
647 		}
648 		// dark vertical line on right edge
649 		if (rect.Width() >= 0) {
650 			view->SetHighColor(darkEdge2);
651 			view->StrokeLine(rect.RightTop(), rect.RightBottom());
652 			rect.right--;
653 		}
654 		// vertical shadow line after left edge
655 		if (rect.Width() >= 0) {
656 			view->SetHighColor(shadow);
657 			view->StrokeLine(rect.LeftTop(), rect.LeftBottom());
658 			rect.left++;
659 		}
660 		// fill
661 		if (rect.Width() >= 0) {
662 			_FillGradient(view, rect, base, gradient1Tint, gradient2Tint,
663 				orientation);
664 		}
665 	} else {
666 		// dark vertical line on top edge
667 		if (rect.Height() > 0) {
668 			view->SetHighColor(darkEdge1);
669 			view->StrokeLine(rect.LeftTop(), rect.RightTop());
670 			rect.top++;
671 		}
672 		// dark vertical line on bottom edge
673 		if (rect.Height() >= 0) {
674 			view->SetHighColor(darkEdge2);
675 			view->StrokeLine(rect.LeftBottom(), rect.RightBottom());
676 			rect.bottom--;
677 		}
678 		// horizontal shadow line after top edge
679 		if (rect.Height() >= 0) {
680 			view->SetHighColor(shadow);
681 			view->StrokeLine(rect.LeftTop(), rect.RightTop());
682 			rect.top++;
683 		}
684 		// fill
685 		if (rect.Height() >= 0) {
686 			_FillGradient(view, rect, base, gradient1Tint, gradient2Tint,
687 				orientation);
688 		}
689 	}
690 }
691 
692 
693 void
694 BControlLook::DrawScrollViewFrame(BView* view, BRect& rect,
695 	const BRect& updateRect, BRect verticalScrollBarFrame,
696 	BRect horizontalScrollBarFrame, const rgb_color& base,
697 	border_style border, uint32 flags, uint32 _borders)
698 {
699 	if (border == B_NO_BORDER)
700 		return;
701 
702 	bool excludeScrollCorner = border == B_FANCY_BORDER
703 		&& horizontalScrollBarFrame.IsValid()
704 		&& verticalScrollBarFrame.IsValid();
705 
706 	uint32 borders = _borders;
707 	if (excludeScrollCorner) {
708 		rect.bottom = horizontalScrollBarFrame.top;
709 		rect.right = verticalScrollBarFrame.left;
710 		borders &= ~(B_RIGHT_BORDER | B_BOTTOM_BORDER);
711 	}
712 
713 	rgb_color scrollbarFrameColor = tint_color(base, B_DARKEN_2_TINT);
714 
715 	if (border == B_FANCY_BORDER)
716 		_DrawOuterResessedFrame(view, rect, base, 1.0, 1.0, flags, borders);
717 
718 	if (flags & B_FOCUSED) {
719 		rgb_color focusColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
720 		_DrawFrame(view, rect, focusColor, focusColor, focusColor, focusColor,
721 			borders);
722 	} else {
723 		_DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor,
724 			scrollbarFrameColor, scrollbarFrameColor, borders);
725 	}
726 
727 	if (excludeScrollCorner) {
728 		horizontalScrollBarFrame.InsetBy(-1, -1);
729 		// do not overdraw the top edge
730 		horizontalScrollBarFrame.top += 2;
731 		borders = _borders;
732 		borders &= ~B_TOP_BORDER;
733 		_DrawOuterResessedFrame(view, horizontalScrollBarFrame, base,
734 			1.0, 1.0, flags, borders);
735 		_DrawFrame(view, horizontalScrollBarFrame, scrollbarFrameColor,
736 			scrollbarFrameColor, scrollbarFrameColor, scrollbarFrameColor,
737 			borders);
738 
739 
740 		verticalScrollBarFrame.InsetBy(-1, -1);
741 		// do not overdraw the left edge
742 		verticalScrollBarFrame.left += 2;
743 		borders = _borders;
744 		borders &= ~B_LEFT_BORDER;
745 		_DrawOuterResessedFrame(view, verticalScrollBarFrame, base,
746 			1.0, 1.0, flags, borders);
747 		_DrawFrame(view, verticalScrollBarFrame, scrollbarFrameColor,
748 			scrollbarFrameColor, scrollbarFrameColor, scrollbarFrameColor,
749 			borders);
750 	}
751 }
752 
753 
754 void
755 BControlLook::DrawArrowShape(BView* view, BRect& rect, const BRect& updateRect,
756 	const rgb_color& base, uint32 direction, uint32 flags, float tint)
757 {
758 	BPoint tri1, tri2, tri3;
759 	float hInset = rect.Width() / 3;
760 	float vInset = rect.Height() / 3;
761 	rect.InsetBy(hInset, vInset);
762 
763 	switch (direction) {
764 		case B_LEFT_ARROW:
765 			tri1.Set(rect.right, rect.top);
766 			tri2.Set(rect.right - rect.Width() / 1.33,
767 				(rect.top + rect.bottom + 1) /2 );
768 			tri3.Set(rect.right, rect.bottom + 1);
769 			break;
770 		case B_RIGHT_ARROW:
771 			tri1.Set(rect.left, rect.bottom + 1);
772 			tri2.Set(rect.left + rect.Width() / 1.33,
773 				(rect.top + rect.bottom + 1) / 2);
774 			tri3.Set(rect.left, rect.top);
775 			break;
776 		case B_UP_ARROW:
777 			tri1.Set(rect.left, rect.bottom);
778 			tri2.Set((rect.left + rect.right + 1) / 2,
779 				rect.bottom - rect.Height() / 1.33);
780 			tri3.Set(rect.right + 1, rect.bottom);
781 			break;
782 		case B_DOWN_ARROW:
783 		default:
784 			tri1.Set(rect.left, rect.top);
785 			tri2.Set((rect.left + rect.right + 1) / 2,
786 				rect.top + rect.Height() / 1.33);
787 			tri3.Set(rect.right + 1, rect.top);
788 			break;
789 	}
790 	// offset triangle if down
791 	if (flags & B_ACTIVATED)
792 		view->MovePenTo(BPoint(1, 1));
793 	else
794 		view->MovePenTo(BPoint(0, 0));
795 
796 	BShape arrowShape;
797 	arrowShape.MoveTo(tri1);
798 	arrowShape.LineTo(tri2);
799 	arrowShape.LineTo(tri3);
800 
801 	if (flags & B_DISABLED)
802 		tint = (tint + B_NO_TINT + B_NO_TINT) / 3;
803 
804 	view->SetHighColor(tint_color(base, tint));
805 
806 	float penSize = view->PenSize();
807 	drawing_mode mode = view->DrawingMode();
808 
809 	view->SetPenSize(ceilf(hInset / 2.0));
810 	view->SetDrawingMode(B_OP_OVER);
811 	view->StrokeShape(&arrowShape);
812 
813 	view->SetPenSize(penSize);
814 	view->SetDrawingMode(mode);
815 }
816 
817 
818 rgb_color
819 BControlLook::SliderBarColor(const rgb_color& base)
820 {
821 	return tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_1_TINT);
822 }
823 
824 
825 void
826 BControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect,
827 	const rgb_color& base, rgb_color leftFillColor, rgb_color rightFillColor,
828 	float sliderScale, uint32 flags, enum orientation orientation)
829 {
830 	if (!rect.IsValid() || !rect.Intersects(updateRect))
831 		return;
832 
833 	// separate the bar in two sides
834 	float sliderPosition;
835 	BRect leftBarSide = rect;
836 	BRect rightBarSide = rect;
837 
838 	if (orientation == B_HORIZONTAL) {
839 		sliderPosition = floorf(rect.left + 2 + (rect.Width() - 2)
840 			* sliderScale);
841 		leftBarSide.right = sliderPosition - 1;
842 		rightBarSide.left = sliderPosition;
843 	} else {
844 		sliderPosition = floorf(rect.top + 2 + (rect.Height() - 2)
845 			* sliderScale);
846 		leftBarSide.bottom = sliderPosition - 1;
847 		rightBarSide.top = sliderPosition;
848 	}
849 
850 	// fill the background for the corners, exclude the middle bar for now
851 	BRegion region(rect);
852 	region.Exclude(rightBarSide);
853 	view->ConstrainClippingRegion(&region);
854 
855 	view->PushState();
856 
857 	DrawSliderBar(view, rect, updateRect, base, leftFillColor, flags,
858 		orientation);
859 
860 	view->PopState();
861 
862 	region.Set(rect);
863 	region.Exclude(leftBarSide);
864 	view->ConstrainClippingRegion(&region);
865 
866 	view->PushState();
867 
868 	DrawSliderBar(view, rect, updateRect, base, rightFillColor, flags,
869 		orientation);
870 
871 	view->PopState();
872 
873 	view->ConstrainClippingRegion(NULL);
874 }
875 
876 
877 void
878 BControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect,
879 	const rgb_color& base, rgb_color fillColor, uint32 flags,
880 	enum orientation orientation)
881 {
882 	if (!rect.IsValid() || !rect.Intersects(updateRect))
883 		return;
884 
885 	// separate the rect into corners
886 	BRect leftCorner(rect);
887 	BRect rightCorner(rect);
888 	BRect barRect(rect);
889 
890 	if (orientation == B_HORIZONTAL) {
891 		leftCorner.right = leftCorner.left + leftCorner.Height();
892 		rightCorner.left = rightCorner.right - rightCorner.Height();
893 		barRect.left += ceilf(barRect.Height() / 2);
894 		barRect.right -= ceilf(barRect.Height() / 2);
895 	} else {
896 		leftCorner.bottom = leftCorner.top + leftCorner.Width();
897 		rightCorner.top = rightCorner.bottom - rightCorner.Width();
898 		barRect.top += ceilf(barRect.Width() / 2);
899 		barRect.bottom -= ceilf(barRect.Width() / 2);
900 	}
901 
902 	// fill the background for the corners, exclude the middle bar for now
903 	BRegion region(rect);
904 	region.Exclude(barRect);
905 	view->ConstrainClippingRegion(&region);
906 
907 	view->SetHighColor(base);
908 	view->FillRect(rect);
909 
910 	// figure out the tints to be used
911 	float edgeLightTint;
912 	float edgeShadowTint;
913 	float frameLightTint;
914 	float frameShadowTint;
915 	float fillLightTint;
916 	float fillShadowTint;
917 
918 	if (flags & B_DISABLED) {
919 		edgeLightTint = 1.0;
920 		edgeShadowTint = 1.0;
921 		frameLightTint = 1.20;
922 		frameShadowTint = 1.25;
923 		fillLightTint = 0.9;
924 		fillShadowTint = 1.05;
925 
926 		fillColor.red = uint8(fillColor.red * 0.4 + base.red * 0.6);
927 		fillColor.green = uint8(fillColor.green * 0.4 + base.green * 0.6);
928 		fillColor.blue = uint8(fillColor.blue * 0.4 + base.blue * 0.6);
929 	} else {
930 		edgeLightTint = 0.65;
931 		edgeShadowTint = 1.07;
932 		frameLightTint = 1.40;
933 		frameShadowTint = 1.50;
934 		fillLightTint = 0.8;
935 		fillShadowTint = 1.1;
936 	}
937 
938 	rgb_color edgeLightColor = tint_color(base, edgeLightTint);
939 	rgb_color edgeShadowColor = tint_color(base, edgeShadowTint);
940 	rgb_color frameLightColor = tint_color(fillColor, frameLightTint);
941 	rgb_color frameShadowColor = tint_color(fillColor, frameShadowTint);
942 	rgb_color fillLightColor = tint_color(fillColor, fillLightTint);
943 	rgb_color fillShadowColor = tint_color(fillColor, fillShadowTint);
944 
945 	if (orientation == B_HORIZONTAL) {
946 		_DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor,
947 			edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
948 			fillShadowColor, 1.0, 1.0, 0.0, -1.0, orientation);
949 
950 		_DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor,
951 			edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
952 			fillShadowColor, 0.0, 1.0, -1.0, -1.0, orientation);
953 	} else {
954 		_DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor,
955 			edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
956 			fillShadowColor, 1.0, 1.0, -1.0, 0.0, orientation);
957 
958 		_DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor,
959 			edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
960 			fillShadowColor, 1.0, 0.0, -1.0, -1.0, orientation);
961 	}
962 
963 	view->ConstrainClippingRegion(NULL);
964 
965 	view->BeginLineArray(4);
966 	if (orientation == B_HORIZONTAL) {
967 		view->AddLine(barRect.LeftTop(), barRect.RightTop(), edgeShadowColor);
968 		view->AddLine(barRect.LeftBottom(), barRect.RightBottom(),
969 			edgeLightColor);
970 		barRect.InsetBy(0, 1);
971 		view->AddLine(barRect.LeftTop(), barRect.RightTop(), frameShadowColor);
972 		view->AddLine(barRect.LeftBottom(), barRect.RightBottom(),
973 			frameLightColor);
974 		barRect.InsetBy(0, 1);
975 	} else {
976 		view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), edgeShadowColor);
977 		view->AddLine(barRect.RightTop(), barRect.RightBottom(),
978 			edgeLightColor);
979 		barRect.InsetBy(1, 0);
980 		view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), frameShadowColor);
981 		view->AddLine(barRect.RightTop(), barRect.RightBottom(),
982 			frameLightColor);
983 		barRect.InsetBy(1, 0);
984 	}
985 	view->EndLineArray();
986 
987 	_FillGradient(view, barRect, fillColor, fillShadowTint, fillLightTint,
988 		orientation);
989 }
990 
991 
992 void
993 BControlLook::DrawSliderThumb(BView* view, BRect& rect, const BRect& updateRect,
994 	const rgb_color& base, uint32 flags, enum orientation orientation)
995 {
996 	if (!rect.IsValid() || !rect.Intersects(updateRect))
997 		return;
998 
999 	// figure out frame color
1000 	rgb_color frameLightColor;
1001 	rgb_color frameShadowColor;
1002 	rgb_color shadowColor = (rgb_color){ 0, 0, 0, 60 };
1003 
1004 	if (flags & B_FOCUSED) {
1005 		// focused
1006 		frameLightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1007 		frameShadowColor = frameLightColor;
1008 	} else {
1009 		// figure out the tints to be used
1010 		float frameLightTint;
1011 		float frameShadowTint;
1012 
1013 		if (flags & B_DISABLED) {
1014 			frameLightTint = 1.30;
1015 			frameShadowTint = 1.35;
1016 			shadowColor.alpha = 30;
1017 		} else {
1018 			frameLightTint = 1.6;
1019 			frameShadowTint = 1.65;
1020 		}
1021 
1022 		frameLightColor = tint_color(base, frameLightTint);
1023 		frameShadowColor = tint_color(base, frameShadowTint);
1024 	}
1025 
1026 	BRect originalRect(rect);
1027 	rect.right--;
1028 	rect.bottom--;
1029 
1030 	_DrawFrame(view, rect, frameLightColor, frameLightColor,
1031 		frameShadowColor, frameShadowColor);
1032 
1033 	flags &= ~B_ACTIVATED;
1034 	DrawButtonBackground(view, rect, updateRect, base, flags);
1035 
1036 	// thumb shadow
1037 	view->SetDrawingMode(B_OP_ALPHA);
1038 	view->SetHighColor(shadowColor);
1039 	originalRect.left++;
1040 	originalRect.top++;
1041 	view->StrokeLine(originalRect.LeftBottom(), originalRect.RightBottom());
1042 	originalRect.bottom--;
1043 	view->StrokeLine(originalRect.RightTop(), originalRect.RightBottom());
1044 
1045 	// thumb edge
1046 	if (orientation == B_HORIZONTAL) {
1047 		rect.InsetBy(0, floorf(rect.Height() / 4));
1048 		rect.left = floorf((rect.left + rect.right) / 2);
1049 		rect.right = rect.left + 1;
1050 		shadowColor = tint_color(base, B_DARKEN_2_TINT);
1051 		shadowColor.alpha = 128;
1052 		view->SetHighColor(shadowColor);
1053 		view->StrokeLine(rect.LeftTop(), rect.LeftBottom());
1054 		rgb_color lightColor = tint_color(base, B_LIGHTEN_2_TINT);
1055 		lightColor.alpha = 128;
1056 		view->SetHighColor(lightColor);
1057 		view->StrokeLine(rect.RightTop(), rect.RightBottom());
1058 	} else {
1059 		rect.InsetBy(floorf(rect.Width() / 4), 0);
1060 		rect.top = floorf((rect.top + rect.bottom) / 2);
1061 		rect.bottom = rect.top + 1;
1062 		shadowColor = tint_color(base, B_DARKEN_2_TINT);
1063 		shadowColor.alpha = 128;
1064 		view->SetHighColor(shadowColor);
1065 		view->StrokeLine(rect.LeftTop(), rect.RightTop());
1066 		rgb_color lightColor = tint_color(base, B_LIGHTEN_2_TINT);
1067 		lightColor.alpha = 128;
1068 		view->SetHighColor(lightColor);
1069 		view->StrokeLine(rect.LeftBottom(), rect.RightBottom());
1070 	}
1071 
1072 	view->SetDrawingMode(B_OP_COPY);
1073 }
1074 
1075 
1076 void
1077 BControlLook::DrawSliderTriangle(BView* view, BRect& rect,
1078 	const BRect& updateRect, const rgb_color& base, uint32 flags,
1079 	enum orientation orientation)
1080 {
1081 	DrawSliderTriangle(view, rect, updateRect, base, base, flags, orientation);
1082 }
1083 
1084 
1085 void
1086 BControlLook::DrawSliderTriangle(BView* view, BRect& rect,
1087 	const BRect& updateRect, const rgb_color& base, const rgb_color& fill,
1088 	uint32 flags, enum orientation orientation)
1089 {
1090 	if (!rect.IsValid() || !rect.Intersects(updateRect))
1091 		return;
1092 
1093 	// figure out frame color
1094 	rgb_color frameLightColor;
1095 	rgb_color frameShadowColor;
1096 	rgb_color shadowColor = (rgb_color){ 0, 0, 0, 60 };
1097 
1098 	float topTint = 0.49;
1099 	float middleTint1 = 0.62;
1100 	float middleTint2 = 0.76;
1101 	float bottomTint = 0.90;
1102 
1103 	if (flags & B_DISABLED) {
1104 		topTint = (topTint + B_NO_TINT) / 2;
1105 		middleTint1 = (middleTint1 + B_NO_TINT) / 2;
1106 		middleTint2 = (middleTint2 + B_NO_TINT) / 2;
1107 		bottomTint = (bottomTint + B_NO_TINT) / 2;
1108 	} else if (flags & B_HOVER) {
1109 		static const float kHoverTintFactor = 0.85;
1110 		topTint *= kHoverTintFactor;
1111 		middleTint1 *= kHoverTintFactor;
1112 		middleTint2 *= kHoverTintFactor;
1113 		bottomTint *= kHoverTintFactor;
1114 	}
1115 
1116 	if (flags & B_FOCUSED) {
1117 		// focused
1118 		frameLightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1119 		frameShadowColor = frameLightColor;
1120 	} else {
1121 		// figure out the tints to be used
1122 		float frameLightTint;
1123 		float frameShadowTint;
1124 
1125 		if (flags & B_DISABLED) {
1126 			frameLightTint = 1.30;
1127 			frameShadowTint = 1.35;
1128 			shadowColor.alpha = 30;
1129 		} else {
1130 			frameLightTint = 1.6;
1131 			frameShadowTint = 1.65;
1132 		}
1133 
1134 		frameLightColor = tint_color(base, frameLightTint);
1135 		frameShadowColor = tint_color(base, frameShadowTint);
1136 	}
1137 
1138 	// make room for the shadow
1139 	rect.right--;
1140 	rect.bottom--;
1141 
1142 	uint32 viewFlags = view->Flags();
1143 	view->SetFlags(viewFlags | B_SUBPIXEL_PRECISE);
1144 	view->SetLineMode(B_ROUND_CAP, B_ROUND_JOIN);
1145 
1146 	float center = (rect.left + rect.right) / 2;
1147 
1148 	BShape shape;
1149 	shape.MoveTo(BPoint(rect.left + 0.5, rect.bottom + 0.5));
1150 	shape.LineTo(BPoint(rect.right + 0.5, rect.bottom + 0.5));
1151 	shape.LineTo(BPoint(rect.right + 0.5, rect.bottom - 1 + 0.5));
1152 	shape.LineTo(BPoint(center + 0.5, rect.top + 0.5));
1153 	shape.LineTo(BPoint(rect.left + 0.5, rect.bottom - 1 + 0.5));
1154 	shape.Close();
1155 
1156 	view->MovePenTo(BPoint(1, 1));
1157 
1158 	view->SetDrawingMode(B_OP_ALPHA);
1159 	view->SetHighColor(shadowColor);
1160 	view->StrokeShape(&shape);
1161 
1162 	view->MovePenTo(B_ORIGIN);
1163 
1164 	view->SetDrawingMode(B_OP_COPY);
1165 	view->SetHighColor(frameLightColor);
1166 	view->StrokeShape(&shape);
1167 
1168 	rect.InsetBy(1, 1);
1169 	shape.Clear();
1170 	shape.MoveTo(BPoint(rect.left, rect.bottom + 1));
1171 	shape.LineTo(BPoint(rect.right + 1, rect.bottom + 1));
1172 	shape.LineTo(BPoint(center + 0.5, rect.top));
1173 	shape.Close();
1174 
1175 	BGradientLinear gradient;
1176 	if (flags & B_DISABLED) {
1177 		_MakeGradient(gradient, rect, fill, topTint, bottomTint);
1178 	} else {
1179 		_MakeGlossyGradient(gradient, rect, fill, topTint, middleTint1,
1180 			middleTint2, bottomTint);
1181 	}
1182 
1183 	view->FillShape(&shape, gradient);
1184 
1185 	view->SetFlags(viewFlags);
1186 }
1187 
1188 
1189 void
1190 BControlLook::DrawSliderHashMarks(BView* view, BRect& rect,
1191 	const BRect& updateRect, const rgb_color& base, int32 count,
1192 	hash_mark_location location, uint32 flags, enum orientation orientation)
1193 {
1194 	if (!rect.IsValid() || !rect.Intersects(updateRect))
1195 		return;
1196 
1197 	rgb_color lightColor;
1198 	rgb_color darkColor;
1199 
1200 	if (flags & B_DISABLED) {
1201 		lightColor = tint_color(base, 0.9);
1202 		darkColor = tint_color(base, 1.07);
1203 	} else {
1204 		lightColor = tint_color(base, 0.8);
1205 		darkColor = tint_color(base, 1.14);
1206 	}
1207 
1208 	int32 hashMarkCount = max_c(count, 2);
1209 		// draw at least two hashmarks at min/max if
1210 		// fHashMarks != B_HASH_MARKS_NONE
1211 	float factor;
1212 	float startPos;
1213 	if (orientation == B_HORIZONTAL) {
1214 		factor = (rect.Width() - 2) / (hashMarkCount - 1);
1215 		startPos = rect.left + 1;
1216 	} else {
1217 		factor = (rect.Height() - 2) / (hashMarkCount - 1);
1218 		startPos = rect.top + 1;
1219 	}
1220 
1221 	if (location & B_HASH_MARKS_TOP) {
1222 		view->BeginLineArray(hashMarkCount * 2);
1223 
1224 		if (orientation == B_HORIZONTAL) {
1225 			float pos = startPos;
1226 			for (int32 i = 0; i < hashMarkCount; i++) {
1227 				view->AddLine(BPoint(pos, rect.top),
1228 							  BPoint(pos, rect.top + 4), darkColor);
1229 				view->AddLine(BPoint(pos + 1, rect.top),
1230 							  BPoint(pos + 1, rect.top + 4), lightColor);
1231 
1232 				pos += factor;
1233 			}
1234 		} else {
1235 			float pos = startPos;
1236 			for (int32 i = 0; i < hashMarkCount; i++) {
1237 				view->AddLine(BPoint(rect.left, pos),
1238 							  BPoint(rect.left + 4, pos), darkColor);
1239 				view->AddLine(BPoint(rect.left, pos + 1),
1240 							  BPoint(rect.left + 4, pos + 1), lightColor);
1241 
1242 				pos += factor;
1243 			}
1244 		}
1245 
1246 		view->EndLineArray();
1247 	}
1248 
1249 	if (location & B_HASH_MARKS_BOTTOM) {
1250 
1251 		view->BeginLineArray(hashMarkCount * 2);
1252 
1253 		if (orientation == B_HORIZONTAL) {
1254 			float pos = startPos;
1255 			for (int32 i = 0; i < hashMarkCount; i++) {
1256 				view->AddLine(BPoint(pos, rect.bottom - 4),
1257 							  BPoint(pos, rect.bottom), darkColor);
1258 				view->AddLine(BPoint(pos + 1, rect.bottom - 4),
1259 							  BPoint(pos + 1, rect.bottom), lightColor);
1260 
1261 				pos += factor;
1262 			}
1263 		} else {
1264 			float pos = startPos;
1265 			for (int32 i = 0; i < hashMarkCount; i++) {
1266 				view->AddLine(BPoint(rect.right - 4, pos),
1267 							  BPoint(rect.right, pos), darkColor);
1268 				view->AddLine(BPoint(rect.right - 4, pos + 1),
1269 							  BPoint(rect.right, pos + 1), lightColor);
1270 
1271 				pos += factor;
1272 			}
1273 		}
1274 
1275 		view->EndLineArray();
1276 	}
1277 }
1278 
1279 
1280 void
1281 BControlLook::DrawActiveTab(BView* view, BRect& rect, const BRect& updateRect,
1282 	const rgb_color& base, uint32 flags, uint32 borders)
1283 {
1284 	if (!rect.IsValid() || !rect.Intersects(updateRect))
1285 		return;
1286 
1287 	rgb_color edgeShadowColor;
1288 	rgb_color edgeLightColor;
1289 	rgb_color frameShadowColor;
1290 	rgb_color frameLightColor;
1291 	rgb_color bevelShadowColor;
1292 	rgb_color bevelLightColor;
1293 	BGradientLinear fillGradient;
1294 	fillGradient.SetStart(rect.LeftTop() + BPoint(3, 3));
1295 	fillGradient.SetEnd(rect.LeftBottom() + BPoint(3, -3));
1296 
1297 	if (flags & B_DISABLED) {
1298 		edgeShadowColor = base;
1299 		edgeLightColor = base;
1300 		frameShadowColor = tint_color(base, 1.30);
1301 		frameLightColor = tint_color(base, 1.25);
1302 		bevelShadowColor = tint_color(base, 1.07);
1303 		bevelLightColor = tint_color(base, 0.8);
1304 		fillGradient.AddColor(tint_color(base, 0.85), 0);
1305 		fillGradient.AddColor(base, 255);
1306 	} else {
1307 		edgeShadowColor = tint_color(base, 1.03);
1308 		edgeLightColor = tint_color(base, 0.80);
1309 		frameShadowColor = tint_color(base, 1.30);
1310 		frameLightColor = tint_color(base, 1.30);
1311 		bevelShadowColor = tint_color(base, 1.07);
1312 		bevelLightColor = tint_color(base, 0.6);
1313 		fillGradient.AddColor(tint_color(base, 0.75), 0);
1314 		fillGradient.AddColor(tint_color(base, 1.03), 255);
1315 	}
1316 
1317 	static const float kRoundCornerRadius = 4;
1318 
1319 	// left/top corner
1320 	BRect cornerRect(rect);
1321 	cornerRect.right = cornerRect.left + kRoundCornerRadius;
1322 	cornerRect.bottom = cornerRect.top + kRoundCornerRadius;
1323 
1324 	BRegion clipping(rect);
1325 	clipping.Exclude(cornerRect);
1326 
1327 	_DrawRoundCornerLeftTop(view, cornerRect, updateRect, base, edgeShadowColor,
1328 		frameLightColor, bevelLightColor, fillGradient);
1329 
1330 	// left/top corner
1331 	cornerRect.right = rect.right;
1332 	cornerRect.left = cornerRect.right - kRoundCornerRadius;
1333 
1334 	clipping.Exclude(cornerRect);
1335 
1336 	_DrawRoundCornerRightTop(view, cornerRect, updateRect, base, edgeShadowColor,
1337 		edgeLightColor, frameLightColor, frameShadowColor, bevelLightColor,
1338 		bevelShadowColor, fillGradient);
1339 
1340 	// rest of frame and fill
1341 	view->ConstrainClippingRegion(&clipping);
1342 
1343 	_DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, edgeLightColor,
1344 		edgeLightColor,
1345 		borders & (B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER));
1346 	if ((borders & B_LEFT_BORDER) == 0)
1347 		rect.left++;
1348 	if ((borders & B_RIGHT_BORDER) == 0)
1349 		rect.right--;
1350 
1351 	_DrawFrame(view, rect, frameLightColor, frameLightColor, frameShadowColor,
1352 		frameShadowColor, B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER);
1353 
1354 	_DrawFrame(view, rect, bevelLightColor, bevelLightColor, bevelShadowColor,
1355 		bevelShadowColor);
1356 
1357 	view->FillRect(rect, fillGradient);
1358 
1359 	view->ConstrainClippingRegion(NULL);
1360 }
1361 
1362 
1363 void
1364 BControlLook::DrawInactiveTab(BView* view, BRect& rect, const BRect& updateRect,
1365 	const rgb_color& base, uint32 flags, uint32 borders)
1366 {
1367 	if (!rect.IsValid() || !rect.Intersects(updateRect))
1368 		return;
1369 
1370 	rgb_color edgeShadowColor;
1371 	rgb_color edgeLightColor;
1372 	rgb_color frameShadowColor;
1373 	rgb_color frameLightColor;
1374 	rgb_color bevelShadowColor;
1375 	rgb_color bevelLightColor;
1376 	BGradientLinear fillGradient;
1377 	fillGradient.SetStart(rect.LeftTop() + BPoint(3, 3));
1378 	fillGradient.SetEnd(rect.LeftBottom() + BPoint(3, -3));
1379 
1380 	if (flags & B_DISABLED) {
1381 		edgeShadowColor = base;
1382 		edgeLightColor = base;
1383 		frameShadowColor = tint_color(base, 1.30);
1384 		frameLightColor = tint_color(base, 1.25);
1385 		bevelShadowColor = tint_color(base, 1.07);
1386 		bevelLightColor = tint_color(base, 0.8);
1387 		fillGradient.AddColor(tint_color(base, 0.85), 0);
1388 		fillGradient.AddColor(base, 255);
1389 	} else {
1390 		edgeShadowColor = tint_color(base, 1.03);
1391 		edgeLightColor = tint_color(base, 0.80);
1392 		frameShadowColor = tint_color(base, 1.30);
1393 		frameLightColor = tint_color(base, 1.30);
1394 		bevelShadowColor = tint_color(base, 1.17);
1395 		bevelLightColor = tint_color(base, 1.10);
1396 		fillGradient.AddColor(tint_color(base, 1.12), 0);
1397 		fillGradient.AddColor(tint_color(base, 1.08), 255);
1398 	}
1399 
1400 	// active tabs stand out at the top, but this is an inactive tab
1401 	view->SetHighColor(base);
1402 	view->FillRect(BRect(rect.left, rect.top, rect.right, rect.top + 4));
1403 	rect.top += 4;
1404 
1405 	// frame and fill
1406 	_DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, edgeLightColor,
1407 		edgeLightColor,
1408 		borders & (B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER));
1409 
1410 	_DrawFrame(view, rect, frameLightColor, frameLightColor, frameShadowColor,
1411 		frameShadowColor,
1412 		borders & (B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER));
1413 
1414 	_DrawFrame(view, rect, bevelShadowColor, bevelShadowColor, bevelLightColor,
1415 		bevelLightColor, B_LEFT_BORDER & ~borders);
1416 
1417 	view->FillRect(rect, fillGradient);
1418 }
1419 
1420 
1421 // #pragma mark -
1422 
1423 
1424 void
1425 BControlLook::DrawBorder(BView* view, BRect& rect, const BRect& updateRect,
1426 	const rgb_color& base, border_style border, uint32 flags, uint32 borders)
1427 {
1428 	if (border == B_NO_BORDER)
1429 		return;
1430 
1431 	rgb_color scrollbarFrameColor = tint_color(base, B_DARKEN_2_TINT);
1432 	if (flags & B_FOCUSED)
1433 		scrollbarFrameColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1434 
1435 	if (border == B_FANCY_BORDER)
1436 		_DrawOuterResessedFrame(view, rect, base, 1.0, 1.0, flags, borders);
1437 
1438 	_DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor,
1439 		scrollbarFrameColor, scrollbarFrameColor, borders);
1440 }
1441 
1442 
1443 void
1444 BControlLook::DrawRaisedBorder(BView* view, BRect& rect,
1445 	const BRect& updateRect, const rgb_color& base, uint32 flags,
1446 	uint32 borders)
1447 {
1448 	rgb_color lightColor;
1449 	rgb_color shadowColor;
1450 
1451 	if (flags & B_DISABLED) {
1452 		lightColor = base;
1453 		shadowColor = base;
1454 	} else {
1455 		lightColor = tint_color(base, 0.85);
1456 		shadowColor = tint_color(base, 1.07);
1457 	}
1458 
1459 	_DrawFrame(view, rect, lightColor, lightColor, shadowColor, shadowColor,
1460 		borders);
1461 }
1462 
1463 
1464 void
1465 BControlLook::DrawTextControlBorder(BView* view, BRect& rect,
1466 	const BRect& updateRect, const rgb_color& base, uint32 flags,
1467 	uint32 borders)
1468 {
1469 	if (!rect.Intersects(updateRect))
1470 		return;
1471 
1472 	rgb_color dark1BorderColor;
1473 	rgb_color dark2BorderColor;
1474 	rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1475 
1476 	if (flags & B_DISABLED) {
1477 		_DrawOuterResessedFrame(view, rect, base, 0.0, 1.0, flags, borders);
1478 
1479 		if (flags & B_BLEND_FRAME)
1480 			dark1BorderColor = (rgb_color){ 0, 0, 0, 40 };
1481 		else
1482 			dark1BorderColor = tint_color(base, 1.15);
1483 		dark2BorderColor = dark1BorderColor;
1484 	} else if (flags & B_CLICKED) {
1485 		dark1BorderColor = tint_color(base, 1.50);
1486 		dark2BorderColor = tint_color(base, 1.49);
1487 
1488 		// BCheckBox uses this to indicate the clicked state...
1489 		_DrawFrame(view, rect,
1490 			dark1BorderColor, dark1BorderColor,
1491 			dark2BorderColor, dark2BorderColor);
1492 
1493 		dark2BorderColor = dark1BorderColor;
1494 	} else {
1495 		_DrawOuterResessedFrame(view, rect, base, 0.6, 1.0, flags, borders);
1496 
1497 		if (flags & B_BLEND_FRAME) {
1498 			dark1BorderColor = (rgb_color){ 0, 0, 0, 102 };
1499 			dark2BorderColor = (rgb_color){ 0, 0, 0, 97 };
1500 		} else {
1501 			dark1BorderColor = tint_color(base, 1.40);
1502 			dark2BorderColor = tint_color(base, 1.38);
1503 		}
1504 	}
1505 
1506 	if ((flags & B_DISABLED) == 0 && (flags & B_FOCUSED)) {
1507 		dark1BorderColor = navigationColor;
1508 		dark2BorderColor = navigationColor;
1509 	}
1510 
1511 	if (flags & B_BLEND_FRAME) {
1512 		drawing_mode oldMode = view->DrawingMode();
1513 		view->SetDrawingMode(B_OP_ALPHA);
1514 
1515 		_DrawFrame(view, rect,
1516 			dark1BorderColor, dark1BorderColor,
1517 			dark2BorderColor, dark2BorderColor, borders);
1518 
1519 		view->SetDrawingMode(oldMode);
1520 	} else {
1521 		_DrawFrame(view, rect,
1522 			dark1BorderColor, dark1BorderColor,
1523 			dark2BorderColor, dark2BorderColor, borders);
1524 	}
1525 }
1526 
1527 
1528 void
1529 BControlLook::DrawGroupFrame(BView* view, BRect& rect, const BRect& updateRect,
1530 	const rgb_color& base, uint32 borders)
1531 {
1532 	rgb_color frameColor = tint_color(base, 1.30);
1533 	rgb_color bevelLight = tint_color(base, 0.8);
1534 	rgb_color bevelShadow = tint_color(base, 1.03);
1535 
1536 	_DrawFrame(view, rect, bevelShadow, bevelShadow, bevelLight, bevelLight,
1537 		borders);
1538 
1539 	_DrawFrame(view, rect, frameColor, frameColor, frameColor, frameColor,
1540 		borders);
1541 
1542 	_DrawFrame(view, rect, bevelLight, bevelLight, bevelShadow, bevelShadow,
1543 		borders);
1544 }
1545 
1546 
1547 void
1548 BControlLook::DrawLabel(BView* view, const char* label, BRect rect,
1549 	const BRect& updateRect, const rgb_color& base, uint32 flags)
1550 {
1551 	DrawLabel(view, label, rect, updateRect, base, flags,
1552 		DefaultLabelAlignment());
1553 }
1554 
1555 
1556 void
1557 BControlLook::DrawLabel(BView* view, const char* label, BRect rect,
1558 	const BRect& updateRect, const rgb_color& base, uint32 flags,
1559 	const BAlignment& alignment)
1560 {
1561 	if (!rect.Intersects(updateRect))
1562 		return;
1563 
1564 	// setup the text color
1565 	rgb_color color;
1566 	if (base.red + base.green + base.blue > 128 * 3)
1567 		color = tint_color(base, B_DARKEN_MAX_TINT);
1568 	else
1569 		color = tint_color(base, B_LIGHTEN_MAX_TINT);
1570 
1571 	if (flags & B_DISABLED) {
1572 		color.red = (uint8)(((int32)base.red + color.red + 1) / 2);
1573 		color.green = (uint8)(((int32)base.green + color.green + 1) / 2);
1574 		color.blue = (uint8)(((int32)base.blue + color.blue + 1) / 2);
1575 	}
1576 
1577 	view->SetHighColor(color);
1578 	view->SetDrawingMode(B_OP_OVER);
1579 
1580 	// truncate the label if necessary and get the width and height
1581 	BString truncatedLabel(label);
1582 
1583 	BFont font;
1584 	view->GetFont(&font);
1585 
1586 	float width = rect.Width();
1587 	font.TruncateString(&truncatedLabel, B_TRUNCATE_END, width);
1588 	width = font.StringWidth(truncatedLabel.String());
1589 
1590 	font_height fontHeight;
1591 	font.GetHeight(&fontHeight);
1592 	float height = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
1593 
1594 	// handle alignment
1595 	BPoint location;
1596 
1597 	switch (alignment.horizontal) {
1598 	default:
1599 		case B_ALIGN_LEFT:
1600 			location.x = rect.left;
1601 			break;
1602 		case B_ALIGN_RIGHT:
1603 			location.x = rect.right - width;
1604 			break;
1605 		case B_ALIGN_CENTER:
1606 			location.x = (rect.left + rect.right - width) / 2.0f;
1607 			break;
1608 	}
1609 
1610 	switch (alignment.vertical) {
1611 		case B_ALIGN_TOP:
1612 			location.y = rect.top + ceilf(fontHeight.ascent);
1613 			break;
1614 		default:
1615 		case B_ALIGN_MIDDLE:
1616 			location.y = floorf((rect.top + rect.bottom - height) / 2.0f + 0.5f)
1617 				+ ceilf(fontHeight.ascent);
1618 			break;
1619 		case B_ALIGN_BOTTOM:
1620 			location.y = rect.bottom - ceilf(fontHeight.descent);
1621 			break;
1622 	}
1623 
1624 	view->DrawString(truncatedLabel.String(), location);
1625 }
1626 
1627 
1628 // #pragma mark -
1629 
1630 
1631 void
1632 BControlLook::_DrawButtonFrame(BView* view, BRect& rect,
1633 	const BRect& updateRect, const rgb_color& base, const rgb_color& background,
1634 	float contrast, float brightness, uint32 flags, uint32 borders)
1635 {
1636 	// colors
1637 	rgb_color dark1BorderColor;
1638 	rgb_color dark2BorderColor;
1639 
1640 	if ((flags & B_DISABLED) == 0) {
1641 		if (flags & B_BLEND_FRAME) {
1642 			dark1BorderColor = (rgb_color){ 0, 0, 0, 75 };
1643 			dark2BorderColor = (rgb_color){ 0, 0, 0, 95 };
1644 		} else {
1645 			dark1BorderColor = tint_color(base, 1.33);
1646 			dark2BorderColor = tint_color(base, 1.45);
1647 		}
1648 
1649 		if (flags & B_DEFAULT_BUTTON) {
1650 			// TODO: B_BLEND_FRAME
1651 			dark2BorderColor = tint_color(dark1BorderColor, 1.5);
1652 			dark1BorderColor = tint_color(dark1BorderColor, 1.35);
1653 		}
1654 	} else {
1655 		// TODO: B_BLEND_FRAME
1656 		dark1BorderColor = tint_color(base, 1.147);
1657 		dark2BorderColor = tint_color(base, 1.24);
1658 
1659 		if (flags & B_DEFAULT_BUTTON) {
1660 			dark1BorderColor = tint_color(dark1BorderColor, 1.14);
1661 			dark2BorderColor = tint_color(dark1BorderColor, 1.12);
1662 		}
1663 	}
1664 
1665 	if (flags & B_ACTIVATED) {
1666 		rgb_color temp = dark2BorderColor;
1667 		dark2BorderColor = dark1BorderColor;
1668 		dark1BorderColor = temp;
1669 	}
1670 
1671 	// indicate focus by changing main button border
1672 	if (flags & B_FOCUSED) {
1673 		dark1BorderColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1674 		dark2BorderColor = dark1BorderColor;
1675 	}
1676 
1677 	if (flags & B_DEFAULT_BUTTON) {
1678 		// TODO: B_BLEND_FRAME
1679 		float focusTint = 1.2;
1680 		if (flags & B_DISABLED)
1681 			focusTint = (B_NO_TINT + focusTint) / 2;
1682 
1683 		rgb_color focusColor = tint_color(base, focusTint);
1684 		view->SetHighColor(base);
1685 
1686 		view->StrokeRect(rect);
1687 		rect.InsetBy(1.0, 1.0);
1688 
1689 		view->SetHighColor(focusColor);
1690 		view->StrokeRect(rect);
1691 		rect.InsetBy(1.0, 1.0);
1692 		view->StrokeRect(rect);
1693 		rect.InsetBy(1.0, 1.0);
1694 
1695 		// bevel around external border
1696 		_DrawOuterResessedFrame(view, rect, focusColor,
1697 			contrast * (((flags & B_DISABLED) ? 0.3 : 0.8)),
1698 			brightness * (((flags & B_DISABLED) ? 1.0 : 0.9)),
1699 			flags, borders);
1700 	} else {
1701 		// bevel around external border
1702 		_DrawOuterResessedFrame(view, rect, background,
1703 			contrast * ((flags & B_DISABLED) ? 0.0 : 1.0), brightness * 1.0,
1704 			flags, borders);
1705 	}
1706 
1707 	if (flags & B_BLEND_FRAME) {
1708 		drawing_mode oldDrawingMode = view->DrawingMode();
1709 		view->SetDrawingMode(B_OP_ALPHA);
1710 
1711 		_DrawFrame(view, rect, dark1BorderColor, dark1BorderColor,
1712 			dark2BorderColor, dark2BorderColor, borders);
1713 
1714 		view->SetDrawingMode(oldDrawingMode);
1715 	} else {
1716 		_DrawFrame(view, rect, dark1BorderColor, dark1BorderColor,
1717 			dark2BorderColor, dark2BorderColor, borders);
1718 	}
1719 }
1720 
1721 
1722 void
1723 BControlLook::_DrawOuterResessedFrame(BView* view, BRect& rect,
1724 	const rgb_color& base, float contrast, float brightness, uint32 flags,
1725 	uint32 borders)
1726 {
1727 	if (flags & B_BLEND_FRAME) {
1728 		// assumes the background has already been painted
1729 		drawing_mode oldDrawingMode = view->DrawingMode();
1730 		view->SetDrawingMode(B_OP_ALPHA);
1731 
1732 		uint8 alpha = uint8(20 * contrast);
1733 		uint32 white = uint8(255 * brightness);
1734 
1735 		rgb_color borderBevelShadow = (rgb_color){ 0, 0, 0, alpha };
1736 		rgb_color borderBevelLight = (rgb_color){ white, white, white, alpha };
1737 
1738 		_DrawFrame(view, rect, borderBevelShadow, borderBevelShadow,
1739 			borderBevelLight, borderBevelLight, borders);
1740 
1741 		view->SetDrawingMode(oldDrawingMode);
1742 	} else {
1743 		// colors
1744 		float tintLight = kEdgeBevelLightTint;
1745 		float tintShadow = kEdgeBevelShadowTint;
1746 
1747 		if (contrast == 0.0) {
1748 			tintLight = B_NO_TINT;
1749 			tintShadow = B_NO_TINT;
1750 		} else if (contrast != 1.0) {
1751 			tintLight = B_NO_TINT + (tintLight - B_NO_TINT) * contrast;
1752 			tintShadow = B_NO_TINT + (tintShadow - B_NO_TINT) * contrast;
1753 		}
1754 
1755 		rgb_color borderBevelShadow = tint_color(base, tintShadow);
1756 		rgb_color borderBevelLight = tint_color(base, tintLight);
1757 
1758 		if (brightness < 1.0) {
1759 			borderBevelShadow.red = uint8(borderBevelShadow.red * brightness);
1760 			borderBevelShadow.green = uint8(borderBevelShadow.green * brightness);
1761 			borderBevelShadow.blue = uint8(borderBevelShadow.blue * brightness);
1762 			borderBevelLight.red = uint8(borderBevelLight.red * brightness);
1763 			borderBevelLight.green = uint8(borderBevelLight.green * brightness);
1764 			borderBevelLight.blue = uint8(borderBevelLight.blue * brightness);
1765 		}
1766 
1767 		_DrawFrame(view, rect, borderBevelShadow, borderBevelShadow,
1768 			borderBevelLight, borderBevelLight, borders);
1769 	}
1770 }
1771 
1772 
1773 void
1774 BControlLook::_DrawFrame(BView* view, BRect& rect, const rgb_color& left,
1775 	const rgb_color& top, const rgb_color& right, const rgb_color& bottom,
1776 	uint32 borders)
1777 {
1778 	view->BeginLineArray(4);
1779 
1780 	if (borders & B_LEFT_BORDER) {
1781 		view->AddLine(
1782 			BPoint(rect.left, rect.bottom),
1783 			BPoint(rect.left, rect.top), left);
1784 		rect.left++;
1785 	}
1786 	if (borders & B_TOP_BORDER) {
1787 		view->AddLine(
1788 			BPoint(rect.left, rect.top),
1789 			BPoint(rect.right, rect.top), top);
1790 		rect.top++;
1791 	}
1792 	if (borders & B_RIGHT_BORDER) {
1793 		view->AddLine(
1794 			BPoint(rect.right, rect.top),
1795 			BPoint(rect.right, rect.bottom), right);
1796 		rect.right--;
1797 	}
1798 	if (borders & B_BOTTOM_BORDER) {
1799 		view->AddLine(
1800 			BPoint(rect.left, rect.bottom),
1801 			BPoint(rect.right, rect.bottom), bottom);
1802 		rect.bottom--;
1803 	}
1804 
1805 	view->EndLineArray();
1806 }
1807 
1808 
1809 void
1810 BControlLook::_DrawFrame(BView* view, BRect& rect, const rgb_color& left,
1811 	const rgb_color& top, const rgb_color& right, const rgb_color& bottom,
1812 	const rgb_color& rightTop, const rgb_color& leftBottom, uint32 borders)
1813 {
1814 	view->BeginLineArray(6);
1815 
1816 	if (borders & B_TOP_BORDER) {
1817 		if (borders & B_RIGHT_BORDER) {
1818 			view->AddLine(
1819 				BPoint(rect.left, rect.top),
1820 				BPoint(rect.right - 1, rect.top), top);
1821 			view->AddLine(
1822 				BPoint(rect.right, rect.top),
1823 				BPoint(rect.right, rect.top), rightTop);
1824 		} else {
1825 			view->AddLine(
1826 				BPoint(rect.left, rect.top),
1827 				BPoint(rect.right, rect.top), top);
1828 		}
1829 		rect.top++;
1830 	}
1831 
1832 	if (borders & B_LEFT_BORDER) {
1833 		view->AddLine(
1834 			BPoint(rect.left, rect.top),
1835 			BPoint(rect.left, rect.bottom - 1), left);
1836 		view->AddLine(
1837 			BPoint(rect.left, rect.bottom),
1838 			BPoint(rect.left, rect.bottom), leftBottom);
1839 		rect.left++;
1840 	}
1841 
1842 	if (borders & B_BOTTOM_BORDER) {
1843 		view->AddLine(
1844 			BPoint(rect.left, rect.bottom),
1845 			BPoint(rect.right, rect.bottom), bottom);
1846 		rect.bottom--;
1847 	}
1848 
1849 	if (borders & B_RIGHT_BORDER) {
1850 		view->AddLine(
1851 			BPoint(rect.right, rect.bottom),
1852 			BPoint(rect.right, rect.top), right);
1853 		rect.right--;
1854 	}
1855 
1856 	view->EndLineArray();
1857 }
1858 
1859 
1860 //void
1861 //BControlLook::_DrawShadowFrame(BView* view, BRect& rect, const rgb_color& base,
1862 //	uint32 borders)
1863 //{
1864 //	view->BeginLineArray(4);
1865 //
1866 //	bevelColor1 = tint_color(base, 1.2);
1867 //	bevelColor2 = tint_color(base, 1.1);
1868 //
1869 //	// shadow along left/top borders
1870 //	if (rect.Height() > 0 && borders & B_LEFT_BORDER) {
1871 //		view->AddLine(BPoint(rect.left, rect.top),
1872 //			BPoint(rect.left, rect.bottom), bevelColor1);
1873 //		rect.left++;
1874 //	}
1875 //	if (rect.Width() > 0 && borders & B_TOP_BORDER) {
1876 //		view->AddLine(BPoint(rect.left, rect.top),
1877 //			BPoint(rect.right, rect.top), bevelColor1);
1878 //		rect.top++;
1879 //	}
1880 //
1881 //	// softer shadow along left/top borders
1882 //	if (rect.Height() > 0 && borders & B_LEFT_BORDER) {
1883 //		view->AddLine(BPoint(rect.left, rect.top),
1884 //			BPoint(rect.left, rect.bottom), bevelColor2);
1885 //		rect.left++;
1886 //	}
1887 //	if (rect.Width() > 0 && borders & B_TOP_BORDER) {
1888 //		view->AddLine(BPoint(rect.left, rect.top),
1889 //			BPoint(rect.right, rect.top), bevelColor2);
1890 //		rect.top++;
1891 //	}
1892 //
1893 //	view->EndLineArray();
1894 //}
1895 
1896 
1897 void
1898 BControlLook::_FillGradient(BView* view, const BRect& rect,
1899 	const rgb_color& base, float topTint, float bottomTint,
1900 	enum orientation orientation)
1901 {
1902 	BGradientLinear gradient;
1903 	_MakeGradient(gradient, rect, base, topTint, bottomTint, orientation);
1904 	view->FillRect(rect, gradient);
1905 }
1906 
1907 
1908 void
1909 BControlLook::_FillGlossyGradient(BView* view, const BRect& rect,
1910 	const rgb_color& base, float topTint, float middle1Tint,
1911 	float middle2Tint, float bottomTint, enum orientation orientation)
1912 {
1913 	BGradientLinear gradient;
1914 	_MakeGlossyGradient(gradient, rect, base, topTint, middle1Tint,
1915 		middle2Tint, bottomTint, orientation);
1916 	view->FillRect(rect, gradient);
1917 }
1918 
1919 
1920 void
1921 BControlLook::_MakeGradient(BGradientLinear& gradient, const BRect& rect,
1922 	const rgb_color& base, float topTint, float bottomTint,
1923 	enum orientation orientation) const
1924 {
1925 	gradient.AddColor(tint_color(base, topTint), 0);
1926 	gradient.AddColor(tint_color(base, bottomTint), 255);
1927 	gradient.SetStart(rect.LeftTop());
1928 	if (orientation == B_HORIZONTAL)
1929 		gradient.SetEnd(rect.LeftBottom());
1930 	else
1931 		gradient.SetEnd(rect.RightTop());
1932 }
1933 
1934 
1935 void
1936 BControlLook::_MakeGlossyGradient(BGradientLinear& gradient, const BRect& rect,
1937 	const rgb_color& base, float topTint, float middle1Tint,
1938 	float middle2Tint, float bottomTint,
1939 	enum orientation orientation) const
1940 {
1941 	gradient.AddColor(tint_color(base, topTint), 0);
1942 	gradient.AddColor(tint_color(base, middle1Tint), 132);
1943 	gradient.AddColor(tint_color(base, middle2Tint), 136);
1944 	gradient.AddColor(tint_color(base, bottomTint), 255);
1945 	gradient.SetStart(rect.LeftTop());
1946 	if (orientation == B_HORIZONTAL)
1947 		gradient.SetEnd(rect.LeftBottom());
1948 	else
1949 		gradient.SetEnd(rect.RightTop());
1950 }
1951 
1952 
1953 bool
1954 BControlLook::_RadioButtonAndCheckBoxMarkColor(const rgb_color& base,
1955 	rgb_color& color, uint32 flags) const
1956 {
1957 	if ((flags & (B_ACTIVATED | B_CLICKED)) == 0) {
1958 		// no mark to be drawn at all
1959 		return false;
1960 	}
1961 
1962 	// TODO: Get from UI settings
1963 	color.red = 27;
1964 	color.green = 82;
1965 	color.blue = 140;
1966 
1967 	float mix = 1.0;
1968 
1969 	if (flags & B_DISABLED) {
1970 		// activated, but disabled
1971 		mix = 0.4;
1972 	} else if (flags & B_CLICKED) {
1973 		if (flags & B_ACTIVATED) {
1974 			// loosing activation
1975 			mix = 0.7;
1976 		} else {
1977 			// becoming activated
1978 			mix = 0.3;
1979 		}
1980 	} else {
1981 		// simply activated
1982 	}
1983 
1984 	color.red = uint8(color.red * mix + base.red * (1.0 - mix));
1985 	color.green = uint8(color.green * mix + base.green * (1.0 - mix));
1986 	color.blue = uint8(color.blue * mix + base.blue * (1.0 - mix));
1987 
1988 	return true;
1989 }
1990 
1991 
1992 void
1993 BControlLook::_DrawRoundBarCorner(BView* view, BRect& rect,
1994 	const BRect& updateRect,
1995 	const rgb_color& edgeLightColor, const rgb_color& edgeShadowColor,
1996 	const rgb_color& frameLightColor, const rgb_color& frameShadowColor,
1997 	const rgb_color& fillLightColor, const rgb_color& fillShadowColor,
1998 	float leftInset, float topInset, float rightInset, float bottomInset,
1999 	enum orientation orientation)
2000 {
2001 	if (!rect.IsValid() || !rect.Intersects(updateRect))
2002 		return;
2003 
2004 	BGradientLinear gradient;
2005 	gradient.AddColor(edgeShadowColor, 0);
2006 	gradient.AddColor(edgeLightColor, 255);
2007 	gradient.SetStart(rect.LeftTop());
2008 	if (orientation == B_HORIZONTAL)
2009 		gradient.SetEnd(rect.LeftBottom());
2010 	else
2011 		gradient.SetEnd(rect.RightTop());
2012 
2013 	view->FillEllipse(rect, gradient);
2014 
2015 	rect.left += leftInset;
2016 	rect.top += topInset;
2017 	rect.right += rightInset;
2018 	rect.bottom += bottomInset;
2019 
2020 	gradient.MakeEmpty();
2021 	gradient.AddColor(frameShadowColor, 0);
2022 	gradient.AddColor(frameLightColor, 255);
2023 	gradient.SetStart(rect.LeftTop());
2024 	if (orientation == B_HORIZONTAL)
2025 		gradient.SetEnd(rect.LeftBottom());
2026 	else
2027 		gradient.SetEnd(rect.RightTop());
2028 
2029 	view->FillEllipse(rect, gradient);
2030 
2031 	rect.left += leftInset;
2032 	rect.top += topInset;
2033 	rect.right += rightInset;
2034 	rect.bottom += bottomInset;
2035 
2036 	gradient.MakeEmpty();
2037 	gradient.AddColor(fillShadowColor, 0);
2038 	gradient.AddColor(fillLightColor, 255);
2039 	gradient.SetStart(rect.LeftTop());
2040 	if (orientation == B_HORIZONTAL)
2041 		gradient.SetEnd(rect.LeftBottom());
2042 	else
2043 		gradient.SetEnd(rect.RightTop());
2044 
2045 	view->FillEllipse(rect, gradient);
2046 }
2047 
2048 
2049 void
2050 BControlLook::_DrawRoundCornerLeftTop(BView* view, BRect& rect,
2051 	const BRect& updateRect, const rgb_color& base, const rgb_color& edgeColor,
2052 	const rgb_color& frameColor, const rgb_color& bevelColor,
2053 	const BGradientLinear& fillGradient)
2054 {
2055 	if (!rect.IsValid() || !rect.Intersects(updateRect))
2056 		return;
2057 
2058 	BRegion clipping(rect);
2059 	view->ConstrainClippingRegion(&clipping);
2060 
2061 	// background
2062 	view->SetHighColor(base);
2063 	view->FillRect(rect);
2064 
2065 	// outer edge
2066 	BRect ellipseRect(rect);
2067 	ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2068 	ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2069 
2070 	view->SetHighColor(edgeColor);
2071 	view->FillEllipse(ellipseRect);
2072 
2073 	// frame
2074 	ellipseRect.InsetBy(1, 1);
2075 	view->SetHighColor(frameColor);
2076 	view->FillEllipse(ellipseRect);
2077 
2078 	// bevel
2079 	ellipseRect.InsetBy(1, 1);
2080 	view->SetHighColor(bevelColor);
2081 	view->FillEllipse(ellipseRect);
2082 
2083 	// fill
2084 	ellipseRect.InsetBy(1, 1);
2085 	view->FillEllipse(ellipseRect, fillGradient);
2086 
2087 	view->ConstrainClippingRegion(NULL);
2088 }
2089 
2090 void
2091 BControlLook::_DrawRoundCornerRightTop(BView* view, BRect& rect,
2092 	const BRect& updateRect, const rgb_color& base,
2093 	const rgb_color& edgeTopColor, const rgb_color& edgeRightColor,
2094 	const rgb_color& frameTopColor, const rgb_color& frameRightColor,
2095 	const rgb_color& bevelTopColor, const rgb_color& bevelRightColor,
2096 	const BGradientLinear& fillGradient)
2097 {
2098 	if (!rect.IsValid() || !rect.Intersects(updateRect))
2099 		return;
2100 
2101 	BRegion clipping(rect);
2102 	view->ConstrainClippingRegion(&clipping);
2103 
2104 	// background
2105 	view->SetHighColor(base);
2106 	view->FillRect(rect);
2107 
2108 	// outer edge
2109 	BRect ellipseRect(rect);
2110 	ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
2111 	ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2112 
2113 	BGradientLinear gradient;
2114 	gradient.AddColor(edgeTopColor, 0);
2115 	gradient.AddColor(edgeRightColor, 255);
2116 	gradient.SetStart(rect.LeftTop());
2117 	gradient.SetEnd(rect.RightBottom());
2118 	view->FillEllipse(ellipseRect, gradient);
2119 
2120 	// frame
2121 	ellipseRect.InsetBy(1, 1);
2122 	rect.right--;
2123 	rect.top++;
2124 	if (frameTopColor == frameRightColor) {
2125 		view->SetHighColor(frameTopColor);
2126 		view->FillEllipse(ellipseRect);
2127 	} else {
2128 		gradient.SetColor(0, frameTopColor);
2129 		gradient.SetColor(1, frameRightColor);
2130 		gradient.SetStart(rect.LeftTop());
2131 		gradient.SetEnd(rect.RightBottom());
2132 		view->FillEllipse(ellipseRect, gradient);
2133 	}
2134 
2135 	// bevel
2136 	ellipseRect.InsetBy(1, 1);
2137 	rect.right--;
2138 	rect.top++;
2139 	gradient.SetColor(0, bevelTopColor);
2140 	gradient.SetColor(1, bevelRightColor);
2141 	gradient.SetStart(rect.LeftTop());
2142 	gradient.SetEnd(rect.RightBottom());
2143 	view->FillEllipse(ellipseRect, gradient);
2144 
2145 	// fill
2146 	ellipseRect.InsetBy(1, 1);
2147 	view->FillEllipse(ellipseRect, fillGradient);
2148 
2149 	view->ConstrainClippingRegion(NULL);
2150 }
2151 
2152 
2153 // NOTE: May come from a add-on in the future. Initialized in
2154 // InterfaceDefs.cpp
2155 BControlLook* be_control_look = NULL;
2156 
2157 } // namespace BPrivate
2158