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