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