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