xref: /haiku/src/add-ons/control_look/FlatControlLook/FlatControlLook.cpp (revision 610f99c838cb661ff85377789ffd3ad4ff672a08)
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(): HaikuControlLook()
39 {
40 }
41 
42 
43 FlatControlLook::~FlatControlLook()
44 {
45 }
46 
47 
48 // #pragma mark -
49 
50 
51 void
52 HaikuControlLook::DrawButtonFrame(BView* view, BRect& rect, const BRect& updateRect,
53 	const rgb_color& base, const rgb_color& background, uint32 flags,
54 	uint32 borders)
55 {
56 	_DrawButtonFrame(view, rect, updateRect, 1.5f, 1.5f, 1.5f, 1.5f, base,
57 		background, 1.0, 1.0, flags, borders);
58 }
59 
60 
61 void
62 HaikuControlLook::DrawButtonFrame(BView* view, BRect& rect, const BRect& updateRect,
63 	float radius, const rgb_color& base, const rgb_color& background, uint32 flags,
64 	uint32 borders)
65 {
66 	_DrawButtonFrame(view, rect, updateRect,  1.5f, 1.5f, 1.5f, 1.5f,
67 		base, background, 1.0, 1.0, flags, borders);
68 }
69 
70 
71 void
72 HaikuControlLook::DrawButtonFrame(BView* view, BRect& rect,
73 	const BRect& updateRect, float leftTopRadius, float rightTopRadius,
74 	float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
75 	const rgb_color& background, uint32 flags,
76 	uint32 borders)
77 {
78 	_DrawButtonFrame(view, rect, updateRect,  1.5f, 1.5f,
79 		1.5f, 1.5f, base, background,
80 		1.0, 1.0, flags, borders);
81 }
82 
83 
84 void
85 FlatControlLook::DrawButtonBackground(BView* view, BRect& rect,
86 	const BRect& updateRect, const rgb_color& base, uint32 flags,
87 	uint32 borders, orientation orientation)
88 {
89 	_DrawButtonBackground(view, rect, updateRect, 1.5f, 1.5f, 1.5f, 1.5f,
90 		base, false, flags, borders, orientation);
91 }
92 
93 
94 void
95 FlatControlLook::DrawButtonBackground(BView* view, BRect& rect,
96 	const BRect& updateRect, float radius, const rgb_color& base, uint32 flags,
97 	uint32 borders, orientation orientation)
98 {
99 	_DrawButtonBackground(view, rect, updateRect, 1.5f, 1.5f, 1.5f, 1.5f,
100 		base, false, flags, borders, orientation);
101 }
102 
103 
104 void
105 FlatControlLook::DrawButtonBackground(BView* view, BRect& rect,
106 	const BRect& updateRect, float leftTopRadius, float rightTopRadius,
107 	float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
108 	uint32 flags, uint32 borders, orientation orientation)
109 {
110 	_DrawButtonBackground(view, rect, updateRect, 1.5f,
111 		1.5f, 1.5f, 1.5f, base, false, flags,
112 		borders, orientation);
113 }
114 
115 
116 void
117 FlatControlLook::DrawMenuBarBackground(BView* view, BRect& rect,
118 	const BRect& updateRect, const rgb_color& base, uint32 flags,
119 	uint32 borders)
120 {
121 	if (!rect.IsValid() || !rect.Intersects(updateRect))
122 		return;
123 
124 	// the surface edges
125 
126 	// colors
127 	float topTint = 1.0;
128 	float bottomTint = 1.16;
129 
130 	rgb_color customColor = base;
131 	bool isEnabled = (flags & B_ACTIVATED) != 0;
132 
133 	if (isEnabled) {
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, 1.5f, 1.5f, 1.5f, 1.5f, base,
172 		background, 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, 1.5f, 1.5f,
182 		base, background, 1.0, 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,
194 		1.5f, 1.5f, base, background, 1.0, 1.0,
195 		flags, borders);
196 }
197 
198 
199 void
200 FlatControlLook::DrawMenuFieldBackground(BView* view, BRect& rect,
201 	const BRect& updateRect, const rgb_color& base, bool popupIndicator,
202 	uint32 flags)
203 {
204 	_DrawMenuFieldBackgroundOutside(view, rect, updateRect,
205 		1.5f, 1.5f, 1.5f, 1.5f, base, popupIndicator, flags);
206 }
207 
208 
209 void
210 FlatControlLook::DrawMenuFieldBackground(BView* view, BRect& rect,
211 	const BRect& updateRect, const rgb_color& base, uint32 flags,
212 	uint32 borders)
213 {
214 	_DrawMenuFieldBackgroundInside(view, rect, updateRect,
215 		1.5f, 1.5f, 1.5f, 1.5f, base, flags, borders);
216 }
217 
218 
219 void
220 FlatControlLook::DrawMenuFieldBackground(BView* view, BRect& rect,
221 	const BRect& updateRect, float radius, const rgb_color& base,
222 	bool popupIndicator, uint32 flags)
223 {
224 	_DrawMenuFieldBackgroundOutside(view, rect, updateRect, radius, radius,
225 		radius, radius, base, popupIndicator, flags);
226 }
227 
228 
229 void
230 FlatControlLook::DrawMenuFieldBackground(BView* view, BRect& rect,
231 	const BRect& updateRect, float leftTopRadius, float rightTopRadius,
232 	float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
233 	bool popupIndicator, uint32 flags)
234 {
235 	_DrawMenuFieldBackgroundOutside(view, rect, updateRect, leftTopRadius,
236 		rightTopRadius, leftBottomRadius, rightBottomRadius, base,
237 		popupIndicator, flags);
238 }
239 
240 
241 void
242 HaikuControlLook::DrawMenuBackground(BView* view, BRect& rect,
243 	const BRect& updateRect, const rgb_color& base, uint32 flags,
244 	uint32 borders)
245 {
246 	if (!rect.IsValid() || !rect.Intersects(updateRect))
247 		return;
248 
249 	// surface top color
250 	rgb_color background = tint_color(base, 0.8);
251 
252 	// inner bevel colors
253 	rgb_color bevelColor;
254 
255 
256 	if ((flags & B_DISABLED) != 0) {
257 		bevelColor = tint_color(background, 1.03);
258 	} else {
259 		bevelColor = tint_color(background, 0.5);
260 	}
261 
262 	// draw inner bevel
263 	_DrawFrame(view, rect,
264 		bevelColor, bevelColor,
265 		bevelColor, bevelColor,
266 		borders);
267 
268 	// draw surface top
269 	view->SetHighColor(background);
270 	view->FillRect(rect);
271 }
272 
273 
274 void
275 FlatControlLook::DrawMenuItemBackground(BView* view, BRect& rect,
276 	const BRect& updateRect, const rgb_color& base, uint32 flags,
277 	uint32 borders)
278 {
279 	if (!rect.IsValid() || !rect.Intersects(updateRect))
280 		return;
281 
282 	// surface edges
283 	float topTint;
284 	float bottomTint;
285 	rgb_color selectedColor = base;
286 
287 	if ((flags & B_ACTIVATED) != 0) {
288 		topTint = 0.94;
289 		bottomTint = 1.1;
290 	} else if ((flags & B_DISABLED) != 0) {
291 		topTint = 1.0;
292 		bottomTint = 1.0;
293 	} else {
294 		topTint = 0.95;
295 		bottomTint = 1.1;
296 	}
297 
298 	//rgb_color bevelLightColor = tint_color(selectedColor, topTint);
299 	rgb_color bevelShadowColor = tint_color(selectedColor, bottomTint);
300 
301 	// draw surface edges
302 	_DrawFrame(view, rect,
303 		bevelShadowColor, bevelShadowColor,
304 		bevelShadowColor, bevelShadowColor,
305 		borders);
306 
307 	// draw surface top
308 	view->SetLowColor(selectedColor);
309 	_FillGradient(view, rect, selectedColor, topTint, bottomTint);
310 }
311 
312 
313 void
314 HaikuControlLook::DrawScrollBarBorder(BView* view, BRect rect,
315 	const BRect& updateRect, const rgb_color& base, uint32 flags,
316 	orientation orientation)
317 {
318 	if (!rect.IsValid() || !rect.Intersects(updateRect))
319 		return;
320 
321 	view->PushState();
322 
323 	// set clipping constraints to updateRect
324 	BRegion clipping(updateRect);
325 	view->ConstrainClippingRegion(&clipping);
326 
327 	bool isEnabled = (flags & B_DISABLED) == 0;
328 	bool isFocused = (flags & B_FOCUSED) != 0;
329 
330 	view->SetHighColor(tint_color(base, 1.2));
331 
332 	// stroke a line around the entire scrollbar
333 	// take care of border highlighting, scroll target is focus view
334 	if (isEnabled && isFocused) {
335 		rgb_color borderColor = tint_color(base, 1.2);
336 		rgb_color highlightColor = tint_color(base, 1.2);
337 
338 		view->BeginLineArray(4);
339 
340 		view->AddLine(BPoint(rect.left + 1, rect.bottom),
341 			BPoint(rect.right, rect.bottom), borderColor);
342 		view->AddLine(BPoint(rect.right, rect.top + 1),
343 			BPoint(rect.right, rect.bottom - 1), borderColor);
344 
345 		if (orientation == B_HORIZONTAL) {
346 			view->AddLine(BPoint(rect.left, rect.top + 1),
347 				BPoint(rect.left, rect.bottom), borderColor);
348 		} else {
349 			view->AddLine(BPoint(rect.left, rect.top),
350 				BPoint(rect.left, rect.bottom), highlightColor);
351 		}
352 
353 		if (orientation == B_HORIZONTAL) {
354 			view->AddLine(BPoint(rect.left, rect.top),
355 				BPoint(rect.right, rect.top), highlightColor);
356 		} else {
357 			view->AddLine(BPoint(rect.left + 1, rect.top),
358 				BPoint(rect.right, rect.top), borderColor);
359 		}
360 
361 		view->EndLineArray();
362 	} else
363 		view->StrokeRect(rect);
364 
365 	view->PopState();
366 }
367 
368 
369 void
370 HaikuControlLook::DrawScrollBarButton(BView* view, BRect rect,
371 	const BRect& updateRect, const rgb_color& base, uint32 flags,
372 	int32 direction, orientation orientation, bool down)
373 {
374 	if (!rect.IsValid() || !rect.Intersects(updateRect))
375 		return;
376 
377 	bool dark = (base.red + base.green + base.blue <= 128 * 3);
378 	rgb_color arrowColor;
379 
380 	bool isEnabled = (flags & B_DISABLED) == 0;
381 
382 	if (isEnabled) {
383 		arrowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 0.6);
384 		// if the base color is too dark, then lets make it lighter
385 		if (dark) {
386 			arrowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 1.3);;
387 		}
388 	} else {
389 		arrowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 0.4);
390 		// if the base color is too dark, then lets make it lighter
391 		if (dark) {
392 			arrowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 1.5);;
393 		}
394 	}
395 
396 	// clip to button
397 	BRegion buttonRegion(rect);
398 	view->ConstrainClippingRegion(&buttonRegion);
399 
400 	flags &= ~B_FLAT;
401 
402 	DrawScrollBarBackground(view, rect, updateRect, base, flags, orientation);
403 	rect.InsetBy(1, 1);
404 	DrawArrowShape(view, rect, updateRect, arrowColor, direction, flags, 1.0f);
405 
406 	// revert clipping constraints
407 	BRegion clipping(updateRect);
408 	view->ConstrainClippingRegion(&clipping);
409 }
410 
411 
412 void
413 HaikuControlLook::DrawScrollBarBackground(BView* view, BRect& rect1,
414 	BRect& rect2, const BRect& updateRect, const rgb_color& base, uint32 flags,
415 	orientation orientation)
416 {
417 	DrawScrollBarBackground(view, rect1, updateRect, base, flags, orientation);
418 	DrawScrollBarBackground(view, rect2, updateRect, base, flags, orientation);
419 }
420 
421 
422 void
423 HaikuControlLook::DrawScrollBarBackground(BView* view, BRect& rect,
424 	const BRect& updateRect, const rgb_color& base, uint32 flags,
425 	orientation orientation)
426 {
427 	if (!rect.IsValid() || !rect.Intersects(updateRect))
428 		return;
429 
430 	view->PushState();
431 
432 	// set clipping constraints to updateRect
433 	BRegion clipping(updateRect);
434 	view->ConstrainClippingRegion(&clipping);
435 
436 	bool isEnabled = (flags & B_DISABLED) == 0;
437 
438 	// fill background, we'll draw arrows and thumb on top
439 	view->SetDrawingMode(B_OP_COPY);
440 
441 	float gradient1Tint;
442 	float gradient2Tint;
443 
444 	if (isEnabled) {
445 		gradient1Tint = 1.08;
446 		gradient2Tint = 0.99;
447 	} else {
448 		gradient1Tint = 1.08;
449 		gradient2Tint = 0.99;
450 	}
451 
452 	if (orientation == B_HORIZONTAL) {
453 		// dark vertical line on left edge
454 		// fill
455 		if (rect.Width() >= 0) {
456 			_FillGradient(view, rect, base, gradient1Tint, gradient2Tint,
457 				orientation);
458 		}
459 	} else {
460 		// dark vertical line on top edge
461 		// fill
462 		if (rect.Height() >= 0) {
463 			_FillGradient(view, rect, base, gradient1Tint, gradient2Tint,
464 				orientation);
465 		}
466 	}
467 
468 	view->PopState();
469 }
470 
471 
472 void
473 FlatControlLook::DrawScrollBarThumb(BView* view, BRect& rect,
474 	const BRect& updateRect, const rgb_color& base, uint32 flags,
475 	orientation orientation, uint32 knobStyle)
476 {
477 	if (!rect.IsValid() || !rect.Intersects(updateRect))
478 		return;
479 
480 	view->PushState();
481 
482 	// set clipping constraints to updateRect
483 	BRegion clipping(updateRect);
484 	view->ConstrainClippingRegion(&clipping);
485 
486 	// flags
487 	bool isEnabled = (flags & B_DISABLED) == 0;
488 
489 	// colors
490 	rgb_color thumbColor = ui_color(B_SCROLL_BAR_THUMB_COLOR);
491 		rgb_color base_panel = ui_color(B_PANEL_BACKGROUND_COLOR);
492 
493 	rgb_color light, dark, dark1, dark2;
494 	light = tint_color(base_panel, B_DARKEN_1_TINT);
495 	dark = tint_color(base_panel, B_DARKEN_1_TINT);
496 	dark1 = tint_color(base_panel, B_DARKEN_1_TINT);
497 	dark2 = tint_color(base_panel, B_DARKEN_1_TINT);
498 
499 	// draw thumb over background
500 	view->SetDrawingMode(B_OP_OVER);
501 	view->SetHighColor(dark1);
502 
503 	// draw scroll thumb
504 	if (isEnabled) {
505 		// fill the clickable surface of the thumb
506 		// set clipping constraints to updateRect
507 		BRegion clipping(updateRect);
508 		view->ConstrainClippingRegion(&clipping);
509 		DrawScrollBarBackground(view, rect, updateRect, base_panel, flags, orientation);
510 		rect.InsetBy(3, 3);
511 		view->SetHighColor(base_panel);
512 		view->FillRect(rect);
513 
514 		_DrawNonFlatButtonBackground(view, rect, updateRect, clipping, 4.0f, 4.0f, 4.0f, 4.0f, thumbColor, false, flags, B_ALL_BORDERS, orientation);
515 
516 	} else {
517 		DrawScrollBarBackground(view, rect, updateRect, base_panel, flags, orientation);
518 	}
519 
520 	knobStyle = B_KNOB_LINES; //Hard set of the knobstyle
521 
522 	// draw knob style
523 	if (knobStyle != B_KNOB_NONE && isEnabled) {
524 		rgb_color knobLight = isEnabled
525 			? tint_color(thumbColor, 0.85)
526 			: tint_color(base_panel, 1.05);
527 		rgb_color knobDark = isEnabled
528 			? tint_color(thumbColor, 1.35)
529 			: tint_color(base_panel, 1.05);
530 
531 		if (knobStyle == B_KNOB_DOTS) {
532 			// draw dots on the scroll bar thumb
533 			float hcenter = rect.left + rect.Width() / 2;
534 			float vmiddle = rect.top + rect.Height() / 2;
535 			BRect knob(hcenter, vmiddle, hcenter, vmiddle);
536 
537 			if (orientation == B_HORIZONTAL) {
538 				view->SetHighColor(knobDark);
539 				view->FillRect(knob);
540 				view->SetHighColor(knobLight);
541 				view->FillRect(knob.OffsetByCopy(1, 1));
542 
543 				float spacer = rect.Height();
544 
545 				if (rect.left + 3 < hcenter - spacer) {
546 					view->SetHighColor(knobDark);
547 					view->FillRect(knob.OffsetByCopy(-spacer, 0));
548 					view->SetHighColor(knobLight);
549 					view->FillRect(knob.OffsetByCopy(-spacer + 1, 1));
550 				}
551 
552 				if (rect.right - 3 > hcenter + spacer) {
553 					view->SetHighColor(knobDark);
554 					view->FillRect(knob.OffsetByCopy(spacer, 0));
555 					view->SetHighColor(knobLight);
556 					view->FillRect(knob.OffsetByCopy(spacer + 1, 1));
557 				}
558 			} else {
559 				// B_VERTICAL
560 				view->SetHighColor(knobDark);
561 				view->FillRect(knob);
562 				view->SetHighColor(knobLight);
563 				view->FillRect(knob.OffsetByCopy(1, 1));
564 
565 				float spacer = rect.Width();
566 
567 				if (rect.top + 3 < vmiddle - spacer) {
568 					view->SetHighColor(knobDark);
569 					view->FillRect(knob.OffsetByCopy(0, -spacer));
570 					view->SetHighColor(knobLight);
571 					view->FillRect(knob.OffsetByCopy(1, -spacer + 1));
572 				}
573 
574 				if (rect.bottom - 3 > vmiddle + spacer) {
575 					view->SetHighColor(knobDark);
576 					view->FillRect(knob.OffsetByCopy(0, spacer));
577 					view->SetHighColor(knobLight);
578 					view->FillRect(knob.OffsetByCopy(1, spacer + 1));
579 				}
580 			}
581 		} else if (knobStyle == B_KNOB_LINES && isEnabled) {
582 			// draw lines on the scroll bar thumb
583 			if (orientation == B_HORIZONTAL) {
584 				float middle = rect.Width() / 2;
585 
586 				view->BeginLineArray(6);
587 				view->AddLine(
588 					BPoint(rect.left + middle - 3, rect.top + 2),
589 					BPoint(rect.left + middle - 3, rect.bottom - 2),
590 					knobDark);
591 				view->AddLine(
592 					BPoint(rect.left + middle, rect.top + 2),
593 					BPoint(rect.left + middle, rect.bottom - 2),
594 					knobDark);
595 				view->AddLine(
596 					BPoint(rect.left + middle + 3, rect.top + 2),
597 					BPoint(rect.left + middle + 3, rect.bottom - 2),
598 					knobDark);
599 				view->AddLine(
600 					BPoint(rect.left + middle - 2, rect.top + 2),
601 					BPoint(rect.left + middle - 2, rect.bottom - 2),
602 					knobLight);
603 				view->AddLine(
604 					BPoint(rect.left + middle + 1, rect.top + 2),
605 					BPoint(rect.left + middle + 1, rect.bottom - 2),
606 					knobLight);
607 				view->AddLine(
608 					BPoint(rect.left + middle + 4, rect.top + 2),
609 					BPoint(rect.left + middle + 4, rect.bottom - 2),
610 					knobLight);
611 				view->EndLineArray();
612 			} else {
613 				// B_VERTICAL
614 				float middle = rect.Height() / 2;
615 
616 				view->BeginLineArray(6);
617 				view->AddLine(
618 					BPoint(rect.left + 2, rect.top + middle - 3),
619 					BPoint(rect.right - 2, rect.top + middle - 3),
620 					knobDark);
621 				view->AddLine(
622 					BPoint(rect.left + 2, rect.top + middle),
623 					BPoint(rect.right - 2, rect.top + middle),
624 					knobDark);
625 				view->AddLine(
626 					BPoint(rect.left + 2, rect.top + middle + 3),
627 					BPoint(rect.right - 2, rect.top + middle + 3),
628 					knobDark);
629 				view->AddLine(
630 					BPoint(rect.left + 2, rect.top + middle - 2),
631 					BPoint(rect.right - 2, rect.top + middle - 2),
632 					knobLight);
633 				view->AddLine(
634 					BPoint(rect.left + 2, rect.top + middle + 1),
635 					BPoint(rect.right - 2, rect.top + middle + 1),
636 					knobLight);
637 				view->AddLine(
638 					BPoint(rect.left + 2, rect.top + middle + 4),
639 					BPoint(rect.right - 2, rect.top + middle + 4),
640 					knobLight);
641 				view->EndLineArray();
642 			}
643 		}
644 	}
645 
646 	view->PopState();
647 }
648 
649 
650 void
651 HaikuControlLook::DrawScrollViewFrame(BView* view, BRect& rect,
652 	const BRect& updateRect, BRect verticalScrollBarFrame,
653 	BRect horizontalScrollBarFrame, const rgb_color& base,
654 	border_style borderStyle, uint32 flags, uint32 _borders)
655 {
656 	// calculate scroll corner rect before messing with the "rect"
657 	BRect scrollCornerFillRect(rect.right, rect.bottom,
658 		rect.right, rect.bottom);
659 
660 	if (horizontalScrollBarFrame.IsValid())
661 		scrollCornerFillRect.left = horizontalScrollBarFrame.right + 1;
662 
663 	if (verticalScrollBarFrame.IsValid())
664 		scrollCornerFillRect.top = verticalScrollBarFrame.bottom + 1;
665 
666 	if (borderStyle == B_NO_BORDER) {
667 		if (scrollCornerFillRect.IsValid()) {
668 			view->SetHighColor(base);
669 			view->FillRect(scrollCornerFillRect);
670 		}
671 		return;
672 	}
673 
674 	bool excludeScrollCorner = borderStyle == B_FANCY_BORDER
675 		&& horizontalScrollBarFrame.IsValid()
676 		&& verticalScrollBarFrame.IsValid();
677 
678 	uint32 borders = _borders;
679 	if (excludeScrollCorner) {
680 		rect.bottom = horizontalScrollBarFrame.top;
681 		rect.right = verticalScrollBarFrame.left;
682 		borders &= ~(B_RIGHT_BORDER | B_BOTTOM_BORDER);
683 	}
684 
685 	rgb_color scrollbarFrameColor = tint_color(base, 1.2);
686 
687 	if (borderStyle == B_FANCY_BORDER)
688 		_DrawOuterResessedFrame(view, rect, base, 1.0, 1.0, flags, borders);
689 
690 	if ((flags & B_FOCUSED) != 0) {
691 		_DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor,
692 			scrollbarFrameColor, scrollbarFrameColor, borders);
693 	} else {
694 		_DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor,
695 			scrollbarFrameColor, scrollbarFrameColor, borders);
696 	}
697 
698 	if (excludeScrollCorner) {
699 		horizontalScrollBarFrame.InsetBy(-1, -1);
700 
701 		// do not overdraw the top edge
702 		horizontalScrollBarFrame.top += 2;
703 		borders = _borders;
704 		borders &= ~B_TOP_BORDER;
705 		_DrawOuterResessedFrame(view, horizontalScrollBarFrame, base,
706 			1.0, 1.0, flags, borders);
707 		_DrawFrame(view, horizontalScrollBarFrame, scrollbarFrameColor,
708 			scrollbarFrameColor, scrollbarFrameColor, scrollbarFrameColor,
709 			borders);
710 
711 		verticalScrollBarFrame.InsetBy(-1, -1);
712 
713 		// do not overdraw the left edge
714 		verticalScrollBarFrame.left += 2;
715 		borders = _borders;
716 		borders &= ~B_LEFT_BORDER;
717 		_DrawOuterResessedFrame(view, verticalScrollBarFrame, base,
718 			1.0, 1.0, flags, borders);
719 		_DrawFrame(view, verticalScrollBarFrame, scrollbarFrameColor,
720 			scrollbarFrameColor, scrollbarFrameColor, scrollbarFrameColor,
721 			borders);
722 
723 		// exclude recessed frame
724 		scrollCornerFillRect.top++;
725 		scrollCornerFillRect.left++;
726 	}
727 
728 	if (scrollCornerFillRect.IsValid()) {
729 		view->SetHighColor(base);
730 		view->FillRect(scrollCornerFillRect);
731 	}
732 }
733 
734 
735 rgb_color
736 HaikuControlLook::SliderBarColor(const rgb_color& base)
737 {
738 	rgb_color customColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 1.05);
739 	// if the color BACKGROUND used is too dark, then make it lighter using the
740 	// same as B_CONTROL_TEXT_COLOR
741 	if (base.red + base.green + base.blue <= 128 * 3) {
742 		customColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 0.95);
743 	}
744 
745 	return customColor;
746 }
747 
748 
749 void
750 HaikuControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect,
751 	const rgb_color& base, rgb_color leftFillColor, rgb_color rightFillColor,
752 	float sliderScale, uint32 flags, orientation orientation)
753 {
754 	if (!rect.IsValid() || !rect.Intersects(updateRect))
755 		return;
756 
757 	// save the clipping constraints of the view
758 	view->PushState();
759 
760 	// separate the bar in two sides
761 	float sliderPosition;
762 	BRect leftBarSide = rect;
763 	BRect rightBarSide = rect;
764 
765 	if (orientation == B_HORIZONTAL) {
766 		sliderPosition = floorf(rect.left + 2 + (rect.Width() - 2)
767 			* sliderScale);
768 		leftBarSide.right = sliderPosition - 1;
769 		rightBarSide.left = sliderPosition;
770 	} else {
771 		// NOTE: position is reverse of coords
772 		sliderPosition = floorf(rect.top + 2 + (rect.Height() - 2)
773 			* (1.0 - sliderScale));
774 		leftBarSide.top = sliderPosition;
775 		rightBarSide.bottom = sliderPosition - 1;
776 	}
777 
778 	// fill the background for the corners, exclude the middle bar for now
779 	BRegion region(rect);
780 	region.Exclude(rightBarSide);
781 	view->ConstrainClippingRegion(&region);
782 
783 	view->PushState();
784 
785 	DrawSliderBar(view, rect, updateRect, base, leftFillColor, flags,
786 		orientation);
787 
788 	view->PopState();
789 
790 	region.Set(rect);
791 	region.Exclude(leftBarSide);
792 	view->ConstrainClippingRegion(&region);
793 
794 	view->PushState();
795 
796 	DrawSliderBar(view, rect, updateRect, base, rightFillColor, flags,
797 		orientation);
798 
799 	view->PopState();
800 
801 	// restore the clipping constraints of the view
802 	view->PopState();
803 }
804 
805 
806 void
807 HaikuControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect,
808 	const rgb_color& base, rgb_color fillColor, uint32 flags,
809 	orientation orientation)
810 {
811 	if (!rect.IsValid() || !rect.Intersects(updateRect))
812 		return;
813 
814 	// separate the rect into corners
815 	BRect leftCorner(rect);
816 	BRect rightCorner(rect);
817 	BRect barRect(rect);
818 
819 	if (orientation == B_HORIZONTAL) {
820 		leftCorner.right = leftCorner.left + leftCorner.Height();
821 		rightCorner.left = rightCorner.right - rightCorner.Height();
822 		barRect.left += ceilf(barRect.Height() / 2);
823 		barRect.right -= ceilf(barRect.Height() / 2);
824 	} else {
825 		leftCorner.bottom = leftCorner.top + leftCorner.Width();
826 		rightCorner.top = rightCorner.bottom - rightCorner.Width();
827 		barRect.top += ceilf(barRect.Width() / 2);
828 		barRect.bottom -= ceilf(barRect.Width() / 2);
829 	}
830 
831 	// fill the background for the corners, exclude the middle bar for now
832 	BRegion region(rect);
833 	region.Exclude(barRect);
834 	view->ConstrainClippingRegion(&region);
835 
836 	if ((flags & B_BLEND_FRAME) == 0) {
837 		view->SetHighColor(base);
838 		view->FillRect(rect);
839 	}
840 
841 	// figure out the tints to be used
842 	float edgeLightTint;
843 	float edgeShadowTint;
844 	float frameLightTint;
845 	float frameShadowTint;
846 	float fillLightTint;
847 	float fillShadowTint;
848 	uint8 edgeLightAlpha;
849 	uint8 edgeShadowAlpha;
850 	uint8 frameLightAlpha;
851 	uint8 frameShadowAlpha;
852 
853 	if ((flags & B_DISABLED) != 0) {
854 		edgeLightTint = 1.0;
855 		edgeShadowTint = 1.0;
856 		frameLightTint = 1.05;
857 		frameShadowTint = 1.05;
858 		fillLightTint = 0.8;
859 		fillShadowTint = 0.8;
860 		edgeLightAlpha = 12;
861 		edgeShadowAlpha = 12;
862 		frameLightAlpha = 40;
863 		frameShadowAlpha = 45;
864 
865 		fillColor.red = uint8(fillColor.red * 0.4 + base.red * 0.6);
866 		fillColor.green = uint8(fillColor.green * 0.4 + base.green * 0.6);
867 		fillColor.blue = uint8(fillColor.blue * 0.4 + base.blue * 0.6);
868 	} else {
869 		edgeLightTint = 1.0;
870 		edgeShadowTint = 1.0;
871 		frameLightTint = 1.20;
872 		frameShadowTint = 1.20;
873 		fillLightTint = 0.9;
874 		fillShadowTint = 0.9;
875 		edgeLightAlpha = 15;
876 		edgeShadowAlpha = 15;
877 		frameLightAlpha = 102;
878 		frameShadowAlpha = 117;
879 	}
880 
881 	rgb_color edgeLightColor;
882 	rgb_color edgeShadowColor;
883 	rgb_color frameLightColor;
884 	rgb_color frameShadowColor;
885 	rgb_color fillLightColor = tint_color(fillColor, fillLightTint);
886 	rgb_color fillShadowColor = tint_color(fillColor, fillShadowTint);
887 
888 	drawing_mode oldMode = view->DrawingMode();
889 
890 	if ((flags & B_BLEND_FRAME) != 0) {
891 		edgeLightColor = (rgb_color){ 255, 255, 255, edgeLightAlpha };
892 		edgeShadowColor = (rgb_color){ 0, 0, 0, edgeShadowAlpha };
893 		frameLightColor = (rgb_color){ 0, 0, 0, frameLightAlpha };
894 		frameShadowColor = (rgb_color){ 0, 0, 0, frameShadowAlpha };
895 
896 		view->SetDrawingMode(B_OP_ALPHA);
897 	} else {
898 		edgeLightColor = tint_color(base, edgeLightTint);
899 		edgeShadowColor = tint_color(base, edgeShadowTint);
900 		frameLightColor = tint_color(fillColor, frameLightTint);
901 		frameShadowColor = tint_color(fillColor, frameShadowTint);
902 	}
903 
904 	if (orientation == B_HORIZONTAL) {
905 		_DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor,
906 			edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
907 			fillShadowColor, 1.0, 1.0, 0.0, -1.0, orientation);
908 
909 		_DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor,
910 			edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
911 			fillShadowColor, 0.0, 1.0, -1.0, -1.0, orientation);
912 	} else {
913 		_DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor,
914 			edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
915 			fillShadowColor, 1.0, 1.0, -1.0, 0.0, orientation);
916 
917 		_DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor,
918 			edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
919 			fillShadowColor, 1.0, 0.0, -1.0, -1.0, orientation);
920 	}
921 
922 	view->ConstrainClippingRegion(NULL);
923 
924 	view->BeginLineArray(4);
925 	if (orientation == B_HORIZONTAL) {
926 		view->AddLine(barRect.LeftTop(), barRect.RightTop(),
927 			edgeShadowColor);
928 		view->AddLine(barRect.LeftBottom(), barRect.RightBottom(),
929 			edgeLightColor);
930 		barRect.InsetBy(0, 1);
931 		view->AddLine(barRect.LeftTop(), barRect.RightTop(),
932 			frameShadowColor);
933 		view->AddLine(barRect.LeftBottom(), barRect.RightBottom(),
934 			frameLightColor);
935 		barRect.InsetBy(0, 1);
936 	} else {
937 		view->AddLine(barRect.LeftTop(), barRect.LeftBottom(),
938 			edgeShadowColor);
939 		view->AddLine(barRect.RightTop(), barRect.RightBottom(),
940 			edgeLightColor);
941 		barRect.InsetBy(1, 0);
942 		view->AddLine(barRect.LeftTop(), barRect.LeftBottom(),
943 			frameShadowColor);
944 		view->AddLine(barRect.RightTop(), barRect.RightBottom(),
945 			frameLightColor);
946 		barRect.InsetBy(1, 0);
947 	}
948 	view->EndLineArray();
949 
950 	view->SetDrawingMode(oldMode);
951 
952 	_FillGradient(view, barRect, fillColor, fillShadowTint, fillLightTint,
953 		orientation);
954 }
955 
956 
957 void
958 HaikuControlLook::DrawSliderThumb(BView* view, BRect& rect, const BRect& updateRect,
959 	const rgb_color& base, uint32 flags, orientation orientation)
960 {
961 	if (!rect.IsValid() || !rect.Intersects(updateRect))
962 		return;
963 
964 	rgb_color thumbColor = tint_color(ui_color(B_SCROLL_BAR_THUMB_COLOR), 1.0);
965 
966 	// figure out frame color
967 	rgb_color frameLightColor;
968 	rgb_color frameShadowColor;
969 	rgb_color shadowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 0.5);
970 
971 	//if the color BACKGROUND used is too dark, then make it lighter using the same as B_CONTROL_TEXT_COLOR
972 	if (base.red + base.green + base.blue <= 128 * 3) {
973 		shadowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 1.55);
974 	}
975 
976 	if ((flags & B_FOCUSED) != 0) {
977 		// focused
978 		frameLightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
979 		frameShadowColor = frameLightColor;
980 	} else {
981 		// figure out the tints to be used
982 		float frameLightTint;
983 		float frameShadowTint;
984 
985 		if ((flags & B_DISABLED) != 0) {
986 			frameLightTint = 1.30;
987 			frameShadowTint = 1.35;
988 			shadowColor.alpha = 30;
989 		} else {
990 			frameLightTint = 1.6;
991 			frameShadowTint = 1.65;
992 		}
993 
994 		frameLightColor = tint_color(base, frameLightTint);
995 		frameShadowColor = tint_color(base, frameShadowTint);
996 	}
997 
998 	BRect originalRect(rect);
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 HaikuControlLook::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 HaikuControlLook::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 HaikuControlLook::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 HaikuControlLook::_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 HaikuControlLook::_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 HaikuControlLook::_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 HaikuControlLook::_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 HaikuControlLook::_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 HaikuControlLook::_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 HaikuControlLook::_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