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