xref: /haiku/src/add-ons/control_look/BeControlLook/BeControlLook.cpp (revision dd2a1e350b303b855a50fd64e6cb55618be1ae6a)
1 /*
2  * Copyright 2003-2023 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  *		DarkWyrm, bpmagic@columbus.rr.com
8  *		Marc Flerackers, mflerackers@androme.be
9  *		François Revol, revol@free.fr
10  *		John Scipione, jscipione@gmail.com
11  *		Clemens Zeidler, haiku@clemens-zeidler.de
12  */
13 
14 
15 /*! BControlLook resembling BeOS R5 */
16 
17 
18 #include "BeControlLook.h"
19 
20 #include <algorithm>
21 
22 #include <Alignment.h>
23 #include <Bitmap.h>
24 #include <Button.h>
25 #include <Control.h>
26 #include <LayoutUtils.h>
27 #include <Region.h>
28 #include <Shape.h>
29 #include <String.h>
30 #include <TabView.h>
31 #include <View.h>
32 #include <Window.h>
33 #include <WindowPrivate.h>
34 
35 //#define DEBUG_CONTROL_LOOK
36 #ifdef DEBUG_CONTROL_LOOK
37 #  define STRACE(x) printf x
38 #else
39 #  define STRACE(x) ;
40 #endif
41 
42 
43 namespace BPrivate {
44 
45 static const float kButtonPopUpIndicatorWidth = 11;
46 
47 
48 BeControlLook::BeControlLook(image_id id)
49 	:
50 	fCachedOutline(false)
51 {
52 }
53 
54 
55 BeControlLook::~BeControlLook()
56 {
57 }
58 
59 
60 BAlignment
61 BeControlLook::DefaultLabelAlignment() const
62 {
63 	return BAlignment(B_ALIGN_LEFT, B_ALIGN_VERTICAL_CENTER);
64 }
65 
66 
67 float
68 BeControlLook::DefaultLabelSpacing() const
69 {
70 	return ceilf(be_plain_font->Size() / 2.0);
71 }
72 
73 
74 float
75 BeControlLook::DefaultItemSpacing() const
76 {
77 	return ceilf(be_plain_font->Size() * 0.85);
78 }
79 
80 
81 uint32
82 BeControlLook::Flags(BControl* control) const
83 {
84 	uint32 flags = B_IS_CONTROL;
85 
86 	if (!control->IsEnabled())
87 		flags |= B_DISABLED;
88 
89 	if (control->IsFocus() && control->Window() != NULL
90 		&& control->Window()->IsActive()) {
91 		flags |= B_FOCUSED;
92 	}
93 
94 	switch (control->Value()) {
95 		case B_CONTROL_ON:
96 			flags |= B_ACTIVATED;
97 			break;
98 		case B_CONTROL_PARTIALLY_ON:
99 			flags |= B_PARTIALLY_ACTIVATED;
100 			break;
101 	}
102 
103 	if (control->Parent() != NULL
104 		&& (control->Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0) {
105 		// In this constellation, assume we want to render the control
106 		// against the already existing view contents of the parent view.
107 		flags |= B_BLEND_FRAME;
108 	}
109 
110 	return flags;
111 }
112 
113 
114 void
115 BeControlLook::DrawButtonFrame(BView* view, BRect& rect,
116 	const BRect& updateRect, const rgb_color& base,
117 	const rgb_color& background, uint32 flags, uint32 borders)
118 {
119 	_DrawButtonFrame(view, rect, updateRect, 0, 0, 0, 0, base,
120 		background, 1.0, 1.0, flags, borders);
121 }
122 
123 
124 void
125 BeControlLook::DrawButtonFrame(BView* view, BRect& rect,
126 	const BRect& updateRect, float, const rgb_color& base,
127 	const rgb_color& background, uint32 flags, uint32 borders)
128 {
129 	_DrawButtonFrame(view, rect, updateRect, 0, 0, 0, 0, base,
130 		background, 1.0, 1.0, flags, borders);
131 }
132 
133 
134 void
135 BeControlLook::DrawButtonFrame(BView* view, BRect& rect,
136 	const BRect& updateRect, float, float, float, float, const rgb_color& base,
137 	const rgb_color& background, uint32 flags, uint32 borders)
138 {
139 	_DrawButtonFrame(view, rect, updateRect, 0, 0, 0, 0, base,
140 		background, 1.0, 1.0, flags, borders);
141 }
142 
143 
144 void
145 BeControlLook::DrawButtonBackground(BView* view, BRect& rect,
146 	const BRect& updateRect, const rgb_color& base, uint32 flags,
147 	uint32 borders, orientation orientation)
148 {
149 	_DrawButtonBackground(view, rect, updateRect, 0, 0, 0, 0,
150 		base, false, flags, borders, orientation);
151 }
152 
153 
154 void
155 BeControlLook::DrawButtonBackground(BView* view, BRect& rect,
156 	const BRect& updateRect, float, const rgb_color& base, uint32 flags,
157 	uint32 borders, orientation orientation)
158 {
159 	_DrawButtonBackground(view, rect, updateRect, 0, 0, 0, 0,
160 		base, false, flags, borders, orientation);
161 }
162 
163 
164 void
165 BeControlLook::DrawButtonBackground(BView* view, BRect& rect,
166 	const BRect& updateRect, float, float, float, float, const rgb_color& base,
167 	uint32 flags, uint32 borders, orientation orientation)
168 {
169 	_DrawButtonBackground(view, rect, updateRect, 0, 0, 0, 0,
170 		base, false, flags, borders, orientation);
171 }
172 
173 
174 void
175 BeControlLook::DrawCheckBox(BView* view, BRect& rect, const BRect& updateRect,
176 	const rgb_color& base, uint32 flags)
177 {
178 	if (!rect.Intersects(updateRect))
179 		return;
180 
181 	bool isEnabled = (flags & B_DISABLED) == 0;
182 	bool isActivated = (flags & B_ACTIVATED) != 0;
183 	bool isFocused = (flags & B_FOCUSED) != 0;
184 	bool isClicked = (flags & B_CLICKED) != 0;
185 
186 	rgb_color lighten1 = tint_color(base, B_LIGHTEN_1_TINT);
187 	rgb_color lightenMax = tint_color(base, B_LIGHTEN_MAX_TINT);
188 	rgb_color darken1 = tint_color(base, B_DARKEN_1_TINT);
189 	rgb_color darken2 = tint_color(base, B_DARKEN_2_TINT);
190 	rgb_color darken3 = tint_color(base, B_DARKEN_3_TINT);
191 	rgb_color darken4 = tint_color(base, B_DARKEN_4_TINT);
192 
193 	view->SetLowColor(base);
194 
195 	if (isEnabled) {
196 		// Filling
197 		view->SetHighColor(lightenMax);
198 		view->FillRect(rect);
199 
200 		// Box
201 		if (isClicked) {
202 			view->SetHighColor(darken3);
203 			view->StrokeRect(rect);
204 
205 			rect.InsetBy(1, 1);
206 
207 			view->BeginLineArray(6);
208 
209 			view->AddLine(BPoint(rect.left, rect.bottom),
210 				BPoint(rect.left, rect.top), darken2);
211 			view->AddLine(BPoint(rect.left, rect.top),
212 				BPoint(rect.right, rect.top), darken2);
213 			view->AddLine(BPoint(rect.left, rect.bottom),
214 				BPoint(rect.right, rect.bottom), darken4);
215 			view->AddLine(BPoint(rect.right, rect.bottom),
216 				BPoint(rect.right, rect.top), darken4);
217 
218 			view->EndLineArray();
219 		} else {
220 			view->BeginLineArray(6);
221 
222 			view->AddLine(BPoint(rect.left, rect.bottom),
223 				BPoint(rect.left, rect.top), darken1);
224 			view->AddLine(BPoint(rect.left, rect.top),
225 				BPoint(rect.right, rect.top), darken1);
226 
227 			rect.InsetBy(1, 1);
228 			view->AddLine(BPoint(rect.left, rect.bottom),
229 				BPoint(rect.left, rect.top), darken4);
230 			view->AddLine(BPoint(rect.left, rect.top),
231 				BPoint(rect.right, rect.top), darken4);
232 			view->AddLine(BPoint(rect.left + 1, rect.bottom),
233 				BPoint(rect.right, rect.bottom), base);
234 			view->AddLine(BPoint(rect.right, rect.bottom),
235 				BPoint(rect.right, rect.top + 1), base);
236 
237 			view->EndLineArray();
238 		}
239 
240 		// Focus
241 		if (isFocused) {
242 			view->SetDrawingMode(B_OP_OVER);
243 			view->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
244 			view->StrokeRect(rect);
245 			view->SetDrawingMode(B_OP_COPY);
246 		}
247 	} else {
248 		// Filling
249 		view->SetHighColor(lighten1);
250 		view->FillRect(rect);
251 
252 		// Box
253 		view->BeginLineArray(6);
254 
255 		view->AddLine(BPoint(rect.left, rect.bottom),
256 				BPoint(rect.left, rect.top), base);
257 		view->AddLine(BPoint(rect.left, rect.top),
258 				BPoint(rect.right, rect.top), base);
259 
260 		rect.InsetBy(1, 1);
261 		view->AddLine(BPoint(rect.left, rect.bottom),
262 				BPoint(rect.left, rect.top), darken2);
263 		view->AddLine(BPoint(rect.left, rect.top),
264 				BPoint(rect.right, rect.top), darken2);
265 		view->AddLine(BPoint(rect.left + 1, rect.bottom),
266 				BPoint(rect.right, rect.bottom), darken1);
267 		view->AddLine(BPoint(rect.right, rect.bottom),
268 				BPoint(rect.right, rect.top + 1), darken1);
269 
270 		view->EndLineArray();
271 	}
272 
273 	// Checkmark
274 	if (isActivated) {
275 		rect.InsetBy(4, 4);
276 
277 		float penSize = std::max(1, 2);
278 		if (penSize > 1 && fmodf(penSize, 2) == 0) {
279 			// Tweak ends to "include" the pixel at the index,
280 			// we need to do this in order to produce results like R5,
281 			// where coordinates were inclusive
282 			rect.right++;
283 			rect.bottom++;
284 		}
285 
286 		view->SetPenSize(penSize);
287 		view->SetDrawingMode(B_OP_OVER);
288 		if (isEnabled)
289 			view->SetHighColor(ui_color(B_CONTROL_MARK_COLOR));
290 		else {
291 			view->SetHighColor(tint_color(ui_color(B_CONTROL_MARK_COLOR),
292 				B_DISABLED_MARK_TINT));
293 		}
294 		view->StrokeLine(rect.LeftTop(), rect.RightBottom());
295 		view->StrokeLine(rect.LeftBottom(), rect.RightTop());
296 	}
297 }
298 
299 
300 void
301 BeControlLook::DrawRadioButton(BView* view, BRect& rect,
302 	const BRect& updateRect, const rgb_color& base, uint32 flags)
303 {
304 	if (!ShouldDraw(view, rect, updateRect))
305 		return;
306 
307 	bool isEnabled = (flags & B_DISABLED) == 0;
308 	bool isActivated = (flags & B_ACTIVATED) != 0;
309 	bool isFocused = (flags & B_FOCUSED) != 0;
310 
311 	// colors
312 	rgb_color bg = ui_color(B_PANEL_BACKGROUND_COLOR);
313 	rgb_color lightenmax;
314 	rgb_color lighten1;
315 	rgb_color darken1;
316 	rgb_color darken2;
317 	rgb_color darken3;
318 
319 	rgb_color markColor = ui_color(B_CONTROL_MARK_COLOR);
320 	rgb_color knob;
321 	rgb_color knobDark;
322 	rgb_color knobLight;
323 
324 	if (isEnabled) {
325 		lightenmax	= tint_color(bg, B_LIGHTEN_MAX_TINT);
326 		lighten1	= tint_color(bg, B_LIGHTEN_1_TINT);
327 		darken1		= tint_color(bg, B_DARKEN_1_TINT);
328 		darken2		= tint_color(bg, B_DARKEN_2_TINT);
329 		darken3		= tint_color(bg, B_DARKEN_3_TINT);
330 
331 		knob		= markColor;
332 		knobDark	= tint_color(markColor, B_DARKEN_3_TINT);
333 		knobLight	= tint_color(markColor, 0.15);
334 	} else {
335 		lightenmax	= tint_color(bg, B_LIGHTEN_2_TINT);
336 		lighten1	= bg;
337 		darken1		= bg;
338 		darken2		= tint_color(bg, B_DARKEN_1_TINT);
339 		darken3		= tint_color(bg, B_DARKEN_2_TINT);
340 
341 		knob		= tint_color(markColor, B_LIGHTEN_2_TINT);
342 		knobDark	= tint_color(markColor, B_LIGHTEN_1_TINT);
343 		knobLight	= tint_color(markColor,
344 			(B_LIGHTEN_2_TINT + B_LIGHTEN_MAX_TINT) / 2.0);
345 	}
346 
347 	rect.InsetBy(2, 2);
348 
349 	view->SetLowColor(bg);
350 
351 	// dot
352 	if (isActivated) {
353 		// full
354 		view->SetHighColor(knobDark);
355 		view->FillEllipse(rect);
356 
357 		view->SetHighColor(knob);
358 		view->FillEllipse(BRect(rect.left + 2, rect.top + 2, rect.right - 3,
359 			rect.bottom - 3));
360 
361 		view->SetHighColor(knobLight);
362 		view->FillEllipse(BRect(rect.left + 3, rect.top + 3, rect.right - 5,
363 			rect.bottom - 5));
364 	} else {
365 		// empty
366 		view->SetHighColor(lightenmax);
367 		view->FillEllipse(rect);
368 	}
369 
370 	rect.InsetBy(-1, -1);
371 
372 	// outer circle
373 	if (isFocused) {
374 		// indicating "about to change value"
375 		view->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
376 		view->SetPenSize(2);
377 		view->SetDrawingMode(B_OP_OVER);
378 		view->StrokeEllipse(rect.InsetByCopy(1, 1));
379 		view->SetDrawingMode(B_OP_COPY);
380 		view->SetPenSize(1);
381 	} else {
382 		view->SetHighColor(darken1);
383 		view->StrokeArc(rect, 45.0, 180.0);
384 		view->SetHighColor(lightenmax);
385 		view->StrokeArc(rect, 45.0, -180.0);
386 	}
387 
388 	// inner circle
389 	view->SetHighColor(darken3);
390 	view->StrokeArc(rect, 45.0, 180.0);
391 	view->SetHighColor(bg);
392 	view->StrokeArc(rect, 45.0, -180.0);
393 
394 	// for faster font rendering, we restore B_OP_COPY
395 	view->SetDrawingMode(B_OP_COPY);
396 }
397 
398 
399 void
400 BeControlLook::DrawScrollBarBorder(BView* view, BRect rect,
401 	const BRect& updateRect, const rgb_color& base, uint32 flags,
402 	orientation orientation)
403 {
404 	if (!ShouldDraw(view, rect, updateRect))
405 		return;
406 
407 	view->PushState();
408 
409 	view->ClipToRect(rect);
410 
411 	bool isEnabled = (flags & B_DISABLED) == 0;
412 	bool isFocused = (flags & B_FOCUSED) != 0;
413 
414 	if (isEnabled && isFocused)
415 		view->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
416 	else
417 		view->SetHighColor(tint_color(base, B_DARKEN_2_TINT));
418 
419 	view->StrokeRect(rect);
420 
421 	view->PopState();
422 }
423 
424 
425 void
426 BeControlLook::DrawScrollBarButton(BView* view, BRect rect,
427 	const BRect& updateRect, const rgb_color& base, uint32 flags,
428 	int32 direction, orientation orientation, bool down)
429 {
430 	view->PushState();
431 
432 	bool isEnabled = (flags & B_DISABLED) == 0;
433 
434 	// border = 152, shine = 144/255, shadow = 208/184/192
435 	rgb_color shine = down ? tint_color(base, 1.333)
436 		: tint_color(base, B_LIGHTEN_MAX_TINT);
437 	rgb_color shadow;
438 	if (isEnabled && down)
439 		shadow = tint_color(base, 1.037);
440 	else if (isEnabled)
441 		shadow = tint_color(base, B_DARKEN_1_TINT);
442 	else
443 		shadow = tint_color(base, 1.111);
444 
445 	view->BeginLineArray(4);
446 	view->AddLine(rect.LeftTop(), rect.LeftBottom() - BPoint(0, 1), shine);
447 	view->AddLine(rect.LeftTop(), rect.RightTop() - BPoint(1, 0), shine);
448 	view->AddLine(rect.RightTop(), rect.RightBottom() - BPoint(0, 1), shadow);
449 	view->AddLine(rect.LeftBottom(), rect.RightBottom(), shadow);
450 	view->EndLineArray();
451 
452 	rgb_color bg;
453 	if (isEnabled) {
454 		// bg = 176/216
455 		bg = down ? tint_color(base, 1.185) : base;
456 	} else {
457 		// bg = 240
458 		rgb_color lighten2 = tint_color(base, B_LIGHTEN_2_TINT);
459 		lighten2.red++; lighten2.green++; lighten2.blue++;
460 			// lighten2 = 239, 240 = 239 + 1
461 		bg = lighten2;
462 	}
463 	view->SetHighColor(bg);
464 	rect.InsetBy(1, 1);
465 	view->FillRect(rect);
466 
467 	// draw button triangle
468 	// don't use DrawArrowShape because we use that to draw arrows differently
469 	// in menus and outline list view
470 
471 	rect.InsetBy(1, 1);
472 	rect.OffsetBy(-3, -3);
473 
474 	BPoint tri1, tri2, tri3;
475 	BPoint off1, off2, off3;
476 	BRect r(rect.left, rect.top, rect.left + 14, rect.top + 14);
477 	rgb_color lightenmax = tint_color(base, B_LIGHTEN_MAX_TINT);
478 	rgb_color light, dark, arrow, arrow2;
479 
480 	switch(direction) {
481 		case B_LEFT_ARROW:
482 			tri1.Set(r.left + 3, floorf((r.top + r.bottom) / 2));
483 			tri2.Set(r.right - 4, r.top + 4);
484 			tri3.Set(r.right - 4, r.bottom - 4);
485 			break;
486 
487 		default:
488 		case B_RIGHT_ARROW:
489 			tri1.Set(r.left + 4, r.bottom - 4);
490 			tri2.Set(r.left + 4, r.top + 4);
491 			tri3.Set(r.right - 3, floorf((r.top + r.bottom) / 2));
492 			break;
493 
494 		case B_UP_ARROW:
495 			tri1.Set(r.left + 4, r.bottom - 4);
496 			tri2.Set(floorf((r.left + r.right) / 2), r.top + 3);
497 			tri3.Set(r.right - 4, r.bottom - 4);
498 			break;
499 
500 		case B_DOWN_ARROW:
501 			tri1.Set(r.left + 4, r.top + 4);
502 			tri2.Set(r.right - 4, r.top + 4);
503 			tri3.Set(floorf((r.left + r.right) / 2), r.bottom - 3);
504 			break;
505 	}
506 
507 	r.InsetBy(1, 1);
508 
509 	float tint = B_NO_TINT;
510 	if (!isEnabled)
511 		tint = (tint + B_NO_TINT + B_NO_TINT) / 3;
512 
513 	view->SetHighColor(tint_color(base, tint));
514 	view->MovePenTo(B_ORIGIN);
515 	view->SetDrawingMode(B_OP_OVER);
516 
517 	view->SetHighColor(tint_color(base, tint));
518 
519 	if (isEnabled) {
520 		arrow2 = light = tint_color(base, B_DARKEN_2_TINT);
521 		dark = tint_color(base, B_DARKEN_3_TINT);
522 		arrow = tint_color(base, B_DARKEN_MAX_TINT);
523 	} else
524 		arrow = arrow2 = light = dark = tint_color(base, B_DARKEN_1_TINT);
525 
526 	// white triangle offset by 1px
527 	off1.Set(tri1.x + 1, tri1.y + 1);
528 	off2.Set(tri2.x + 1, tri2.y + 1);
529 	off3.Set(tri3.x + 1, tri3.y + 1);
530 
531 	// draw white triangle
532 	view->BeginLineArray(3);
533 	view->AddLine(off2, off3, lightenmax);
534 	view->AddLine(off1, off3, lightenmax);
535 	view->AddLine(off1, off2, lightenmax);
536 	view->EndLineArray();
537 
538 	// draw triangle on top
539 	view->BeginLineArray(3);
540 	view->AddLine(tri2, tri3, dark);
541 	view->AddLine(tri1, tri3, dark);
542 	view->AddLine(tri1, tri2, arrow2);
543 	view->EndLineArray();
544 
545 	view->PopState();
546 }
547 
548 
549 void
550 BeControlLook::DrawScrollBarBackground(BView* view, BRect& rect1, BRect& rect2,
551 	const BRect& updateRect, const rgb_color& base, uint32 flags,
552 	orientation orientation)
553 {
554 	_DrawScrollBarBackgroundFirst(view, rect1, updateRect, base, flags,
555 		orientation);
556 	_DrawScrollBarBackgroundSecond(view, rect2, updateRect, base, flags,
557 		orientation);
558 }
559 
560 
561 void
562 BeControlLook::DrawScrollBarBackground(BView* view, BRect& rect,
563 	const BRect& updateRect, const rgb_color& base, uint32 flags,
564 	orientation orientation)
565 {
566 	_DrawScrollBarBackgroundFirst(view, rect, updateRect, base, flags,
567 		orientation);
568 }
569 
570 
571 void
572 BeControlLook::DrawScrollBarThumb(BView* view, BRect& rect,
573 	const BRect& updateRect, const rgb_color& base, uint32 flags,
574 	orientation orientation, uint32 knobStyle)
575 {
576 	if (!ShouldDraw(view, rect, updateRect))
577 		return;
578 
579 	view->PushState();
580 
581 	view->ClipToRect(rect);
582 
583 	bool isEnabled = (flags & B_DISABLED) == 0;
584 
585 	BRect orig(rect);
586 
587 	// shine = 255
588 	rgb_color shine = tint_color(base, B_LIGHTEN_MAX_TINT);
589 	rgb_color bg;
590 	if (isEnabled) {
591 		// bg = 216
592 		bg = base;
593 	} else {
594 		// bg = 240
595 		rgb_color lighten2 = tint_color(base, B_LIGHTEN_2_TINT);
596 		lighten2.red++; lighten2.green++; lighten2.blue++;
597 			// lighten2 = 239, 240 = 239 + 1
598 		bg = lighten2;
599 	}
600 
601 	// draw thumb over background
602 	view->SetDrawingMode(B_OP_OVER);
603 
604 	view->BeginLineArray(2);
605 	if (orientation == B_VERTICAL) {
606 		// shine
607 		view->AddLine(rect.LeftTop(), rect.LeftBottom(), shine);
608 		rect.left++;
609 		view->AddLine(rect.LeftTop(), rect.RightTop(), shine);
610 		rect.top++;
611 	} else {
612 		// shine
613 		view->AddLine(rect.LeftTop(), rect.LeftBottom(), shine);
614 		rect.left++;
615 		view->AddLine(rect.LeftTop(), rect.RightTop(), shine);
616 		rect.top++;
617 	}
618 	view->EndLineArray();
619 
620 	// fill bg
621 	view->SetHighColor(bg);
622 	view->FillRect(rect);
623 
624 	// undraw right top or left bottom point
625 	view->BeginLineArray(1);
626 	if (orientation == B_VERTICAL) {
627 		rect.right--;
628 		view->AddLine(rect.RightTop(), rect.RightTop(), base);
629 	} else {
630 		rect.bottom--;
631 		view->AddLine(rect.LeftBottom(), rect.LeftBottom(), base);
632 	}
633 	view->EndLineArray();
634 
635 	// restore rect
636 	rect = orig;
637 
638 	// knobs
639 
640 	if (knobStyle != B_KNOB_NONE) {
641 		float hcenter = rect.left + rect.Width() / 2;
642 		float vmiddle = rect.top + rect.Height() / 2;
643 		rgb_color knobDark = tint_color(base, B_DARKEN_1_TINT);
644 		rgb_color knobLight = tint_color(base, B_LIGHTEN_MAX_TINT);
645 
646 		if (knobStyle == B_KNOB_DOTS) {
647 			// center/middle dot
648 			_DrawScrollBarKnobDot(view, hcenter, vmiddle, knobDark, knobLight,
649 				orientation);
650 			if (orientation == B_HORIZONTAL) {
651 				float spacer = rect.Height();
652 				// left dot
653 				if (rect.left + 7 < hcenter - spacer) {
654 					_DrawScrollBarKnobDot(view, hcenter - 7, vmiddle, knobDark,
655 						knobLight, orientation);
656 				}
657 				// right dot
658 				if (rect.right - 7 > hcenter + spacer) {
659 					_DrawScrollBarKnobDot(view, hcenter + 7, vmiddle, knobDark,
660 						knobLight, orientation);
661 				}
662 			} else {
663 				float spacer = rect.Width();
664 				// top dot
665 				if (rect.top + 7 < vmiddle - spacer) {
666 					_DrawScrollBarKnobDot(view, hcenter, vmiddle - 7, knobDark,
667 						knobLight, orientation);
668 				}
669 				// bottom dot
670 				if (rect.bottom - 7 > vmiddle + spacer) {
671 					_DrawScrollBarKnobDot(view, hcenter, vmiddle + 7, knobDark,
672 						knobLight, orientation);
673 				}
674 			}
675 		} else if (knobStyle == B_KNOB_LINES) {
676 			// center/middle line
677 			_DrawScrollBarKnobLine(view, hcenter, vmiddle, knobDark, knobLight,
678 				orientation);
679 			if (orientation == B_HORIZONTAL) {
680 				float spacer = rect.Height();
681 				// left line
682 				if (rect.left + 4 < hcenter - spacer) {
683 					_DrawScrollBarKnobLine(view, hcenter - 4, vmiddle, knobDark,
684 						knobLight, orientation);
685 				}
686 				// right line
687 				if (rect.right - 4 > hcenter + spacer) {
688 					_DrawScrollBarKnobLine(view, hcenter + 4, vmiddle, knobDark,
689 						knobLight, orientation);
690 				}
691 			} else {
692 				float spacer = rect.Width();
693 				// top line
694 				if (rect.top + 4 < vmiddle - spacer) {
695 					_DrawScrollBarKnobLine(view, hcenter, vmiddle - 4, knobDark,
696 						knobLight, orientation);
697 				}
698 				// bottom line
699 				if (rect.bottom - 5 > vmiddle + spacer) {
700 					_DrawScrollBarKnobLine(view, hcenter, vmiddle + 4, knobDark,
701 						knobLight, orientation);
702 				}
703 			}
704 		}
705 	}
706 
707 	view->PopState();
708 }
709 
710 
711 
712 void
713 BeControlLook::DrawScrollViewFrame(BView* view, BRect& rect,
714 	const BRect& updateRect, BRect verticalScrollBarFrame,
715 	BRect horizontalScrollBarFrame, const rgb_color& base,
716 	border_style borderStyle, uint32 flags, uint32 _borders)
717 {
718 	rgb_color darken1 = tint_color(base, B_DARKEN_1_TINT);
719 	rgb_color lightenmax = tint_color(base, B_LIGHTEN_MAX_TINT);
720 
721 	view->BeginLineArray(4);
722 	view->AddLine(rect.LeftBottom(), rect.LeftTop(), darken1);
723 	view->AddLine(rect.LeftTop(), rect.RightTop(), darken1);
724 	view->AddLine(rect.RightTop(), rect.RightBottom(), lightenmax);
725 	view->AddLine(rect.RightBottom(), rect.LeftBottom(), lightenmax);
726 	view->EndLineArray();
727 
728 	rect.InsetBy(1, 1);
729 
730 	bool isEnabled = (flags & B_DISABLED) == 0;
731 	bool isFocused = (flags & B_FOCUSED) != 0;
732 
733 	if (isEnabled && isFocused)
734 		view->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
735 	else
736 		view->SetHighColor(tint_color(base, B_DARKEN_2_TINT));
737 
738 	view->StrokeRect(rect);
739 }
740 
741 
742 void
743 BeControlLook::DrawArrowShape(BView* view, BRect& rect, const BRect& updateRect,
744 	const rgb_color& base, uint32 direction, uint32 flags, float tint)
745 {
746 	if (!ShouldDraw(view, rect, updateRect))
747 		return;
748 
749 	view->PushState();
750 
751 	rgb_color fill = tint_color(base, 1.074); // 200
752 	rgb_color stroke = tint_color(base, 1.629); // 80
753 
754 	switch(direction) {
755 		case B_LEFT_ARROW:
756 			view->SetHighColor(fill);
757 			view->FillTriangle(rect.LeftTop() + BPoint(4, 6),
758 				rect.LeftTop() + BPoint(8, 2),
759 				rect.LeftTop() + BPoint(8, 10));
760 			view->SetHighColor(stroke);
761 			view->StrokeTriangle(rect.LeftTop() + BPoint(4, 6),
762 				rect.LeftTop() + BPoint(8, 2),
763 				rect.LeftTop() + BPoint(8, 10));
764 			break;
765 
766 		default:
767 		case B_RIGHT_ARROW:
768 			view->SetHighColor(fill);
769 			view->FillTriangle(rect.LeftTop() + BPoint(4, 2),
770 				rect.LeftTop() + BPoint(4, 10),
771 				rect.LeftTop() + BPoint(8, 6));
772 			view->SetHighColor(stroke);
773 			view->StrokeTriangle(rect.LeftTop() + BPoint(4, 2),
774 				rect.LeftTop() + BPoint(4, 10),
775 				rect.LeftTop() + BPoint(8, 6));
776 			break;
777 
778 		case B_UP_ARROW:
779 			view->SetHighColor(fill);
780 			view->FillTriangle(rect.LeftTop() + BPoint(6, 4),
781 				rect.LeftTop() + BPoint(2, 8),
782 				rect.LeftTop() + BPoint(10, 8));
783 			view->SetHighColor(stroke);
784 			view->StrokeTriangle(rect.LeftTop() + BPoint(6, 4),
785 				rect.LeftTop() + BPoint(2, 8),
786 				rect.LeftTop() + BPoint(10, 8));
787 			break;
788 
789 		case B_DOWN_ARROW:
790 			view->SetHighColor(fill);
791 			view->FillTriangle(rect.LeftTop() + BPoint(2, 4),
792 				rect.LeftTop() + BPoint(10, 4),
793 				rect.LeftTop() + BPoint(6, 8));
794 			view->SetHighColor(stroke);
795 			view->StrokeTriangle(rect.LeftTop() + BPoint(2, 4),
796 				rect.LeftTop() + BPoint(10, 4),
797 				rect.LeftTop() + BPoint(6, 8));
798 			break;
799 	}
800 
801 	view->PopState();
802 }
803 
804 
805 void
806 BeControlLook::DrawMenuBarBackground(BView* view, BRect& rect,
807 	const BRect& updateRect, const rgb_color& base, uint32 flags,
808 	uint32 borders)
809 {
810 	if (!ShouldDraw(view, rect, updateRect))
811 		return;
812 
813 	view->PushState();
814 
815 	// restore the background color in case a menu item was selected
816 	view->SetHighColor(base);
817 	view->FillRect(rect);
818 
819 	rgb_color lighten2 = tint_color(base, B_LIGHTEN_2_TINT);
820 	rgb_color darken1 = tint_color(base, B_DARKEN_1_TINT);
821 
822 	view->BeginLineArray(3);
823 	view->AddLine(rect.LeftTop(), rect.RightTop(), lighten2);
824 	// left bottom pixel is base color
825 	view->AddLine(rect.LeftTop(), rect.LeftBottom() - BPoint(0, 1),
826 		lighten2);
827 	view->AddLine(rect.LeftBottom() + BPoint(1, 0), rect.RightBottom(),
828 		darken1);
829 	view->EndLineArray();
830 
831 	view->PopState();
832 }
833 
834 
835 void
836 BeControlLook::DrawMenuFieldFrame(BView* view, BRect& rect,
837 	const BRect& updateRect, const rgb_color& base,
838 	const rgb_color& background, uint32 flags, uint32 borders)
839 {
840 	// BeControlLook does not support rounded corners and it never will
841 	DrawMenuFieldFrame(view, rect, updateRect, 0, base, background, flags,
842 		borders);
843 }
844 
845 
846 void
847 BeControlLook::DrawMenuFieldFrame(BView* view, BRect& rect,
848 	const BRect& updateRect, float, const rgb_color& base,
849 	const rgb_color& background, uint32 flags, uint32 borders)
850 {
851 	// BeControlLook does not support rounded corners and it never will
852 	DrawMenuFieldFrame(view, rect, updateRect, 0, 0, 0, 0, base,
853 		background, flags, borders);
854 }
855 
856 
857 void
858 BeControlLook::DrawMenuFieldFrame(BView* view, BRect& rect,
859 	const BRect& updateRect, float, float, float, float, const rgb_color& base,
860 	const rgb_color& background, uint32 flags, uint32 borders)
861 {
862 	if (!ShouldDraw(view, rect, updateRect))
863 		return;
864 
865 	bool isEnabled = (flags & B_DISABLED) == 0;
866 	bool isFocused = (flags & B_FOCUSED) != 0;
867 
868 	// inset the frame by 2 and draw the outer border
869 	rect.InsetBy(2, 2);
870 
871 	rgb_color darken2 = tint_color(base, B_DARKEN_2_TINT);
872 
873 	// draw left and top side and top right corner
874 	view->BeginLineArray(3);
875 	view->AddLine(BPoint(rect.left - 1, rect.top - 1),
876 		BPoint(rect.left - 1, rect.bottom - 1), darken2);
877 	view->AddLine(BPoint(rect.left - 1, rect.top - 1),
878 		BPoint(rect.right - 1, rect.top - 1), darken2);
879 	view->AddLine(BPoint(rect.right, rect.top - 1),
880 		BPoint(rect.right, rect.top - 1), darken2);
881 	view->EndLineArray();
882 
883 	if (isEnabled && isFocused) {
884 		// draw the focus ring on top of the frame
885 		// Note that this is an intentional deviation from BeOS R5
886 		// which draws the frame around the outside of the frame
887 		// but that doesn't look as good.
888 		view->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
889 		view->StrokeRect(rect.InsetByCopy(-1, -1));
890 	}
891 }
892 
893 
894 void
895 BeControlLook::DrawMenuFieldBackground(BView* view, BRect& rect,
896 	const BRect& updateRect, const rgb_color& base, bool popupIndicator,
897 	uint32 flags)
898 {
899 	_DrawMenuFieldBackgroundOutside(view, rect, updateRect,
900 		0, 0, 0, 0, base, popupIndicator, flags);
901 }
902 
903 
904 void
905 BeControlLook::DrawMenuFieldBackground(BView* view, BRect& rect,
906 	const BRect& updateRect, const rgb_color& base, uint32 flags,
907 	uint32 borders)
908 {
909 	_DrawMenuFieldBackgroundInside(view, rect, updateRect,
910 		0, 0, 0, 0, base, flags, borders);
911 }
912 
913 
914 void
915 BeControlLook::DrawMenuFieldBackground(BView* view, BRect& rect,
916 	const BRect& updateRect, float, const rgb_color& base,
917 	bool popupIndicator, uint32 flags)
918 {
919 	_DrawMenuFieldBackgroundOutside(view, rect, updateRect, 0, 0,
920 		0, 0, base, popupIndicator, flags);
921 }
922 
923 
924 void
925 BeControlLook::DrawMenuFieldBackground(BView* view, BRect& rect,
926 	const BRect& updateRect, float, float, float, float, const rgb_color& base,
927 	bool popupIndicator, uint32 flags)
928 {
929 	_DrawMenuFieldBackgroundOutside(view, rect, updateRect, 0, 0,
930 		0, 0, base, popupIndicator, flags);
931 }
932 
933 
934 void
935 BeControlLook::DrawMenuBackground(BView* view, BRect& rect,
936 	const BRect& updateRect, const rgb_color& base, uint32 flags,
937 	uint32 borders)
938 {
939 	if (!ShouldDraw(view, rect, updateRect))
940 		return;
941 
942 	view->PushState();
943 
944 	view->SetHighColor(base);
945 	view->FillRect(rect);
946 
947 	view->PopState();
948 }
949 
950 
951 void
952 BeControlLook::DrawMenuItemBackground(BView* view, BRect& rect,
953 	const BRect& updateRect, const rgb_color& base, uint32 flags,
954 	uint32 borders)
955 {
956 	if (!ShouldDraw(view, rect, updateRect))
957 		return;
958 
959 	view->PushState();
960 
961 	view->SetHighColor(base);
962 	view->FillRect(rect);
963 
964 	view->PopState();
965 }
966 
967 
968 void
969 BeControlLook::DrawStatusBar(BView* view, BRect& rect, const BRect& updateRect,
970 	const rgb_color& base, const rgb_color& barColor, float progressPosition)
971 {
972 	if (!ShouldDraw(view, rect, updateRect))
973 		return;
974 
975 	view->PushState();
976 
977 	// draw background
978 	view->SetHighColor(base);
979 	view->FillRect(rect);
980 
981 	// draw frame around bar
982 	DrawTextControlBorder(view, rect, updateRect, tint_color(base, B_DARKEN_1_TINT));
983 
984 	// filled and nonfilled rects
985 	BRect filledRect(rect);
986 	filledRect.right = progressPosition - 1;
987 	BRect nonfilledRect(rect);
988 	nonfilledRect.left = progressPosition;
989 
990 	bool drawFilled = filledRect.Width() > 0;
991 	bool drawNonfilled = nonfilledRect.Width() > 0;
992 
993 	// filled
994 	if (drawFilled) {
995 		rgb_color light = tint_color(barColor, 0.6);
996 		rgb_color dark = tint_color(barColor, 1.4);
997 		_DrawFrame(view, filledRect, light, light, dark, dark);
998 
999 		view->SetHighColor(barColor);
1000 		view->FillRect(filledRect);
1001 	}
1002 
1003 	// nonfilled
1004 	if (drawNonfilled) {
1005 		view->SetHighColor(ui_color(B_CONTROL_BACKGROUND_COLOR));
1006 		view->FillRect(nonfilledRect);
1007 	}
1008 
1009 	view->PopState();
1010 }
1011 
1012 
1013 rgb_color
1014 BeControlLook::SliderBarColor(const rgb_color& base)
1015 {
1016 	return tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_1_TINT);
1017 }
1018 
1019 
1020 void
1021 BeControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect,
1022 	const rgb_color& base, rgb_color leftFillColor, rgb_color rightFillColor,
1023 	float sliderScale, uint32 flags, orientation orientation)
1024 {
1025 	if (!ShouldDraw(view, rect, updateRect))
1026 		return;
1027 
1028 	// separate the bar in two sides
1029 	float sliderPosition;
1030 	BRect leftBarSide = rect;
1031 	BRect rightBarSide = rect;
1032 
1033 	if (orientation == B_HORIZONTAL) {
1034 		sliderPosition = floorf(rect.left + 2 + (rect.Width() - 2)
1035 			* sliderScale);
1036 		leftBarSide.right = sliderPosition - 1;
1037 		rightBarSide.left = sliderPosition;
1038 	} else {
1039 		// NOTE: position is reverse of coords
1040 		sliderPosition = floorf(rect.top + 2 + (rect.Height() - 2)
1041 			* (1.0 - sliderScale));
1042 		leftBarSide.top = sliderPosition;
1043 		rightBarSide.bottom = sliderPosition - 1;
1044 	}
1045 
1046 	view->PushState();
1047 	view->ClipToRect(leftBarSide);
1048 
1049 	DrawSliderBar(view, rect, updateRect, base, leftFillColor, flags,
1050 		orientation);
1051 	view->PopState();
1052 
1053 	view->PushState();
1054 	view->ClipToRect(rightBarSide);
1055 
1056 	DrawSliderBar(view, rect, updateRect, base, rightFillColor, flags,
1057 		orientation);
1058 	view->PopState();
1059 }
1060 
1061 
1062 void
1063 BeControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect,
1064 	const rgb_color& base, rgb_color fillColor, uint32 flags,
1065 	orientation orientation)
1066 {
1067 	if (!ShouldDraw(view, rect, updateRect))
1068 		return;
1069 
1070 	view->SetHighColor(fillColor);
1071 	view->FillRect(rect);
1072 
1073 	rgb_color lightenmax = tint_color(base, B_LIGHTEN_MAX_TINT);
1074 	rgb_color darken1 = tint_color(base, B_DARKEN_1_TINT);
1075 	rgb_color darken2 = tint_color(base, B_DARKEN_2_TINT);
1076 	rgb_color darkenmax = tint_color(base, B_DARKEN_MAX_TINT);
1077 
1078 	view->BeginLineArray(9);
1079 
1080 	view->AddLine(BPoint(rect.left, rect.top),
1081 		BPoint(rect.left + 1, rect.top), darken1);
1082 	view->AddLine(BPoint(rect.left, rect.bottom),
1083 		BPoint(rect.left + 1, rect.bottom), darken1);
1084 	view->AddLine(BPoint(rect.right - 1, rect.top),
1085 		BPoint(rect.right, rect.top), darken1);
1086 
1087 	view->AddLine(BPoint(rect.left + 1, rect.top),
1088 		BPoint(rect.right - 1, rect.top), darken2);
1089 	view->AddLine(BPoint(rect.left, rect.bottom - 1),
1090 		BPoint(rect.left, rect.top + 1), darken2);
1091 
1092 	view->AddLine(BPoint(rect.left + 1, rect.bottom),
1093 		BPoint(rect.right, rect.bottom), lightenmax);
1094 	view->AddLine(BPoint(rect.right, rect.top + 1),
1095 		BPoint(rect.right, rect.bottom), lightenmax);
1096 
1097 	rect.InsetBy(1, 1);
1098 
1099 	view->AddLine(BPoint(rect.left, rect.top),
1100 		BPoint(rect.left, rect.bottom), darkenmax);
1101 	view->AddLine(BPoint(rect.left, rect.top),
1102 		BPoint(rect.right, rect.top), darkenmax);
1103 
1104 	view->EndLineArray();
1105 }
1106 
1107 
1108 void
1109 BeControlLook::DrawSliderThumb(BView* view, BRect& rect, const BRect& updateRect,
1110 	const rgb_color& base, uint32 flags, orientation orientation)
1111 {
1112 	if (!ShouldDraw(view, rect, updateRect))
1113 		return;
1114 
1115 	rgb_color lighten2 = tint_color(base, B_LIGHTEN_2_TINT);
1116 	rgb_color dark = tint_color(base, 1.333); // 144
1117 	rgb_color darker = tint_color(base, 1.444); // 120
1118 	rgb_color darkenmax = tint_color(base, B_DARKEN_MAX_TINT);
1119 
1120 	view->BeginLineArray(14);
1121 
1122 	// outline
1123 	view->AddLine(BPoint(rect.left, rect.bottom - 2),
1124 		BPoint(rect.left, rect.top + 1), darker);
1125 	view->AddLine(BPoint(rect.left + 1, rect.top),
1126 		BPoint(rect.right - 2, rect.top), darker);
1127 	view->AddLine(BPoint(rect.right, rect.top + 2),
1128 		BPoint(rect.right, rect.bottom - 1), darker);
1129 	view->AddLine(BPoint(rect.left + 2, rect.bottom),
1130 		BPoint(rect.right - 1, rect.bottom), darker);
1131 
1132 	// first bevel
1133 	rect.InsetBy(1, 1);
1134 
1135 	view->SetHighColor(lighten2);
1136 	view->FillRect(rect);
1137 
1138 	view->AddLine(BPoint(rect.left, rect.bottom),
1139 		BPoint(rect.right - 1, rect.bottom), darkenmax);
1140 	view->AddLine(BPoint(rect.right, rect.bottom - 1),
1141 		BPoint(rect.right, rect.top), darkenmax);
1142 
1143 	rect.InsetBy(1, 1);
1144 
1145 	// second bevel and center dots
1146 	view->SetHighColor(dark);
1147 	view->AddLine(BPoint(rect.left, rect.bottom),
1148 		BPoint(rect.right, rect.bottom), dark);
1149 	view->AddLine(BPoint(rect.right, rect.top),
1150 		BPoint(rect.right, rect.bottom), dark);
1151 
1152 	// center dots
1153 	float hCenter = rect.Width() / 2;
1154 	float vMiddle = rect.Height() / 2;
1155 	if (orientation == B_HORIZONTAL) {
1156 		view->AddLine(BPoint(rect.left + hCenter, rect.top + 1),
1157 			BPoint(rect.left + hCenter, rect.top + 1), dark);
1158 		view->AddLine(BPoint(rect.left + hCenter, rect.top + 3),
1159 			BPoint(rect.left + hCenter, rect.top + 3), dark);
1160 		view->AddLine(BPoint(rect.left + hCenter, rect.top + 5),
1161 			BPoint(rect.left + hCenter, rect.top + 5), dark);
1162 	} else {
1163 		view->AddLine(BPoint(rect.left + 1, rect.top + vMiddle),
1164 			BPoint(rect.left + 1, rect.top + vMiddle), dark);
1165 		view->AddLine(BPoint(rect.left + 3, rect.top + vMiddle),
1166 			BPoint(rect.left + 3, rect.top + vMiddle), dark);
1167 		view->AddLine(BPoint(rect.left + 5, rect.top + vMiddle - 1),
1168 			BPoint(rect.left + 5, rect.top + vMiddle), dark);
1169 	}
1170 
1171 	view->AddLine(BPoint(rect.right + 1, rect.bottom + 1),
1172 		BPoint(rect.right + 1, rect.bottom + 1), dark);
1173 
1174 	rect.InsetBy(1, 1);
1175 
1176 	// third bevel
1177 	view->AddLine(BPoint(rect.left, rect.bottom),
1178 		BPoint(rect.right, rect.bottom), base);
1179 	view->AddLine(BPoint(rect.right, rect.top),
1180 		BPoint(rect.right, rect.bottom), base);
1181 
1182 	view->EndLineArray();
1183 }
1184 
1185 
1186 void
1187 BeControlLook::DrawSliderTriangle(BView* view, BRect& rect,
1188 	const BRect& updateRect, const rgb_color& base, uint32 flags,
1189 	orientation orientation)
1190 {
1191 	DrawSliderTriangle(view, rect, updateRect, base, base, flags, orientation);
1192 }
1193 
1194 
1195 void
1196 BeControlLook::DrawSliderTriangle(BView* view, BRect& rect,
1197 	const BRect& updateRect, const rgb_color& base, const rgb_color& fill,
1198 	uint32 flags, orientation orientation)
1199 {
1200 	if (!ShouldDraw(view, rect, updateRect))
1201 		return;
1202 
1203 	rgb_color lighten1 = tint_color(base, B_LIGHTEN_1_TINT);
1204 	rgb_color darken2 = tint_color(base, B_DARKEN_2_TINT);
1205 	rgb_color darkenmax = tint_color(base, B_DARKEN_MAX_TINT);
1206 
1207 	if (orientation == B_HORIZONTAL) {
1208 		view->SetHighColor(lighten1);
1209 		view->FillTriangle(BPoint(rect.left, rect.bottom - 1),
1210 			BPoint(rect.left + 6, rect.top),
1211 			BPoint(rect.right, rect.bottom - 1));
1212 
1213 		view->SetHighColor(darkenmax);
1214 		view->StrokeLine(BPoint(rect.right, rect.bottom + 1),
1215 			BPoint(rect.left, rect.bottom + 1));
1216 		view->StrokeLine(BPoint(rect.right, rect.bottom),
1217 			BPoint(rect.left + 6, rect.top));
1218 
1219 		view->SetHighColor(darken2);
1220 		view->StrokeLine(BPoint(rect.right - 1, rect.bottom),
1221 			BPoint(rect.left, rect.bottom));
1222 		view->StrokeLine(BPoint(rect.left, rect.bottom),
1223 			BPoint(rect.left + 5, rect.top + 1));
1224 
1225 		view->SetHighColor(base);
1226 		view->StrokeLine(BPoint(rect.right - 2, rect.bottom - 1),
1227 			BPoint(rect.left + 3, rect.bottom - 1));
1228 		view->StrokeLine(BPoint(rect.right - 3, rect.bottom - 2),
1229 			BPoint(rect.left + 6, rect.top + 1));
1230 	} else {
1231 		view->SetHighColor(lighten1);
1232 		view->FillTriangle(BPoint(rect.left + 1, rect.top),
1233 			BPoint(rect.left + 7, rect.top + 6),
1234 			BPoint(rect.left + 1, rect.bottom));
1235 
1236 		view->SetHighColor(darkenmax);
1237 		view->StrokeLine(BPoint(rect.left, rect.top + 1),
1238 			BPoint(rect.left, rect.bottom));
1239 		view->StrokeLine(BPoint(rect.left + 1, rect.bottom),
1240 			BPoint(rect.left + 7, rect.top + 6));
1241 
1242 		view->SetHighColor(darken2);
1243 		view->StrokeLine(BPoint(rect.left, rect.top),
1244 			BPoint(rect.left, rect.bottom - 1));
1245 		view->StrokeLine(BPoint(rect.left + 1, rect.top),
1246 			BPoint(rect.left + 6, rect.top + 5));
1247 
1248 		view->SetHighColor(base);
1249 		view->StrokeLine(BPoint(rect.left + 1, rect.top + 2),
1250 			BPoint(rect.left + 1, rect.bottom - 1));
1251 		view->StrokeLine(BPoint(rect.left + 2, rect.bottom - 2),
1252 			BPoint(rect.left + 6, rect.top + 6));
1253 	}
1254 }
1255 
1256 
1257 void
1258 BeControlLook::DrawSliderHashMarks(BView* view, BRect& rect,
1259 	const BRect& updateRect, const rgb_color& base, int32 count,
1260 	hash_mark_location location, uint32 flags, orientation orientation)
1261 {
1262 	if (!ShouldDraw(view, rect, updateRect))
1263 		return;
1264 
1265 	rgb_color lightColor;
1266 	rgb_color darkColor;
1267 
1268 	if ((flags & B_DISABLED) != 0) {
1269 		lightColor = tint_color(base, 0.9);
1270 		darkColor = tint_color(base, 1.07);
1271 	} else {
1272 		lightColor = tint_color(base, 0.8);
1273 		darkColor = tint_color(base, 1.14);
1274 	}
1275 
1276 	int32 hashMarkCount = std::max(count, (int32)2);
1277 		// draw at least two hashmarks at min/max if
1278 		// fHashMarks != B_HASH_MARKS_NONE
1279 	float factor;
1280 	float startPos;
1281 	if (orientation == B_HORIZONTAL) {
1282 		factor = (rect.Width() - 2) / (hashMarkCount - 1);
1283 		startPos = rect.left + 1;
1284 	} else {
1285 		factor = (rect.Height() - 2) / (hashMarkCount - 1);
1286 		startPos = rect.top + 1;
1287 	}
1288 
1289 	if (location & B_HASH_MARKS_TOP) {
1290 		view->BeginLineArray(hashMarkCount * 2);
1291 
1292 		if (orientation == B_HORIZONTAL) {
1293 			float pos = startPos;
1294 			for (int32 i = 0; i < hashMarkCount; i++) {
1295 				view->AddLine(BPoint(pos, rect.top),
1296 							  BPoint(pos, rect.top + 4), darkColor);
1297 				view->AddLine(BPoint(pos + 1, rect.top),
1298 							  BPoint(pos + 1, rect.top + 4), lightColor);
1299 
1300 				pos += factor;
1301 			}
1302 		} else {
1303 			float pos = startPos;
1304 			for (int32 i = 0; i < hashMarkCount; i++) {
1305 				view->AddLine(BPoint(rect.left, pos),
1306 							  BPoint(rect.left + 4, pos), darkColor);
1307 				view->AddLine(BPoint(rect.left, pos + 1),
1308 							  BPoint(rect.left + 4, pos + 1), lightColor);
1309 
1310 				pos += factor;
1311 			}
1312 		}
1313 
1314 		view->EndLineArray();
1315 	}
1316 
1317 	if ((location & B_HASH_MARKS_BOTTOM) != 0) {
1318 		view->BeginLineArray(hashMarkCount * 2);
1319 
1320 		if (orientation == B_HORIZONTAL) {
1321 			float pos = startPos;
1322 			for (int32 i = 0; i < hashMarkCount; i++) {
1323 				view->AddLine(BPoint(pos, rect.bottom - 4),
1324 							  BPoint(pos, rect.bottom), darkColor);
1325 				view->AddLine(BPoint(pos + 1, rect.bottom - 4),
1326 							  BPoint(pos + 1, rect.bottom), lightColor);
1327 
1328 				pos += factor;
1329 			}
1330 		} else {
1331 			float pos = startPos;
1332 			for (int32 i = 0; i < hashMarkCount; i++) {
1333 				view->AddLine(BPoint(rect.right - 4, pos),
1334 							  BPoint(rect.right, pos), darkColor);
1335 				view->AddLine(BPoint(rect.right - 4, pos + 1),
1336 							  BPoint(rect.right, pos + 1), lightColor);
1337 
1338 				pos += factor;
1339 			}
1340 		}
1341 
1342 		view->EndLineArray();
1343 	}
1344 }
1345 
1346 
1347 void
1348 BeControlLook::DrawTabFrame(BView* view, BRect& rect, const BRect& updateRect,
1349 	const rgb_color& base, uint32 flags, uint32 borders,
1350 	border_style borderStyle, uint32 side)
1351 {
1352 	view->SetHighColor(base);
1353 	view->FillRect(rect);
1354 
1355 	rgb_color lightenmax = tint_color(base, B_LIGHTEN_MAX_TINT);
1356 
1357 	view->BeginLineArray(1);
1358 
1359 	switch(side) {
1360 		case BTabView::kLeftSide:
1361 			view->AddLine(BPoint(rect.right, rect.top),
1362 				BPoint(rect.right, rect.bottom), lightenmax);
1363 			break;
1364 
1365 		case BTabView::kRightSide:
1366 			view->AddLine(BPoint(rect.left, rect.top),
1367 				BPoint(rect.left, rect.bottom), lightenmax);
1368 			break;
1369 
1370 		default:
1371 		case BTabView::kTopSide:
1372 			view->AddLine(BPoint(rect.left, rect.bottom),
1373 				BPoint(rect.right, rect.bottom), lightenmax);
1374 			break;
1375 
1376 		case BTabView::kBottomSide:
1377 			view->AddLine(BPoint(rect.left, rect.top),
1378 				BPoint(rect.right, rect.top), lightenmax);
1379 			break;
1380 	}
1381 
1382 	view->EndLineArray();
1383 }
1384 
1385 
1386 void
1387 BeControlLook::DrawActiveTab(BView* view, BRect& rect,
1388 	const BRect& updateRect, const rgb_color& base, uint32 flags,
1389 	uint32 borders, uint32 side, int32, int32, int32, int32)
1390 {
1391 	if (!ShouldDraw(view, rect, updateRect))
1392 		return;
1393 
1394 	view->PushState();
1395 
1396 	// clip draw rect to rect plus 2px
1397 	view->ClipToRect(rect.InsetByCopy(-2, -2));
1398 
1399 	// set colors and draw
1400 
1401 	rgb_color lightenmax = tint_color(base, B_LIGHTEN_MAX_TINT);
1402 	rgb_color darken4 = tint_color(base, B_DARKEN_4_TINT);
1403 	rgb_color darkenmax = tint_color(base, B_DARKEN_MAX_TINT);
1404 
1405 	view->SetHighColor(darkenmax);
1406 	view->SetLowColor(base);
1407 
1408 	view->BeginLineArray(12);
1409 
1410 	switch (side) {
1411 		case BTabView::kLeftSide:
1412 			// before going left
1413 			view->AddLine(BPoint(rect.right - 1, rect.top - 1),
1414 				BPoint(rect.right - 1, rect.top - 1), lightenmax);
1415 			view->AddLine(BPoint(rect.right - 2, rect.top),
1416 				BPoint(rect.right - 3, rect.top), lightenmax);
1417 
1418 			// going left
1419 			view->AddLine(BPoint(rect.right - 4, rect.top + 1),
1420 				BPoint(rect.left + 5, rect.top + 1), lightenmax);
1421 
1422 			// before going down
1423 			view->AddLine(BPoint(rect.left + 2, rect.top + 2),
1424 				BPoint(rect.left + 4, rect.top + 2), lightenmax);
1425 			view->AddLine(BPoint(rect.left + 1, rect.top + 3),
1426 				BPoint(rect.left + 1, rect.top + 4 ), lightenmax);
1427 
1428 			// going down
1429 			view->AddLine(BPoint(rect.left, rect.top + 5),
1430 				BPoint(rect.left, rect.bottom - 5), lightenmax);
1431 
1432 			// after going down
1433 			view->AddLine(BPoint(rect.left + 1, rect.bottom - 4),
1434 				BPoint(rect.left + 1, rect.bottom - 3), lightenmax);
1435 			view->AddLine(BPoint(rect.left + 2, rect.bottom - 2),
1436 				BPoint(rect.left + 3, rect.bottom - 2), darken4);
1437 
1438 			// going right
1439 			view->AddLine(BPoint(rect.left + 4, rect.bottom - 1),
1440 				BPoint(rect.right - 4, rect.bottom - 1), darken4);
1441 
1442 			// after going right
1443 			view->AddLine(BPoint(rect.right - 3, rect.bottom),
1444 				BPoint(rect.right - 2, rect.bottom), darken4);
1445 			view->AddLine(BPoint(rect.right - 1, rect.bottom + 1),
1446 				BPoint(rect.right - 1, rect.bottom + 1), darken4);
1447 			view->AddLine(BPoint(rect.right, rect.bottom + 2),
1448 				BPoint(rect.right, rect.bottom + 2), darken4);
1449 			break;
1450 
1451 		case BTabView::kRightSide:
1452 			// before going right
1453 			view->AddLine(BPoint(rect.left - 1, rect.top - 1),
1454 				BPoint(rect.left - 1, rect.top - 1), lightenmax);
1455 			view->AddLine(BPoint(rect.left - 2, rect.top),
1456 				BPoint(rect.left - 3, rect.top), lightenmax);
1457 
1458 			// going right
1459 			view->AddLine(BPoint(rect.left - 4, rect.top + 1),
1460 				BPoint(rect.right + 5, rect.top + 1), lightenmax);
1461 
1462 			// before going down
1463 			view->AddLine(BPoint(rect.right + 2, rect.top + 2),
1464 				BPoint(rect.right + 4, rect.top + 2), lightenmax);
1465 			view->AddLine(BPoint(rect.right + 1, rect.top + 3),
1466 				BPoint(rect.right + 1, rect.top + 4 ), lightenmax);
1467 
1468 			// going down
1469 			view->AddLine(BPoint(rect.right, rect.top + 5),
1470 				BPoint(rect.right, rect.bottom - 5), lightenmax);
1471 
1472 			// after going down
1473 			view->AddLine(BPoint(rect.right + 1, rect.bottom - 4),
1474 				BPoint(rect.right + 1, rect.bottom - 3), lightenmax);
1475 			view->AddLine(BPoint(rect.right + 2, rect.bottom - 2),
1476 				BPoint(rect.right + 3, rect.bottom - 2), darken4);
1477 
1478 			// going left
1479 			view->AddLine(BPoint(rect.right + 4, rect.bottom - 1),
1480 				BPoint(rect.left - 4, rect.bottom - 1), darken4);
1481 
1482 			// after going left
1483 			view->AddLine(BPoint(rect.left - 3, rect.bottom),
1484 				BPoint(rect.left - 2, rect.bottom), darken4);
1485 			view->AddLine(BPoint(rect.left - 1, rect.bottom + 1),
1486 				BPoint(rect.left - 1, rect.bottom + 1), darken4);
1487 			view->AddLine(BPoint(rect.left, rect.bottom + 2),
1488 				BPoint(rect.left, rect.bottom + 2), darken4);
1489 			break;
1490 
1491 		default:
1492 		case BTabView::kTopSide:
1493 			// before going up
1494 			view->AddLine(BPoint(rect.left - 1, rect.bottom - 1),
1495 				BPoint(rect.left - 1, rect.bottom - 1), lightenmax);
1496 			view->AddLine(BPoint(rect.left, rect.bottom - 2),
1497 				BPoint(rect.left, rect.bottom - 3), lightenmax);
1498 
1499 			// going up
1500 			view->AddLine(BPoint(rect.left + 1, rect.bottom - 4),
1501 				BPoint(rect.left + 1, rect.top + 5), lightenmax);
1502 
1503 			// before going right
1504 			view->AddLine(BPoint(rect.left + 2, rect.top + 4),
1505 				BPoint(rect.left + 2, rect.top + 2), lightenmax);
1506 			view->AddLine(BPoint(rect.left + 3, rect.top + 1),
1507 				BPoint(rect.left + 4, rect.top + 1), lightenmax);
1508 
1509 			// going right
1510 			view->AddLine(BPoint(rect.left + 5, rect.top),
1511 				BPoint(rect.right - 5, rect.top), lightenmax);
1512 
1513 			// after going right
1514 			view->AddLine(BPoint(rect.right - 4, rect.top + 1),
1515 				BPoint(rect.right - 3, rect.top + 1), lightenmax);
1516 			view->AddLine(BPoint(rect.right - 2, rect.top + 2),
1517 				BPoint(rect.right - 2, rect.top + 3), darken4);
1518 
1519 			// going down
1520 			view->AddLine(BPoint(rect.right - 1, rect.top + 4),
1521 				BPoint(rect.right - 1, rect.bottom - 4), darken4);
1522 
1523 			// after going down
1524 			view->AddLine(BPoint(rect.right, rect.bottom - 3),
1525 				BPoint(rect.right, rect.bottom - 2), darken4);
1526 			view->AddLine(BPoint(rect.right + 1, rect.bottom - 1),
1527 				BPoint(rect.right + 1, rect.bottom - 1), darken4);
1528 			view->AddLine(BPoint(rect.right + 2, rect.bottom),
1529 				BPoint(rect.right + 2, rect.bottom), darken4);
1530 			break;
1531 
1532 		case BTabView::kBottomSide:
1533 			// before going down
1534 			view->AddLine(BPoint(rect.left - 1, rect.top - 1),
1535 				BPoint(rect.left - 1, rect.top - 1), lightenmax);
1536 			view->AddLine(BPoint(rect.left, rect.top - 2),
1537 				BPoint(rect.left, rect.top - 3), lightenmax);
1538 
1539 			// going down
1540 			view->AddLine(BPoint(rect.left + 1, rect.top - 4),
1541 				BPoint(rect.left + 1, rect.bottom + 5), lightenmax);
1542 
1543 			// before going right
1544 			view->AddLine(BPoint(rect.left + 2, rect.bottom + 4),
1545 				BPoint(rect.left + 2, rect.bottom + 2), lightenmax);
1546 			view->AddLine(BPoint(rect.left + 3, rect.bottom + 1),
1547 				BPoint(rect.left + 4, rect.bottom + 1), lightenmax);
1548 
1549 			// going right
1550 			view->AddLine(BPoint(rect.left + 5, rect.bottom),
1551 				BPoint(rect.right - 5, rect.bottom), lightenmax);
1552 
1553 			// after going right
1554 			view->AddLine(BPoint(rect.right - 4, rect.bottom + 1),
1555 				BPoint(rect.right - 3, rect.bottom + 1), lightenmax);
1556 			view->AddLine(BPoint(rect.right - 2, rect.bottom + 2),
1557 				BPoint(rect.right - 2, rect.bottom + 3), darken4);
1558 
1559 			// going up
1560 			view->AddLine(BPoint(rect.right - 1, rect.bottom + 4),
1561 				BPoint(rect.right - 1, rect.top - 4), darken4);
1562 
1563 			// after going up
1564 			view->AddLine(BPoint(rect.right, rect.top - 3),
1565 				BPoint(rect.right, rect.top - 2), darken4);
1566 			view->AddLine(BPoint(rect.right + 1, rect.top - 1),
1567 				BPoint(rect.right + 1, rect.top - 1), darken4);
1568 			view->AddLine(BPoint(rect.right + 2, rect.top),
1569 				BPoint(rect.right + 2, rect.top), darken4);
1570 			break;
1571 	}
1572 	view->EndLineArray();
1573 
1574 	// undraw white line
1575 	view->BeginLineArray(1);
1576 	switch (side) {
1577 		case BTabView::kLeftSide:
1578 			view->AddLine(BPoint(rect.right, rect.top - 1),
1579 				BPoint(rect.right, rect.bottom + 1), base);
1580 			break;
1581 
1582 		case BTabView::kRightSide:
1583 			view->AddLine(BPoint(rect.left, rect.top - 1),
1584 				BPoint(rect.left, rect.bottom + 1), base);
1585 			break;
1586 
1587 		default:
1588 		case BTabView::kTopSide:
1589 			view->AddLine(BPoint(rect.left - 1, rect.bottom),
1590 				BPoint(rect.right + 1, rect.bottom), base);
1591 			break;
1592 
1593 		case BTabView::kBottomSide:
1594 			view->AddLine(BPoint(rect.left - 1, rect.top),
1595 				BPoint(rect.right + 1, rect.top), base);
1596 			break;
1597 	}
1598 	view->EndLineArray();
1599 
1600 	// inset rect for view contents
1601 	rect.InsetBy(2, 2);
1602 
1603 	view->PopState();
1604 }
1605 
1606 
1607 void
1608 BeControlLook::DrawInactiveTab(BView* view, BRect& rect,
1609 	const BRect& updateRect, const rgb_color& base, uint32 flags,
1610 	uint32 borders, uint32 side, int32 index, int32 selected,
1611 	int32 first, int32 last)
1612 {
1613 	if (!ShouldDraw(view, rect, updateRect))
1614 		return;
1615 
1616 	bool isFirst = index == first;
1617 	bool isFull = index != selected - 1;
1618 
1619 	view->PushState();
1620 
1621 	// clip draw rect to rect plus 2px
1622 	view->ClipToRect(rect.InsetByCopy(-2, -2));
1623 
1624 	// set colors and draw
1625 
1626 	rgb_color lightenmax = tint_color(base, B_LIGHTEN_MAX_TINT);
1627 	rgb_color darken4 = tint_color(base, B_DARKEN_4_TINT);
1628 	rgb_color darkenmax = tint_color(base, B_DARKEN_MAX_TINT);
1629 
1630 	view->SetHighColor(darkenmax);
1631 	view->SetLowColor(base);
1632 
1633 	view->BeginLineArray(12);
1634 
1635 	switch (side) {
1636 		case BTabView::kLeftSide:
1637 			// only draw if first tab is unselected
1638 			if (isFirst) {
1639 				// before going left
1640 				view->AddLine(BPoint(rect.right - 1, rect.top - 1),
1641 					BPoint(rect.right - 1, rect.top - 1), lightenmax);
1642 				view->AddLine(BPoint(rect.right - 2, rect.top),
1643 					BPoint(rect.right - 3, rect.top), lightenmax);
1644 			}
1645 
1646 			// going left
1647 			view->AddLine(BPoint(rect.right - 4, rect.top + 1),
1648 				BPoint(rect.left + 5, rect.top + 1), lightenmax);
1649 
1650 			// before going down
1651 			view->AddLine(BPoint(rect.left + 2, rect.top + 2),
1652 				BPoint(rect.left + 4, rect.top + 2), lightenmax);
1653 			view->AddLine(BPoint(rect.left + 1, rect.top + 3),
1654 				BPoint(rect.left + 1, rect.top + 4 ), lightenmax);
1655 
1656 			// going down
1657 			view->AddLine(BPoint(rect.left, rect.top + 5),
1658 				BPoint(rect.left, rect.bottom - 5), lightenmax);
1659 
1660 			// after going down
1661 			view->AddLine(BPoint(rect.left + 1, rect.bottom - 4),
1662 				BPoint(rect.left + 1, rect.bottom - 3), lightenmax);
1663 			view->AddLine(BPoint(rect.left + 2, rect.bottom - 2),
1664 				BPoint(rect.left + 3, rect.bottom - 2), darken4);
1665 
1666 			// going right
1667 			view->AddLine(BPoint(rect.left + 4, rect.bottom - 1),
1668 				BPoint(rect.right - 4, rect.bottom - 1), darken4);
1669 
1670 			// only draw if not before selected tab
1671 			if (isFull) {
1672 				// after going right
1673 				view->AddLine(BPoint(rect.right - 3, rect.bottom),
1674 					BPoint(rect.right - 2, rect.bottom), darken4);
1675 				view->AddLine(BPoint(rect.right - 1, rect.bottom + 1),
1676 					BPoint(rect.right - 1, rect.bottom + 1), darken4);
1677 			}
1678 			break;
1679 
1680 		case BTabView::kRightSide:
1681 			// only draw if first tab is unselected
1682 			if (isFirst) {
1683 				// before going right
1684 				view->AddLine(BPoint(rect.left - 1, rect.top - 1),
1685 					BPoint(rect.left - 1, rect.top - 1), lightenmax);
1686 				view->AddLine(BPoint(rect.left - 2, rect.top),
1687 					BPoint(rect.left - 3, rect.top), lightenmax);
1688 			}
1689 
1690 			// going right
1691 			view->AddLine(BPoint(rect.left - 4, rect.top + 1),
1692 				BPoint(rect.right + 5, rect.top + 1), lightenmax);
1693 
1694 			// before going down
1695 			view->AddLine(BPoint(rect.right + 2, rect.top + 2),
1696 				BPoint(rect.right + 4, rect.top + 2), lightenmax);
1697 			view->AddLine(BPoint(rect.right + 1, rect.top + 3),
1698 				BPoint(rect.right + 1, rect.top + 4 ), lightenmax);
1699 
1700 			// going down
1701 			view->AddLine(BPoint(rect.right, rect.top + 5),
1702 				BPoint(rect.right, rect.bottom - 5), lightenmax);
1703 
1704 			// after going down
1705 			view->AddLine(BPoint(rect.right + 1, rect.bottom - 4),
1706 				BPoint(rect.right + 1, rect.bottom - 3), lightenmax);
1707 			view->AddLine(BPoint(rect.right + 2, rect.bottom - 2),
1708 				BPoint(rect.right + 3, rect.bottom - 2), darken4);
1709 
1710 			// going left
1711 			view->AddLine(BPoint(rect.right + 4, rect.bottom - 1),
1712 				BPoint(rect.left - 4, rect.bottom - 1), darken4);
1713 
1714 			// only draw if not before selected tab
1715 			if (isFull) {
1716 				// after going left
1717 				view->AddLine(BPoint(rect.left - 3, rect.bottom),
1718 					BPoint(rect.left - 2, rect.bottom), darken4);
1719 				view->AddLine(BPoint(rect.left - 1, rect.bottom + 1),
1720 					BPoint(rect.left - 1, rect.bottom + 1), darken4);
1721 			}
1722 			break;
1723 
1724 		default:
1725 		case BTabView::kTopSide:
1726 			// only draw if first tab is unselected
1727 			if (isFirst) {
1728 				// before going up
1729 				view->AddLine(BPoint(rect.left - 1, rect.bottom - 1),
1730 					BPoint(rect.left - 1, rect.bottom - 1), lightenmax);
1731 				view->AddLine(BPoint(rect.left, rect.bottom - 2),
1732 					BPoint(rect.left, rect.bottom - 3), lightenmax);;
1733 			}
1734 
1735 			// going up
1736 			view->AddLine(BPoint(rect.left + 1, rect.bottom - 4),
1737 				BPoint(rect.left + 1, rect.top + 5), lightenmax);
1738 
1739 			// before going right
1740 			view->AddLine(BPoint(rect.left + 2, rect.top + 4),
1741 				BPoint(rect.left + 2, rect.top + 2), lightenmax);
1742 			view->AddLine(BPoint(rect.left + 3, rect.top + 1),
1743 				BPoint(rect.left + 4, rect.top + 1), lightenmax);
1744 
1745 			// going right
1746 			view->AddLine(BPoint(rect.left + 5, rect.top),
1747 				BPoint(rect.right - 5, rect.top), lightenmax);
1748 
1749 			// after going right
1750 			view->AddLine(BPoint(rect.right - 4, rect.top + 1),
1751 				BPoint(rect.right - 3, rect.top + 1), lightenmax);
1752 			view->AddLine(BPoint(rect.right - 2, rect.top + 2),
1753 				BPoint(rect.right - 2, rect.top + 3), darken4);
1754 
1755 			// going down
1756 			view->AddLine(BPoint(rect.right - 1, rect.top + 4),
1757 				BPoint(rect.right - 1, rect.bottom - 4), darken4);
1758 
1759 			// only draw if not before selected tab
1760 			if (isFull) {
1761 				// after going down
1762 				view->AddLine(BPoint(rect.right, rect.bottom - 3),
1763 					BPoint(rect.right, rect.bottom - 2), darken4);
1764 				view->AddLine(BPoint(rect.right + 1, rect.bottom - 1),
1765 					BPoint(rect.right + 1, rect.bottom - 1), darken4);
1766 			}
1767 			break;
1768 
1769 		case BTabView::kBottomSide:
1770 			// only draw if first tab is unselected
1771 			if (isFirst) {
1772 				// before going down
1773 				view->AddLine(BPoint(rect.left - 1, rect.top - 1),
1774 					BPoint(rect.left - 1, rect.top - 1), lightenmax);
1775 				view->AddLine(BPoint(rect.left, rect.top - 2),
1776 					BPoint(rect.left, rect.top - 3), lightenmax);
1777 			}
1778 
1779 			// before going down
1780 			view->AddLine(BPoint(rect.left + 1, rect.top - 4),
1781 				BPoint(rect.left + 1, rect.bottom + 5), lightenmax);
1782 
1783 			// before going right
1784 			view->AddLine(BPoint(rect.left + 2, rect.bottom + 4),
1785 				BPoint(rect.left + 2, rect.bottom + 2), lightenmax);
1786 			view->AddLine(BPoint(rect.left + 3, rect.bottom + 1),
1787 				BPoint(rect.left + 4, rect.bottom + 1), lightenmax);
1788 
1789 			// going right
1790 			view->AddLine(BPoint(rect.left + 5, rect.bottom),
1791 				BPoint(rect.right - 5, rect.bottom), lightenmax);
1792 
1793 			// after going right
1794 			view->AddLine(BPoint(rect.right - 4, rect.bottom + 1),
1795 				BPoint(rect.right - 3, rect.bottom + 1), lightenmax);
1796 			view->AddLine(BPoint(rect.right - 2, rect.bottom + 2),
1797 				BPoint(rect.right - 2, rect.bottom + 3), darken4);
1798 
1799 			// going up
1800 			view->AddLine(BPoint(rect.right - 1, rect.bottom + 4),
1801 				BPoint(rect.right - 1, rect.top - 4), darken4);
1802 
1803 			// only draw if not before selected tab
1804 			if (isFull) {
1805 				// after going up
1806 				view->AddLine(BPoint(rect.right, rect.top - 3),
1807 					BPoint(rect.right, rect.top - 2), darken4);
1808 				view->AddLine(BPoint(rect.right + 1, rect.top - 1),
1809 					BPoint(rect.right + 1, rect.top - 1), darken4);
1810 			}
1811 			break;
1812 	}
1813 
1814 	view->EndLineArray();
1815 
1816 	// inset rect for view contents
1817 	rect.InsetBy(2, 2);
1818 
1819 	view->PopState();
1820 }
1821 
1822 
1823 void
1824 BeControlLook::DrawSplitter(BView* view, BRect& rect, const BRect& updateRect,
1825 	const rgb_color& base, orientation orientation, uint32 flags,
1826 	uint32 borders)
1827 {
1828 	if (!ShouldDraw(view, rect, updateRect))
1829 		return;
1830 
1831 	rgb_color background;
1832 	if ((flags & (B_CLICKED | B_ACTIVATED)) != 0)
1833 		background = tint_color(base, B_DARKEN_1_TINT);
1834 	else
1835 		background = base;
1836 
1837 	rgb_color light = tint_color(background, 0.6);
1838 	rgb_color shadow = tint_color(background, 1.21);
1839 
1840 	// frame
1841 	if (borders != 0 && rect.Width() > 3 && rect.Height() > 3)
1842 		DrawRaisedBorder(view, rect, updateRect, background, flags, borders);
1843 
1844 	// dots and rest of background
1845 	if (orientation == B_HORIZONTAL) {
1846 		if (rect.Width() > 2) {
1847 			// background on left/right
1848 			BRegion region(rect);
1849 			rect.left = floorf((rect.left + rect.right) / 2.0 - 0.5);
1850 			rect.right = rect.left + 1;
1851 			region.Exclude(rect);
1852 			view->SetHighColor(background);
1853 			view->FillRegion(&region);
1854 		}
1855 
1856 		BPoint dot = rect.LeftTop();
1857 		BPoint stop = rect.LeftBottom();
1858 		int32 num = 1;
1859 		while (dot.y <= stop.y) {
1860 			rgb_color col1;
1861 			rgb_color col2;
1862 			switch (num) {
1863 				case 1:
1864 					col1 = background;
1865 					col2 = background;
1866 					break;
1867 				case 2:
1868 					col1 = shadow;
1869 					col2 = background;
1870 					break;
1871 				case 3:
1872 				default:
1873 					col1 = background;
1874 					col2 = light;
1875 					num = 0;
1876 					break;
1877 			}
1878 			view->SetHighColor(col1);
1879 			view->StrokeLine(dot, dot, B_SOLID_HIGH);
1880 			view->SetHighColor(col2);
1881 			dot.x++;
1882 			view->StrokeLine(dot, dot, B_SOLID_HIGH);
1883 			dot.x -= 1.0;
1884 			// next pixel
1885 			num++;
1886 			dot.y++;
1887 		}
1888 	} else {
1889 		if (rect.Height() > 2) {
1890 			// background on left/right
1891 			BRegion region(rect);
1892 			rect.top = floorf((rect.top + rect.bottom) / 2.0 - 0.5);
1893 			rect.bottom = rect.top + 1;
1894 			region.Exclude(rect);
1895 			view->SetHighColor(background);
1896 			view->FillRegion(&region);
1897 		}
1898 
1899 		BPoint dot = rect.LeftTop();
1900 		BPoint stop = rect.RightTop();
1901 		int32 num = 1;
1902 		while (dot.x <= stop.x) {
1903 			rgb_color col1;
1904 			rgb_color col2;
1905 			switch (num) {
1906 				case 1:
1907 					col1 = background;
1908 					col2 = background;
1909 					break;
1910 				case 2:
1911 					col1 = shadow;
1912 					col2 = background;
1913 					break;
1914 				case 3:
1915 				default:
1916 					col1 = background;
1917 					col2 = light;
1918 					num = 0;
1919 					break;
1920 			}
1921 			view->SetHighColor(col1);
1922 			view->StrokeLine(dot, dot, B_SOLID_HIGH);
1923 			view->SetHighColor(col2);
1924 			dot.y++;
1925 			view->StrokeLine(dot, dot, B_SOLID_HIGH);
1926 			dot.y -= 1.0;
1927 			// next pixel
1928 			num++;
1929 			dot.x++;
1930 		}
1931 	}
1932 }
1933 
1934 
1935 //	#pragma mark - various borders
1936 
1937 
1938 void
1939 BeControlLook::DrawBorder(BView* view, BRect& rect, const BRect& updateRect,
1940 	const rgb_color& base, border_style borderStyle, uint32 flags,
1941 	uint32 borders)
1942 {
1943 	if (borderStyle == B_NO_BORDER)
1944 		return;
1945 
1946 	if (!ShouldDraw(view, rect, updateRect))
1947 		return;
1948 
1949 	view->PushState();
1950 
1951 	view->ClipToRect(rect);
1952 
1953 	rgb_color lightColor;
1954 	rgb_color shadowColor;
1955 	if (base.IsLight()) {
1956 		lightColor = tint_color(base, B_DARKEN_2_TINT);
1957 		shadowColor = tint_color(base, B_LIGHTEN_2_TINT);
1958 	} else {
1959 		lightColor = tint_color(base, B_LIGHTEN_MAX_TINT);
1960 		shadowColor = tint_color(base, B_DARKEN_3_TINT);
1961 	}
1962 
1963 	view->BeginLineArray(8);
1964 
1965 	if (borderStyle == B_FANCY_BORDER) {
1966 		if ((borders & B_LEFT_BORDER) != 0) {
1967 			view->AddLine(rect.LeftBottom(), rect.LeftTop(), shadowColor);
1968 			rect.left++;
1969 		}
1970 		if ((borders & B_TOP_BORDER) != 0) {
1971 			view->AddLine(rect.LeftTop(), rect.RightTop(), shadowColor);
1972 			rect.top++;
1973 		}
1974 		if ((borders & B_RIGHT_BORDER) != 0) {
1975 			view->AddLine(rect.RightTop(), rect.RightBottom(), shadowColor);
1976 			rect.right--;
1977 		}
1978 		if ((borders & B_BOTTOM_BORDER) != 0) {
1979 			view->AddLine(rect.RightBottom(), rect.LeftBottom(), shadowColor);
1980 			rect.bottom--;
1981 		}
1982 
1983 		if ((borders & B_LEFT_BORDER) != 0) {
1984 			view->AddLine(rect.LeftBottom(), rect.LeftTop(), lightColor);
1985 			rect.left++;
1986 		}
1987 		if ((borders & B_TOP_BORDER) != 0) {
1988 			view->AddLine(rect.LeftTop(), rect.RightTop(), lightColor);
1989 			rect.top++;
1990 		}
1991 		if ((borders & B_RIGHT_BORDER) != 0) {
1992 			view->AddLine(rect.RightTop(), rect.RightBottom(), lightColor);
1993 			rect.right--;
1994 		}
1995 		if ((borders & B_BOTTOM_BORDER) != 0) {
1996 			view->AddLine(rect.RightBottom(), rect.LeftBottom(), lightColor);
1997 			rect.bottom--;
1998 		}
1999 	} else if (borderStyle == B_PLAIN_BORDER) {
2000 		if ((borders & B_LEFT_BORDER) != 0) {
2001 			view->AddLine(rect.LeftBottom(), rect.LeftTop(), shadowColor);
2002 			rect.left++;
2003 		}
2004 		if ((borders & B_TOP_BORDER) != 0) {
2005 			view->AddLine(rect.LeftTop(), rect.RightTop(), shadowColor);
2006 			rect.top++;
2007 		}
2008 		if ((borders & B_RIGHT_BORDER) != 0) {
2009 			view->AddLine(rect.RightTop(), rect.RightBottom(), shadowColor);
2010 			rect.right--;
2011 		}
2012 		if ((borders & B_BOTTOM_BORDER) != 0) {
2013 			view->AddLine(rect.RightBottom(), rect.LeftBottom(), shadowColor);
2014 			rect.bottom--;
2015 		}
2016 
2017 		if ((borders & B_LEFT_BORDER) != 0) {
2018 			view->AddLine(rect.LeftBottom(), rect.LeftTop(), lightColor);
2019 			rect.left++;
2020 		}
2021 		if ((borders & B_TOP_BORDER) != 0) {
2022 			view->AddLine(rect.LeftTop(), rect.RightTop(), lightColor);
2023 			rect.top++;
2024 		}
2025 		if ((borders & B_RIGHT_BORDER) != 0) {
2026 			view->AddLine(rect.RightTop(), rect.RightBottom(), lightColor);
2027 			rect.right--;
2028 		}
2029 		if ((borders & B_BOTTOM_BORDER) != 0) {
2030 			view->AddLine(rect.RightBottom(), rect.LeftBottom(), lightColor);
2031 			rect.bottom--;
2032 		}
2033 	}
2034 
2035 	view->EndLineArray();
2036 
2037 	view->PopState();
2038 }
2039 
2040 
2041 void
2042 BeControlLook::DrawRaisedBorder(BView* view, BRect& rect,
2043 	const BRect& updateRect, const rgb_color& base, uint32 flags,
2044 	uint32 borders)
2045 {
2046 	if (!ShouldDraw(view, rect, updateRect))
2047 		return;
2048 
2049 	view->PushState();
2050 
2051 	view->ClipToRect(rect);
2052 
2053 	rgb_color lightColor;
2054 	rgb_color shadowColor;
2055 
2056 	if ((flags & B_DISABLED) != 0) {
2057 		lightColor = base;
2058 		shadowColor = base;
2059 	} else {
2060 		lightColor = tint_color(base, 0.85);
2061 		shadowColor = tint_color(base, 1.07);
2062 	}
2063 
2064 	view->BeginLineArray(8);
2065 
2066 	if ((borders & B_LEFT_BORDER) != 0) {
2067 		view->AddLine(rect.LeftBottom(), rect.LeftTop(), lightColor);
2068 		rect.left++;
2069 	}
2070 	if ((borders & B_TOP_BORDER) != 0) {
2071 		view->AddLine(rect.LeftTop(), rect.RightTop(), lightColor);
2072 		rect.top++;
2073 	}
2074 	if ((borders & B_RIGHT_BORDER) != 0) {
2075 		view->AddLine(rect.RightTop(), rect.RightBottom(), lightColor);
2076 		rect.right--;
2077 	}
2078 	if ((borders & B_BOTTOM_BORDER) != 0) {
2079 		view->AddLine(rect.RightBottom(), rect.LeftBottom(), lightColor);
2080 		rect.bottom--;
2081 	}
2082 
2083 	if ((borders & B_LEFT_BORDER) != 0) {
2084 		view->AddLine(rect.LeftBottom(), rect.LeftTop(), shadowColor);
2085 		rect.left++;
2086 	}
2087 	if ((borders & B_TOP_BORDER) != 0) {
2088 		view->AddLine(rect.LeftTop(), rect.RightTop(), shadowColor);
2089 		rect.top++;
2090 	}
2091 	if ((borders & B_RIGHT_BORDER) != 0) {
2092 		view->AddLine(rect.RightTop(), rect.RightBottom(), shadowColor);
2093 		rect.right--;
2094 	}
2095 	if ((borders & B_BOTTOM_BORDER) != 0) {
2096 		view->AddLine(rect.RightBottom(), rect.LeftBottom(), shadowColor);
2097 		rect.bottom--;
2098 	}
2099 
2100 	view->EndLineArray();
2101 
2102 	view->PopState();
2103 }
2104 
2105 
2106 void
2107 BeControlLook::DrawTextControlBorder(BView* view, BRect& rect,
2108 	const BRect& updateRect, const rgb_color& base, uint32 flags,
2109 	uint32 borders)
2110 {
2111 	if (!ShouldDraw(view, rect, updateRect))
2112 		return;
2113 
2114 	view->PushState();
2115 
2116 	view->ClipToRect(rect);
2117 
2118 	bool isEnabled = (flags & B_DISABLED) == 0;
2119 	bool isFocused = (flags & B_FOCUSED) != 0;
2120 
2121 	rgb_color dark;
2122 	rgb_color light;
2123 
2124 	// outer bevel
2125 
2126 	dark = tint_color(base, (isEnabled ? B_DARKEN_1_TINT : B_DARKEN_2_TINT));
2127 	light = tint_color(base, (isEnabled ? B_LIGHTEN_MAX_TINT : B_LIGHTEN_2_TINT));
2128 
2129 	_DrawFrame(view, rect, dark, dark, light, light);
2130 
2131 	// inner bevel
2132 
2133 	if (isEnabled && isFocused) {
2134 		view->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
2135 		view->StrokeRect(rect);
2136 		rect.InsetBy(1, 1);
2137 	} else {
2138 		dark = tint_color(base, (isEnabled ? B_DARKEN_4_TINT : B_LIGHTEN_2_TINT));
2139 		light = base;
2140 
2141 		_DrawFrame(view, rect, dark, dark, light, light);
2142 	}
2143 
2144 	view->PopState();
2145 }
2146 
2147 
2148 void
2149 BeControlLook::DrawGroupFrame(BView* view, BRect& rect, const BRect& updateRect,
2150 	const rgb_color& base, uint32 borders)
2151 {
2152 	DrawBorder(view, rect, updateRect, base, B_FANCY_BORDER, 0, borders);
2153 }
2154 
2155 
2156 //	#pragma mark - Labels
2157 
2158 
2159 void
2160 BeControlLook::DrawLabel(BView* view, const char* label, BRect rect,
2161 	const BRect& updateRect, const rgb_color& base, uint32 flags,
2162 	const rgb_color* textColor)
2163 {
2164 	DrawLabel(view, label, NULL, rect, updateRect, base, flags,
2165 		DefaultLabelAlignment(), textColor);
2166 }
2167 
2168 
2169 void
2170 BeControlLook::DrawLabel(BView* view, const char* label, BRect rect,
2171 	const BRect& updateRect, const rgb_color& base, uint32 flags,
2172 	const BAlignment& alignment, const rgb_color* textColor)
2173 {
2174 	DrawLabel(view, label, NULL, rect, updateRect, base, flags, alignment,
2175 		textColor);
2176 }
2177 
2178 
2179 void
2180 BeControlLook::DrawLabel(BView* view, const char* label, const rgb_color& base,
2181 	uint32 flags, const BPoint& where, const rgb_color* textColor)
2182 {
2183 	view->PushState();
2184 
2185 	bool isButton = (flags & B_FLAT) != 0 || (flags & B_HOVER) != 0
2186 		|| (flags & B_DEFAULT_BUTTON) != 0;
2187 	bool isEnabled = (flags & B_DISABLED) == 0;
2188 	bool isActivated = (flags & B_ACTIVATED) != 0;
2189 
2190 	BWindow* window = view->Window();
2191 	bool isDesktop = window != NULL
2192 		&& window->Feel() == kDesktopWindowFeel
2193 		&& window->Look() == kDesktopWindowLook
2194 		&& view->Parent()
2195 		&& view->Parent()->Parent() == NULL
2196 		&& (flags & B_IGNORE_OUTLINE) == 0;
2197 
2198 	rgb_color low;
2199 	rgb_color color;
2200 	rgb_color glowColor;
2201 
2202 	if (textColor != NULL)
2203 		glowColor = *textColor;
2204 	else if ((flags & B_IS_CONTROL) != 0)
2205 		glowColor = ui_color(B_CONTROL_TEXT_COLOR);
2206 	else
2207 		glowColor = ui_color(B_PANEL_TEXT_COLOR);
2208 
2209 	color = glowColor;
2210 
2211 	if (isDesktop)
2212 		low = view->Parent()->ViewColor();
2213 	else
2214 		low = base;
2215 
2216 	if (!isEnabled) {
2217 		color.red = (uint8)(((int32)low.red + color.red + 1) / 2);
2218 		color.green = (uint8)(((int32)low.green + color.green + 1) / 2);
2219 		color.blue = (uint8)(((int32)low.blue + color.blue + 1) / 2);
2220 	}
2221 
2222 	if (isDesktop) {
2223 		// enforce proper use of desktop label colors
2224 		if (low.IsDark()) {
2225 			if (textColor == NULL)
2226 				color = make_color(255, 255, 255);
2227 
2228 			glowColor = make_color(0, 0, 0);
2229 		} else {
2230 			if (textColor == NULL)
2231 				color = make_color(0, 0, 0);
2232 
2233 			glowColor = make_color(255, 255, 255);
2234 		}
2235 
2236 		// drawing occurs on the desktop
2237 		if (fCachedWorkspace != current_workspace()) {
2238 			int8 indice = 0;
2239 			int32 mask;
2240 			bool tmpOutline;
2241 			while (fBackgroundInfo.FindInt32("be:bgndimginfoworkspaces",
2242 					indice, &mask) == B_OK
2243 				&& fBackgroundInfo.FindBool("be:bgndimginfoerasetext",
2244 					indice, &tmpOutline) == B_OK) {
2245 
2246 				if (((1 << current_workspace()) & mask) != 0) {
2247 					fCachedOutline = tmpOutline;
2248 					fCachedWorkspace = current_workspace();
2249 					break;
2250 				}
2251 				indice++;
2252 			}
2253 		}
2254 
2255 		if (fCachedOutline) {
2256 			BFont font;
2257 			view->GetFont(&font);
2258 
2259 			view->SetDrawingMode(B_OP_ALPHA);
2260 			view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
2261 			// Draw glow or outline
2262 			if (glowColor.IsLight()) {
2263 				font.SetFalseBoldWidth(2.0);
2264 				view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
2265 
2266 				glowColor.alpha = 30;
2267 				view->SetHighColor(glowColor);
2268 				view->DrawString(label, where);
2269 
2270 				font.SetFalseBoldWidth(1.0);
2271 				view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
2272 
2273 				glowColor.alpha = 65;
2274 				view->SetHighColor(glowColor);
2275 				view->DrawString(label, where);
2276 
2277 				font.SetFalseBoldWidth(0.0);
2278 				view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
2279 			} else {
2280 				font.SetFalseBoldWidth(1.0);
2281 				view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
2282 
2283 				glowColor.alpha = 30;
2284 				view->SetHighColor(glowColor);
2285 				view->DrawString(label, where);
2286 
2287 				font.SetFalseBoldWidth(0.0);
2288 				view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
2289 
2290 				glowColor.alpha = 200;
2291 				view->SetHighColor(glowColor);
2292 				view->DrawString(label, BPoint(where.x + 1, where.y + 1));
2293 			}
2294 		}
2295 	}
2296 
2297 	rgb_color invertedIfClicked = color;
2298 	if (isButton && isEnabled && isActivated) {
2299 		// only for enabled and activated buttons
2300 		invertedIfClicked.red = 255 - invertedIfClicked.red;
2301 		invertedIfClicked.green = 255 - invertedIfClicked.green;
2302 		invertedIfClicked.blue = 255 - invertedIfClicked.blue;
2303 	}
2304 
2305 	view->SetLowColor(invertedIfClicked);
2306 	view->SetHighColor(invertedIfClicked);
2307 	view->SetDrawingMode(B_OP_OVER);
2308 	view->DrawString(label, where);
2309 	view->SetDrawingMode(B_OP_COPY);
2310 
2311 	view->PopState();
2312 }
2313 
2314 
2315 void
2316 BeControlLook::DrawLabel(BView* view, const char* label, const BBitmap* icon,
2317 	BRect rect, const BRect& updateRect, const rgb_color& base, uint32 flags,
2318 	const BAlignment& alignment, const rgb_color* textColor)
2319 {
2320 	if (!ShouldDraw(view, rect, updateRect))
2321 		return;
2322 
2323 	if (label == NULL && icon == NULL)
2324 		return;
2325 
2326 	if (label == NULL && icon != NULL) {
2327 		// icon only
2328 		BRect alignedRect = BLayoutUtils::AlignInFrame(
2329 			rect.OffsetByCopy(-2, -2),
2330 			icon->Bounds().Size(), alignment);
2331 		view->SetDrawingMode(B_OP_OVER);
2332 		view->DrawBitmap(icon, alignedRect.LeftTop());
2333 		view->SetDrawingMode(B_OP_COPY);
2334 		return;
2335 	}
2336 
2337 	view->PushState();
2338 
2339 	// label, possibly with icon
2340 	float availableWidth = rect.Width() + 1;
2341 	float width = 0;
2342 	float textOffset = 0;
2343 	float height = 0;
2344 
2345 	if (icon != NULL && label != NULL) {
2346 		// move text over to fit icon
2347 		width = icon->Bounds().Width() + DefaultLabelSpacing() + 1;
2348 		height = icon->Bounds().Height() + 1;
2349 		textOffset = width;
2350 		availableWidth -= textOffset;
2351 	}
2352 
2353 	// truncate the label if necessary and get the width and height
2354 	BString truncatedLabel(label);
2355 
2356 	BFont font;
2357 	view->GetFont(&font);
2358 
2359 	font.TruncateString(&truncatedLabel, B_TRUNCATE_MIDDLE, availableWidth);
2360 	width += ceilf(font.StringWidth(truncatedLabel.String()));
2361 
2362 	font_height fontHeight;
2363 	font.GetHeight(&fontHeight);
2364 	float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
2365 	height = std::max(height, textHeight);
2366 
2367 	// handle alignment
2368 	BRect alignedRect(BLayoutUtils::AlignOnRect(rect,
2369 		BSize(width - 1, height - 1), alignment));
2370 
2371 	if (icon != NULL) {
2372 		BPoint location(alignedRect.LeftTop());
2373 		if (icon->Bounds().Height() + 1 < height)
2374 			location.y += ceilf((height - icon->Bounds().Height() - 1) / 2);
2375 
2376 		view->SetDrawingMode(B_OP_OVER);
2377 		view->DrawBitmap(icon, location);
2378 		view->SetDrawingMode(B_OP_COPY);
2379 	}
2380 
2381 	BPoint location(alignedRect.left + textOffset,
2382 		alignedRect.top + ceilf(fontHeight.ascent));
2383 	if (textHeight < height)
2384 		location.y += ceilf((height - textHeight) / 2);
2385 
2386 	if ((flags & B_FOCUSED) != 0) {
2387 		// draw underline under label
2388 		float x = location.x;
2389 		float y = location.y + ceilf(fontHeight.descent);
2390 		view->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
2391 		view->StrokeLine(BPoint(x, y),
2392 			BPoint(x + view->StringWidth(truncatedLabel.String()), y));
2393 	}
2394 
2395 	DrawLabel(view, truncatedLabel.String(), base, flags, location, textColor);
2396 
2397 	view->PopState();
2398 }
2399 
2400 
2401 void
2402 BeControlLook::GetFrameInsets(frame_type frameType, uint32 flags, float& _left,
2403 	float& _top, float& _right, float& _bottom)
2404 {
2405 	// All frames have the same inset on each side.
2406 	float inset = 0;
2407 
2408 	switch (frameType) {
2409 		case B_BUTTON_FRAME:
2410 			inset = (flags & B_DEFAULT_BUTTON) != 0 ? 5 : 2;
2411 			break;
2412 
2413 		case B_GROUP_FRAME:
2414 		case B_MENU_FIELD_FRAME:
2415 			inset = 3;
2416 			break;
2417 
2418 		case B_SCROLL_VIEW_FRAME:
2419 		case B_TEXT_CONTROL_FRAME:
2420 			inset = 2;
2421 			break;
2422 	}
2423 
2424 	_left = inset;
2425 	_top = inset;
2426 	_right = inset;
2427 	_bottom = inset;
2428 }
2429 
2430 
2431 void
2432 BeControlLook::GetBackgroundInsets(background_type backgroundType,
2433 	uint32 flags, float& _left, float& _top, float& _right, float& _bottom)
2434 {
2435 	// Most backgrounds have the same inset on each side.
2436 	float inset = 0;
2437 
2438 	switch (backgroundType) {
2439 		case B_BUTTON_BACKGROUND:
2440 		case B_MENU_BACKGROUND:
2441 		case B_MENU_BAR_BACKGROUND:
2442 		case B_MENU_FIELD_BACKGROUND:
2443 		case B_MENU_ITEM_BACKGROUND:
2444 			inset = 1;
2445 			break;
2446 		case B_BUTTON_WITH_POP_UP_BACKGROUND:
2447 			_left = 1;
2448 			_top = 1;
2449 			_right = 1 + kButtonPopUpIndicatorWidth;
2450 			_bottom = 1;
2451 			return;
2452 		case B_HORIZONTAL_SCROLL_BAR_BACKGROUND:
2453 			_left = 2;
2454 			_top = 0;
2455 			_right = 1;
2456 			_bottom = 0;
2457 			return;
2458 		case B_VERTICAL_SCROLL_BAR_BACKGROUND:
2459 			_left = 0;
2460 			_top = 2;
2461 			_right = 0;
2462 			_bottom = 1;
2463 			return;
2464 	}
2465 
2466 	_left = inset;
2467 	_top = inset;
2468 	_right = inset;
2469 	_bottom = inset;
2470 }
2471 
2472 
2473 void
2474 BeControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect,
2475 	const BRect& updateRect, const rgb_color& base, uint32 flags,
2476 	uint32 borders, orientation orientation)
2477 {
2478 	_DrawButtonBackground(view, rect, updateRect, 0.0f, 0.0f, 0.0f, 0.0f,
2479 		base, true, flags, borders, orientation);
2480 }
2481 
2482 
2483 void
2484 BeControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect,
2485 	const BRect& updateRect, float radius, const rgb_color& base, uint32 flags,
2486 	uint32 borders, orientation orientation)
2487 {
2488 	_DrawButtonBackground(view, rect, updateRect, radius, radius, radius,
2489 		radius, base, true, flags, borders, orientation);
2490 }
2491 
2492 
2493 void
2494 BeControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect,
2495 	const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2496 	float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2497 	uint32 flags, uint32 borders, orientation orientation)
2498 {
2499 	_DrawButtonBackground(view, rect, updateRect, leftTopRadius,
2500 		rightTopRadius, leftBottomRadius, rightBottomRadius, base, true, flags,
2501 		borders, orientation);
2502 }
2503 
2504 
2505 //	#pragma mark - protected methods
2506 
2507 
2508 void
2509 BeControlLook::_DrawButtonFrame(BView* view, BRect& rect,
2510 	const BRect& updateRect, float, float, float, float, const rgb_color& base,
2511 	const rgb_color& background, float contrast, float brightness,
2512 	uint32 flags, uint32 borders)
2513 {
2514 	if (!ShouldDraw(view, rect, updateRect))
2515 		return;
2516 
2517 	view->PushState();
2518 
2519 	view->ClipToRect(rect);
2520 
2521 	// flags
2522 	bool isEnabled = (flags & B_DISABLED) == 0;
2523 	bool isDefault = (flags & B_DEFAULT_BUTTON) != 0;
2524 
2525 	// colors
2526 	rgb_color lighten1 = tint_color(base, B_LIGHTEN_1_TINT); // 231
2527 	lighten1.red++; lighten1.green++; lighten1.blue++; // 232 = 231 + 1
2528 	rgb_color lighten2 = tint_color(base, B_LIGHTEN_2_TINT);
2529 	rgb_color lightenMax = tint_color(base, B_LIGHTEN_MAX_TINT);
2530 	rgb_color darken1 = tint_color(base, B_DARKEN_1_TINT); // 184
2531 	rgb_color darken2 = tint_color(base, B_DARKEN_2_TINT); // 158
2532 	rgb_color darken3 = tint_color(base, B_DARKEN_3_TINT);
2533 	rgb_color darken4 = tint_color(base, B_DARKEN_4_TINT); // 96
2534 
2535 	rgb_color buttonBgColor = lighten1;
2536 	rgb_color lightColor;
2537 
2538 	rgb_color dark1BorderColor;
2539 	rgb_color dark2BorderColor;
2540 
2541 	rgb_color bevelColor1;
2542 	rgb_color bevelColor2;
2543 	rgb_color bevelColorRBCorner;
2544 
2545 	rgb_color borderBevelShadow;
2546 	rgb_color borderBevelLight;
2547 
2548 	if (isEnabled) {
2549 		lightColor = tint_color(base, B_LIGHTEN_2_TINT);
2550 		dark1BorderColor = darken3;
2551 		dark2BorderColor = darken4;
2552 		bevelColor1 = darken2;
2553 		bevelColor2 = lighten1;
2554 
2555 		if (isDefault) {
2556 			borderBevelShadow = tint_color(dark1BorderColor,
2557 				(B_NO_TINT + B_DARKEN_1_TINT) / 2);
2558 			borderBevelLight = tint_color(dark1BorderColor, B_LIGHTEN_1_TINT);
2559 
2560 			borderBevelLight.red = (borderBevelLight.red + base.red) / 2;
2561 			borderBevelLight.green = (borderBevelLight.green + base.green) / 2;
2562 			borderBevelLight.blue = (borderBevelLight.blue + base.blue) / 2;
2563 
2564 			dark1BorderColor = darken3;
2565 			dark2BorderColor = darken4;
2566 
2567 			bevelColorRBCorner = borderBevelShadow;
2568 		} else {
2569 			borderBevelShadow = tint_color(base,
2570 				(B_NO_TINT + B_DARKEN_1_TINT) / 2);
2571 			borderBevelLight = buttonBgColor;
2572 			bevelColorRBCorner = dark1BorderColor;
2573 		}
2574 	} else {
2575 		lightColor = lighten2;
2576 		dark1BorderColor = darken1;
2577 		dark2BorderColor = darken2;
2578 		bevelColor1 = base;
2579 		bevelColor2 = buttonBgColor;
2580 
2581 		if (isDefault) {
2582 			borderBevelShadow = dark1BorderColor;
2583 			borderBevelLight = base;
2584 			dark1BorderColor = tint_color(dark1BorderColor, B_DARKEN_1_TINT);
2585 			dark2BorderColor = tint_color(dark1BorderColor, 1.16);
2586 		} else {
2587 			borderBevelShadow = base;
2588 			borderBevelLight = base;
2589 		}
2590 
2591 		bevelColorRBCorner = tint_color(base, 1.08);
2592 	}
2593 
2594 	if (isDefault) {
2595 		if (isEnabled) {
2596 			// dark border
2597 			view->BeginLineArray(4);
2598 			if ((borders & B_LEFT_BORDER) != 0) {
2599 				view->AddLine(BPoint(rect.left, rect.top + 1),
2600 					BPoint(rect.left, rect.bottom - 1), dark2BorderColor);
2601 				rect.left++;
2602 			}
2603 			if ((borders & B_TOP_BORDER) != 0) {
2604 				view->AddLine(BPoint(rect.left, rect.top),
2605 					BPoint(rect.right - 1, rect.top), dark2BorderColor);
2606 				rect.top++;
2607 			}
2608 			if ((borders & B_RIGHT_BORDER) != 0) {
2609 				view->AddLine(BPoint(rect.right, rect.top),
2610 					BPoint(rect.right, rect.bottom - 1), dark2BorderColor);
2611 				rect.right--;
2612 			}
2613 			if ((borders & B_BOTTOM_BORDER) != 0) {
2614 				view->AddLine(BPoint(rect.left, rect.bottom),
2615 					BPoint(rect.right, rect.bottom), dark2BorderColor);
2616 				rect.bottom--;
2617 			}
2618 			view->EndLineArray();
2619 
2620 			// bevel
2621 			view->SetHighColor(darken1);
2622 			view->StrokeRect(rect);
2623 
2624 			rect.InsetBy(1, 1);
2625 
2626 			// fill
2627 			view->SetHighColor(lighten1);
2628 			view->FillRect(rect);
2629 
2630 			rect.InsetBy(2, 2);
2631 		} else {
2632 			// dark border
2633 			view->BeginLineArray(4);
2634 			if ((borders & B_LEFT_BORDER) != 0) {
2635 				view->AddLine(BPoint(rect.left, rect.top + 1),
2636 					BPoint(rect.left, rect.bottom - 1), darken1);
2637 				rect.left++;
2638 			}
2639 			if ((borders & B_TOP_BORDER) != 0) {
2640 				view->AddLine(BPoint(rect.left, rect.top),
2641 					BPoint(rect.right - 1, rect.top), darken1);
2642 				rect.top++;
2643 			}
2644 			if ((borders & B_RIGHT_BORDER) != 0) {
2645 				view->AddLine(BPoint(rect.right, rect.top),
2646 					BPoint(rect.right, rect.bottom - 1), darken1);
2647 				rect.right--;
2648 			}
2649 			if ((borders & B_BOTTOM_BORDER) != 0) {
2650 				view->AddLine(BPoint(rect.left, rect.bottom),
2651 					BPoint(rect.right, rect.bottom), darken1);
2652 				rect.bottom--;
2653 			}
2654 			view->EndLineArray();
2655 
2656 			// fill
2657 			view->SetHighColor(lighten1);
2658 			view->FillRect(rect);
2659 
2660 			rect.InsetBy(3, 3);
2661 		}
2662 	} else {
2663 		// if not default button, inset top and bottom by 1px
2664 		rect.InsetBy(1, 0);
2665 	}
2666 
2667 	// stroke frame to draw four corners, then write on top
2668 	view->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
2669 	view->StrokeRect(rect);
2670 
2671 	view->BeginLineArray(16);
2672 
2673 	// external border
2674 	view->AddLine(BPoint(rect.left, rect.top + 1),
2675 		BPoint(rect.left, rect.bottom - 1),
2676 		(borders & B_LEFT_BORDER) != 0 ? dark2BorderColor : darken1);
2677 	view->AddLine(BPoint(rect.left + 1, rect.top),
2678 		BPoint(rect.right - 1, rect.top),
2679 		(borders & B_TOP_BORDER) != 0 ? dark2BorderColor : darken1);
2680 	view->AddLine(BPoint(rect.right, rect.top + 1),
2681 		BPoint(rect.right, rect.bottom - 1),
2682 		(borders & B_RIGHT_BORDER) != 0 ? dark2BorderColor : darken1);
2683 	view->AddLine(BPoint(rect.left + 1, rect.bottom),
2684 		BPoint(rect.right - 1, rect.bottom),
2685 		(borders & B_BOTTOM_BORDER) != 0 ? dark2BorderColor : darken1);
2686 
2687 	// inset past external border
2688 	rect.InsetBy(1, 1);
2689 
2690 	// internal bevel
2691 	view->AddLine(rect.LeftBottom(), rect.LeftTop(), bevelColor2);
2692 	view->AddLine(rect.LeftTop(), rect.RightTop(), bevelColor2);
2693 	view->AddLine(BPoint(rect.right, rect.top + 1), rect.RightBottom(),
2694 		bevelColor1);
2695 	view->AddLine(rect.RightBottom(), BPoint(rect.left + 1, rect.bottom),
2696 		bevelColor1);
2697 
2698 	// inset past internal bevel
2699 	rect.InsetBy(1, 1);
2700 
2701 	// internal gloss outside
2702 	view->AddLine(BPoint(rect.left, rect.bottom + 1), rect.LeftTop(),
2703 		lightenMax); // come down an extra pixel
2704 	view->AddLine(rect.LeftTop(), rect.RightTop(), lightenMax);
2705 	view->AddLine(rect.RightTop(), rect.RightBottom(), base);
2706 	view->AddLine(rect.RightBottom(), BPoint(rect.left + 1, rect.bottom),
2707 		base); // compensate for extra pixel
2708 
2709 	// inset past gloss outside
2710 	rect.InsetBy(1, 1);
2711 
2712 	// internal gloss inside
2713 	view->AddLine(BPoint(rect.left, rect.bottom + 1), rect.LeftTop(),
2714 		lightenMax); // come down an extra pixel
2715 	view->AddLine(rect.LeftTop(), rect.RightTop(), lightenMax);
2716 	view->AddLine(rect.RightTop(), rect.RightBottom(), buttonBgColor);
2717 	view->AddLine(rect.RightBottom(), BPoint(rect.left + 1, rect.bottom),
2718 		buttonBgColor); // compensate for extra pixel
2719 
2720 	// inset past gloss inside
2721 	rect.InsetBy(1, 1);
2722 
2723 	view->EndLineArray();
2724 
2725 	view->PopState();
2726 }
2727 
2728 
2729 void
2730 BeControlLook::_DrawButtonBackground(BView* view, BRect& rect,
2731 	const BRect& updateRect, float, float, float, float, const rgb_color& base,
2732 	bool popupIndicator, uint32 flags, uint32 borders, orientation orientation)
2733 {
2734 	if (!ShouldDraw(view, rect, updateRect))
2735 		return;
2736 
2737 	// fill the button area
2738 	view->SetHighColor(tint_color(base, B_LIGHTEN_1_TINT));
2739 	view->FillRect(rect);
2740 
2741 	bool isEnabled = (flags & B_DISABLED) == 0;
2742 	bool isActivated = (flags & B_ACTIVATED) != 0;
2743 
2744 	if (isEnabled && isActivated) {
2745 		// invert if clicked without altering rect
2746 		BRect invertRect(rect.InsetByCopy(-3, -3));
2747 		view->SetDrawingMode(B_OP_INVERT);
2748 		view->FillRect(invertRect);
2749 	}
2750 }
2751 
2752 
2753 void
2754 BeControlLook::_DrawPopUpMarker(BView* view, const BRect& rect,
2755 	const rgb_color& base, uint32 flags)
2756 {
2757 	bool isEnabled = (flags & B_DISABLED) == 0;
2758 
2759 	BPoint position(rect.right - 8, rect.bottom - 8);
2760 	BPoint triangle[3];
2761 	triangle[0] = position + BPoint(-2.5, -0.5);
2762 	triangle[1] = position + BPoint(2.5, -0.5);
2763 	triangle[2] = position + BPoint(0.0, 2.0);
2764 
2765 	uint32 viewFlags = view->Flags();
2766 	view->SetFlags(viewFlags | B_SUBPIXEL_PRECISE);
2767 
2768 	rgb_color markerColor = isEnabled
2769 		? tint_color(base, B_DARKEN_4_TINT)
2770 		: tint_color(base, B_DARKEN_2_TINT);
2771 
2772 	view->SetHighColor(markerColor);
2773 	view->FillTriangle(triangle[0], triangle[1], triangle[2]);
2774 
2775 	view->SetFlags(viewFlags);
2776 }
2777 
2778 
2779 void
2780 BeControlLook::_DrawMenuFieldBackgroundOutside(BView* view, BRect& rect,
2781 	const BRect& updateRect, float, float, float, float, const rgb_color& base,
2782 	bool popupIndicator, uint32 flags)
2783 {
2784 	if (!ShouldDraw(view, rect, updateRect))
2785 		return;
2786 
2787 	// BeControlLook does not support rounded corners and it never will
2788 	if (popupIndicator) {
2789 		BRect rightRect(rect);
2790 		rightRect.left = rect.right - 10;
2791 
2792 		_DrawMenuFieldBackgroundInside(view, rect, updateRect,
2793 			0, 0, 0, 0, base, flags, B_ALL_BORDERS);
2794 		_DrawPopUpMarker(view, rightRect, base, flags);
2795 	} else {
2796 		_DrawMenuFieldBackgroundInside(view, rect, updateRect, 0, 0,
2797 			0, 0, base, flags);
2798 	}
2799 }
2800 
2801 
2802 void
2803 BeControlLook::_DrawMenuFieldBackgroundInside(BView* view, BRect& rect,
2804 	const BRect& updateRect, float, float, float, float, const rgb_color& base,
2805 	uint32 flags, uint32 borders)
2806 {
2807 	if (!ShouldDraw(view, rect, updateRect))
2808 		return;
2809 
2810 	view->PushState();
2811 
2812 	view->ClipToRect(rect);
2813 
2814 	// flags
2815 	bool isEnabled = (flags & B_DISABLED) == 0;
2816 
2817 	// colors
2818 	rgb_color darken4;
2819 	rgb_color darken1;
2820 	rgb_color lighten1;
2821 	rgb_color lighten2;
2822 
2823 	if (isEnabled) {
2824 		darken4 = tint_color(base, B_DARKEN_4_TINT);
2825 		darken1 = tint_color(base, B_DARKEN_1_TINT);
2826 		lighten1 = tint_color(base, B_LIGHTEN_1_TINT);
2827 		lighten2 = tint_color(base, B_LIGHTEN_2_TINT);
2828 	} else {
2829 		darken4 = tint_color(base, B_DARKEN_2_TINT);
2830 		darken1 = tint_color(base, (B_NO_TINT + B_DARKEN_1_TINT) / 2.0);
2831 		lighten1 = tint_color(base, (B_NO_TINT + B_LIGHTEN_1_TINT) / 2.0);
2832 		lighten2 = tint_color(base, B_LIGHTEN_1_TINT);
2833 	}
2834 
2835 	// fill background
2836 	view->SetHighColor(base);
2837 	view->FillRect(rect);
2838 
2839 	// draw shadow lines around bottom and right sides
2840 	view->BeginLineArray(6);
2841 
2842 	// bottom below item text, darker then BMenuBar
2843 	// would normaly draw it
2844 	view->AddLine(BPoint(rect.left, rect.bottom),
2845 		BPoint(rect.left - 1, rect.bottom), darken4);
2846 
2847 	// bottom below popup marker
2848 	view->AddLine(BPoint(rect.left, rect.bottom),
2849 		BPoint(rect.right, rect.bottom), darken4);
2850 	// right of popup marker
2851 	view->AddLine(BPoint(rect.right, rect.bottom - 1),
2852 		BPoint(rect.right, rect.top), darken4);
2853 	// top above popup marker
2854 	view->AddLine(BPoint(rect.left, rect.top),
2855 		BPoint(rect.right - 2, rect.top), lighten2);
2856 
2857 	rect.top += 1;
2858 	rect.bottom -= 1;
2859 	rect.right -= 1;
2860 
2861 	// bottom below popup marker
2862 	view->AddLine(BPoint(rect.left, rect.bottom),
2863 		BPoint(rect.right, rect.bottom), darken1);
2864 	// right of popup marker
2865 	view->AddLine(BPoint(rect.right, rect.bottom - 1),
2866 		BPoint(rect.right, rect.top), darken1);
2867 
2868 	view->EndLineArray();
2869 
2870 	rect.bottom -= 1;
2871 	rect.right -= 1;
2872 	view->SetHighColor(base);
2873 	view->FillRect(rect);
2874 
2875 	view->PopState();
2876 }
2877 
2878 
2879 void
2880 BeControlLook::_DrawScrollBarBackgroundFirst(BView* view, BRect& rect,
2881 	const BRect& updateRect, const rgb_color& base, uint32 flags,
2882 	orientation orientation)
2883 {
2884 	if (!ShouldDraw(view, rect, updateRect))
2885 		return;
2886 
2887 	view->PushState();
2888 
2889 	view->ClipToRect(rect);
2890 
2891 	bool isEnabled = (flags & B_DISABLED) == 0;
2892 	BRect orig(rect);
2893 
2894 	// border = 152
2895 	rgb_color border = tint_color(base, B_DARKEN_2_TINT);
2896 	rgb_color shine, shadow, bg;
2897 	if (isEnabled) {
2898 		// shine = 216, shadow = 184, bg = 200
2899 		shine = base;
2900 		shadow = tint_color(base, B_DARKEN_1_TINT);
2901 		bg = tint_color(base, 1.074);
2902 	} else {
2903 		// shine = 255, shadow = bg = 240
2904 		shine = tint_color(base, B_LIGHTEN_MAX_TINT);
2905 		rgb_color lighten2 = tint_color(base, B_LIGHTEN_2_TINT);
2906 		lighten2.red++; lighten2.green++; lighten2.blue++;
2907 			// lighten2 = 239, 240 = 239 + 1
2908 		shadow = bg = lighten2;
2909 	}
2910 
2911 	// fill background, we'll draw arrows and thumb on top
2912 	view->SetDrawingMode(B_OP_COPY);
2913 
2914 	view->BeginLineArray(5);
2915 	if (orientation == B_VERTICAL) {
2916 		// left shadow
2917 		view->AddLine(rect.LeftTop(), rect.LeftBottom(),
2918 			isEnabled ? shadow : shine);
2919 		rect.left++;
2920 		view->AddLine(rect.LeftTop(), rect.LeftBottom(), shadow);
2921 		rect.left++;
2922 		// top shadow
2923 		view->AddLine(rect.LeftTop(), rect.RightTop(),
2924 			isEnabled ? shadow : shine);
2925 		rect.top++;
2926 		view->AddLine(rect.LeftTop(), rect.RightTop(), shadow);
2927 		rect.top++;
2928 		// shine
2929 		view->AddLine(rect.RightTop(), rect.RightBottom(), base);
2930 		rect.right--;
2931 	} else {
2932 		// left shadow
2933 		view->AddLine(rect.LeftTop(), rect.LeftBottom(), shadow);
2934 		rect.left++;
2935 		view->AddLine(rect.LeftTop(), rect.LeftBottom(), shadow);
2936 		rect.left++;
2937 		// top shadow
2938 		view->AddLine(rect.LeftTop(), rect.RightTop(), shadow);
2939 		rect.top++;
2940 		view->AddLine(rect.LeftTop(), rect.RightTop(), shadow);
2941 		rect.top++;
2942 		// shine
2943 		view->AddLine(rect.LeftBottom(), rect.RightBottom(), base);
2944 		rect.bottom--;
2945 	}
2946 	view->EndLineArray();
2947 
2948 	// fill bg
2949 	view->SetHighColor(bg);
2950 	view->FillRect(rect);
2951 
2952 	rect = orig;
2953 
2954 	// draw border last
2955 	view->BeginLineArray(2);
2956 	if (orientation == B_VERTICAL) {
2957 		// top border
2958 		view->AddLine(rect.LeftTop(), rect.RightTop(), border);
2959 		// bottom border
2960 		view->AddLine(rect.LeftBottom(), rect.RightBottom(), border);
2961 	} else {
2962 		// left border
2963 		view->AddLine(rect.LeftTop(), rect.LeftBottom(), border);
2964 		// right border
2965 		view->AddLine(rect.RightTop(), rect.RightBottom(), border);
2966 	}
2967 	view->EndLineArray();
2968 
2969 	view->PopState();
2970 }
2971 
2972 
2973 void
2974 BeControlLook::_DrawScrollBarBackgroundSecond(BView* view, BRect& rect,
2975 	const BRect& updateRect, const rgb_color& base, uint32 flags,
2976 	orientation orientation)
2977 {
2978 	if (!ShouldDraw(view, rect, updateRect))
2979 		return;
2980 
2981 	view->PushState();
2982 
2983 	view->ClipToRect(rect);
2984 
2985 	bool isEnabled = (flags & B_DISABLED) == 0;
2986 
2987 	BRect orig(rect);
2988 
2989 	// border = 152
2990 	rgb_color border = tint_color(base, B_DARKEN_2_TINT);
2991 	rgb_color darkBorder, shine, shadow, bg;
2992 	if (isEnabled) {
2993 		// darkBorder = 96 shine = 216, shadow = 184, bg = 200
2994 		darkBorder = tint_color(base, B_DARKEN_4_TINT);
2995 		shine = base;
2996 		shadow = tint_color(base, B_DARKEN_1_TINT);
2997 		bg = tint_color(base, 1.074);
2998 	} else {
2999 		// darkBorder = 184, shine = 255, shadow = bg = 240
3000 		darkBorder = tint_color(base, B_DARKEN_1_TINT);
3001 		shine = tint_color(base, B_LIGHTEN_MAX_TINT);
3002 		rgb_color lighten2 = tint_color(base, B_LIGHTEN_2_TINT);
3003 		lighten2.red++; lighten2.green++; lighten2.blue++;
3004 			// lighten2 = 239, 240 = 239 + 1
3005 		shadow = bg = lighten2;
3006 	}
3007 
3008 	// fill background, we'll draw arrows and thumb on top
3009 	view->SetDrawingMode(B_OP_COPY);
3010 
3011 	view->BeginLineArray(3);
3012 	if (orientation == B_VERTICAL) {
3013 		// left shadow (no top shadow on second rect)
3014 		view->AddLine(rect.LeftTop(), rect.LeftBottom(),
3015 			isEnabled ? shadow : shine);
3016 		rect.left++;
3017 		view->AddLine(rect.LeftTop(), rect.LeftBottom(), shadow);
3018 		rect.left++;
3019 		// shine (use base color)
3020 		view->AddLine(rect.RightTop(), rect.RightBottom(), base);
3021 		rect.right--;
3022 	} else {
3023 		// left shadow (no top shadow on second rect)
3024 		view->AddLine(rect.LeftTop(), rect.RightTop(),
3025 			isEnabled ? shadow : shine);
3026 		rect.top++;
3027 		view->AddLine(rect.LeftTop(), rect.RightTop(), shadow);
3028 		rect.top++;
3029 		// shine (use base color)
3030 		view->AddLine(rect.LeftBottom(), rect.RightBottom(), base);
3031 		rect.bottom--;
3032 	}
3033 	view->EndLineArray();
3034 
3035 	// fill bg
3036 	view->SetHighColor(bg);
3037 	view->FillRect(rect);
3038 
3039 	rect = orig;
3040 
3041 	// draw border over bg
3042 	view->BeginLineArray(2);
3043 	if (orientation == B_VERTICAL) {
3044 		// top border
3045 		view->AddLine(rect.LeftTop(), rect.RightTop(), darkBorder);
3046 		// bottom border
3047 		view->AddLine(rect.LeftBottom(), rect.RightBottom(), border);
3048 	} else {
3049 		// left border
3050 		view->AddLine(rect.LeftTop(), rect.LeftBottom(), darkBorder);
3051 		// right border
3052 		view->AddLine(rect.RightTop(), rect.RightBottom(), border);
3053 	}
3054 	view->EndLineArray();
3055 
3056 	view->PopState();
3057 }
3058 
3059 void
3060 BeControlLook::_DrawScrollBarKnobDot(BView* view,
3061 	float hcenter, float vmiddle, rgb_color dark, rgb_color light,
3062 	orientation orientation)
3063 {
3064 	// orientation is unused
3065 	view->BeginLineArray(4);
3066 	view->AddLine(BPoint(hcenter + 2, vmiddle - 2),
3067 		BPoint(hcenter + 2, vmiddle + 2), dark);
3068 	view->AddLine(BPoint(hcenter + 2, vmiddle + 2),
3069 		BPoint(hcenter - 2, vmiddle + 2), dark);
3070 	view->AddLine(BPoint(hcenter - 2, vmiddle + 1),
3071 		BPoint(hcenter - 2, vmiddle - 1), light);
3072 	view->AddLine(BPoint(hcenter - 2, vmiddle - 1),
3073 		BPoint(hcenter - 2, vmiddle + 1), light);
3074 	view->EndLineArray();
3075 }
3076 
3077 
3078 void
3079 BeControlLook::_DrawScrollBarKnobLine(BView* view,
3080 	float hcenter, float vmiddle, rgb_color dark, rgb_color light,
3081 	orientation orientation)
3082 {
3083 	if (orientation == B_HORIZONTAL) {
3084 		view->BeginLineArray(4);
3085 		view->AddLine(BPoint(hcenter, vmiddle + 3),
3086 			BPoint(hcenter + 1, vmiddle + 3), dark);
3087 		view->AddLine(BPoint(hcenter + 1, vmiddle + 3),
3088 			BPoint(hcenter + 1, vmiddle - 3), dark);
3089 		view->AddLine(BPoint(hcenter, vmiddle - 3),
3090 			BPoint(hcenter - 1, vmiddle - 3), light);
3091 		view->AddLine(BPoint(hcenter - 1, vmiddle - 3),
3092 			BPoint(hcenter - 1, vmiddle + 3), light);
3093 		view->EndLineArray();
3094 	} else {
3095 		view->BeginLineArray(4);
3096 		view->AddLine(BPoint(hcenter + 3, vmiddle),
3097 			BPoint(hcenter + 3, vmiddle + 1), dark);
3098 		view->AddLine(BPoint(hcenter + 3, vmiddle + 1),
3099 			BPoint(hcenter - 3, vmiddle + 1), dark);
3100 		view->AddLine(BPoint(hcenter - 3, vmiddle),
3101 			BPoint(hcenter - 3, vmiddle - 1), light);
3102 		view->AddLine(BPoint(hcenter - 3, vmiddle - 1),
3103 			BPoint(hcenter + 3, vmiddle - 1), light);
3104 		view->EndLineArray();
3105 	}
3106 }
3107 
3108 
3109 void
3110 BeControlLook::_DrawFrame(BView* view, BRect& rect, const rgb_color& left,
3111 	const rgb_color& top, const rgb_color& right, const rgb_color& bottom,
3112 	uint32 borders)
3113 {
3114 	view->BeginLineArray(4);
3115 
3116 	// draw in reverse so that bottom and right corners cover top and left
3117 
3118 	if ((borders & B_BOTTOM_BORDER) != 0) {
3119 		view->AddLine(
3120 			BPoint(rect.left, rect.bottom),
3121 			BPoint(rect.right, rect.bottom), bottom);
3122 		rect.bottom--;
3123 	}
3124 	if ((borders & B_RIGHT_BORDER) != 0) {
3125 		view->AddLine(
3126 			BPoint(rect.right, rect.top),
3127 			BPoint(rect.right, rect.bottom), right);
3128 		rect.right--;
3129 	}
3130 	if ((borders & B_TOP_BORDER) != 0) {
3131 		view->AddLine(
3132 			BPoint(rect.left, rect.top),
3133 			BPoint(rect.right, rect.top), top);
3134 		rect.top++;
3135 	}
3136 	if ((borders & B_LEFT_BORDER) != 0) {
3137 		view->AddLine(
3138 			BPoint(rect.left, rect.bottom),
3139 			BPoint(rect.left, rect.top), left);
3140 		rect.left++;
3141 	}
3142 
3143 	view->EndLineArray();
3144 }
3145 
3146 } // namespace BPrivate
3147 
3148 
3149 extern "C" BControlLook* (instantiate_control_look)(image_id id)
3150 {
3151 	return new (std::nothrow)BPrivate::BeControlLook(id);
3152 }
3153