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