1b5436616SAxel Dörfler/*
27f9368caSlooncraz * Copyright 2001-2015 Haiku, Inc.
3b5436616SAxel Dörfler * Distributed under the terms of the MIT License.
4b5436616SAxel Dörfler *
5b5436616SAxel Dörfler * Authors:
687c51182SJohn Scipione *		Stephan A��mus, superstippi@gmx.de
787c51182SJohn Scipione *		DarkWyrm, bpmagic@columbus.rr.com
887c51182SJohn Scipione *		Ryan Leavengood, leavengood@gmail.com
9003491a5SPhilippe Saint-Pierre *		Philippe Saint-Pierre, stpere@gmail.com
1087c51182SJohn Scipione *		John Scipione, jscipione@gmail.com
1187c51182SJohn Scipione *		Ingo Weinhold, ingo_weinhold@gmx.de
1287c51182SJohn Scipione *		Clemens Zeidler, haiku@clemens-zeidler.de
137f9368caSlooncraz *		Joseph Groover <looncraz@looncraz.net>
14b5436616SAxel Dörfler */
15b5436616SAxel Dörfler
16ba1d39e4SAxel Dörfler
17437b1927SAxel Dörfler/*!	Default and fallback decorator for the app_server - the yellow tabs */
18b5436616SAxel Dörfler
19e742e3e1SStephan Aßmus
2005bd1efeSAxel Dörfler#include "DefaultDecorator.h"
21e742e3e1SStephan Aßmus
2292fe8be9SIngo Weinhold#include <algorithm>
23bb2e9b06SClemens Zeidler#include <cmath>
24926e63c8SBrecht Machiels#include <new>
25926e63c8SBrecht Machiels#include <stdio.h>
26926e63c8SBrecht Machiels
27926e63c8SBrecht Machiels#include <Autolock.h>
28bb2e9b06SClemens Zeidler#include <Debug.h>
29926e63c8SBrecht Machiels#include <GradientLinear.h>
30926e63c8SBrecht Machiels#include <Rect.h>
315a32087bSJohn Scipione#include <Region.h>
32926e63c8SBrecht Machiels#include <View.h>
33926e63c8SBrecht Machiels
34926e63c8SBrecht Machiels#include <WindowPrivate.h>
35926e63c8SBrecht Machiels
36e13a79e0SMichael Lotz#include "BitmapDrawingEngine.h"
3705bd1efeSAxel Dörfler#include "DesktopSettings.h"
386ed89418SStephan Aßmus#include "DrawingEngine.h"
39aca4f50dSAxel Dörfler#include "DrawState.h"
40bdd34c02SAxel Dörfler#include "FontManager.h"
41a7e4fa4cSDarkWyrm#include "PatternHandler.h"
42e13a79e0SMichael Lotz#include "ServerBitmap.h"
4347b0fc0eSDarkWyrm
4467f4247fSAdi Oanca
457641924eSAdi Oanca//#define DEBUG_DECORATOR
4683742972SDarkWyrm#ifdef DEBUG_DECORATOR
473ecfa8e1SAdi Oanca#	define STRACE(x) printf x
483ecfa8e1SAdi Oanca#else
493ecfa8e1SAdi Oanca#	define STRACE(x) ;
5083742972SDarkWyrm#endif
5183742972SDarkWyrm
5205bd1efeSAxel Dörfler
53db4da598SRyan Leavengoodstatic const float kBorderResizeLength = 22.0;
54db4da598SRyan Leavengood
55a17770f4SRyan Leavengood
5649fe9677SAxel Dörflerstatic inline uint8
5749fe9677SAxel Dörflerblend_color_value(uint8 a, uint8 b, float position)
5849fe9677SAxel Dörfler{
59c16fda11SAxel Dörfler	int16 delta = (int16)b - a;
6049fe9677SAxel Dörfler	int32 value = a + (int32)(position * delta);
6149fe9677SAxel Dörfler	if (value > 255)
6249fe9677SAxel Dörfler		return 255;
6349fe9677SAxel Dörfler	if (value < 0)
6449fe9677SAxel Dörfler		return 0;
6549fe9677SAxel Dörfler
6649fe9677SAxel Dörfler	return (uint8)value;
6749fe9677SAxel Dörfler}
6849fe9677SAxel Dörfler
6949fe9677SAxel Dörfler
7049fe9677SAxel Dörfler//	#pragma mark -
7149fe9677SAxel Dörfler
7249fe9677SAxel Dörfler
7385f8bb71SAxel Dörfler// TODO: get rid of DesktopSettings here, and introduce private accessor
7485f8bb71SAxel Dörfler//	methods to the Decorator base class
757f9368caSlooncrazDefaultDecorator::DefaultDecorator(DesktopSettings& settings, BRect rect,
767f9368caSlooncraz	Desktop* desktop)
77e3ab8648SIngo Weinhold	:
787f9368caSlooncraz	TabDecorator(settings, rect, desktop)
79ae01fc9bSDarkWyrm{
807f6629a9SStephan Aßmus	// TODO: If the decorator was created with a frame too small, it should
817f6629a9SStephan Aßmus	// resize itself!
8208d9a6e3SAxel Dörfler
8337aec728SDarkWyrm	STRACE(("DefaultDecorator:\n"));
8408d9a6e3SAxel Dörfler	STRACE(("\tFrame (%.1f,%.1f,%.1f,%.1f)\n",
8508d9a6e3SAxel Dörfler		rect.left, rect.top, rect.right, rect.bottom));
86ae01fc9bSDarkWyrm}
87ae01fc9bSDarkWyrm
88614de12dSAxel Dörfler
89614de12dSAxel DörflerDefaultDecorator::~DefaultDecorator()
90ae01fc9bSDarkWyrm{
9137aec728SDarkWyrm	STRACE(("DefaultDecorator: ~DefaultDecorator()\n"));
9259345e26SStephan Aßmus}
9359345e26SStephan Aßmus
94614de12dSAxel Dörfler
95cfe0652aSJohn Scipione// #pragma mark - Public methods
9659345e26SStephan Aßmus
97e13a79e0SMichael Lotz
985a32087bSJohn Scipione/*!	Returns the frame colors for the specified decorator component.
995a32087bSJohn Scipione
1005a32087bSJohn Scipione	The meaning of the color array elements depends on the specified component.
1015a32087bSJohn Scipione	For some components some array elements are unused.
1025a32087bSJohn Scipione
1035a32087bSJohn Scipione	\param component The component for which to return the frame colors.
1045a32087bSJohn Scipione	\param highlight The highlight set for the component.
1055a32087bSJohn Scipione	\param colors An array of colors to be initialized by the function.
1065a32087bSJohn Scipione*/
1075a32087bSJohn Scipionevoid
1085a32087bSJohn ScipioneDefaultDecorator::GetComponentColors(Component component, uint8 highlight,
1095a32087bSJohn Scipione	ComponentColors _colors, Decorator::Tab* _tab)
1105a32087bSJohn Scipione{
111cfe0652aSJohn Scipione	Decorator::Tab* tab = static_cast<Decorator::Tab*>(_tab);
1125a32087bSJohn Scipione	switch (component) {
1135a32087bSJohn Scipione		case COMPONENT_TAB:
1145a32087bSJohn Scipione			if (tab && tab->buttonFocus) {
1155a32087bSJohn Scipione				_colors[COLOR_TAB_FRAME_LIGHT]
1167f9368caSlooncraz					= tint_color(fFocusFrameColor, B_DARKEN_2_TINT);
1175a32087bSJohn Scipione				_colors[COLOR_TAB_FRAME_DARK]
1187f9368caSlooncraz					= tint_color(fFocusFrameColor, B_DARKEN_3_TINT);
1197f9368caSlooncraz				_colors[COLOR_TAB] = fFocusTabColor;
1207f9368caSlooncraz				_colors[COLOR_TAB_LIGHT] = fFocusTabColorLight;
1217f9368caSlooncraz				_colors[COLOR_TAB_BEVEL] = fFocusTabColorBevel;
1227f9368caSlooncraz				_colors[COLOR_TAB_SHADOW] = fFocusTabColorShadow;
1237f9368caSlooncraz				_colors[COLOR_TAB_TEXT] = fFocusTextColor;
1245a32087bSJohn Scipione			} else {
1255a32087bSJohn Scipione				_colors[COLOR_TAB_FRAME_LIGHT]
1267f9368caSlooncraz					= tint_color(fNonFocusFrameColor, B_DARKEN_2_TINT);
1275a32087bSJohn Scipione				_colors[COLOR_TAB_FRAME_DARK]
1287f9368caSlooncraz					= tint_color(fNonFocusFrameColor, B_DARKEN_3_TINT);
1297f9368caSlooncraz				_colors[COLOR_TAB] = fNonFocusTabColor;
1307f9368caSlooncraz				_colors[COLOR_TAB_LIGHT] = fNonFocusTabColorLight;
1317f9368caSlooncraz				_colors[COLOR_TAB_BEVEL] = fNonFocusTabColorBevel;
1327f9368caSlooncraz				_colors[COLOR_TAB_SHADOW] = fNonFocusTabColorShadow;
1337f9368caSlooncraz				_colors[COLOR_TAB_TEXT] = fNonFocusTextColor;
1345a32087bSJohn Scipione			}
1355a32087bSJohn Scipione			break;
1365a32087bSJohn Scipione
1375a32087bSJohn Scipione		case COMPONENT_CLOSE_BUTTON:
1385a32087bSJohn Scipione		case COMPONENT_ZOOM_BUTTON:
1395a32087bSJohn Scipione			if (tab && tab->buttonFocus) {
1407f9368caSlooncraz				_colors[COLOR_BUTTON] = fFocusTabColor;
1417f9368caSlooncraz				_colors[COLOR_BUTTON_LIGHT] = fFocusTabColorLight;
1425a32087bSJohn Scipione			} else {
1437f9368caSlooncraz				_colors[COLOR_BUTTON] = fNonFocusTabColor;
1447f9368caSlooncraz				_colors[COLOR_BUTTON_LIGHT] = fNonFocusTabColorLight;
1455a32087bSJohn Scipione			}
1465a32087bSJohn Scipione			break;
1475a32087bSJohn Scipione
1485a32087bSJohn Scipione		case COMPONENT_LEFT_BORDER:
1495a32087bSJohn Scipione		case COMPONENT_RIGHT_BORDER:
1505a32087bSJohn Scipione		case COMPONENT_TOP_BORDER:
1515a32087bSJohn Scipione		case COMPONENT_BOTTOM_BORDER:
1525a32087bSJohn Scipione		case COMPONENT_RESIZE_CORNER:
1535a32087bSJohn Scipione		default:
1545a32087bSJohn Scipione			if (tab && tab->buttonFocus) {
1557f9368caSlooncraz				_colors[0] = tint_color(fFocusFrameColor, B_DARKEN_2_TINT);
1567f9368caSlooncraz				_colors[1] = tint_color(fFocusFrameColor, B_LIGHTEN_2_TINT);
1577f9368caSlooncraz				_colors[2] = fFocusFrameColor;
1587f9368caSlooncraz				_colors[3] = tint_color(fFocusFrameColor,
1595a32087bSJohn Scipione					(B_DARKEN_1_TINT + B_NO_TINT) / 2);
1607f9368caSlooncraz				_colors[4] = tint_color(fFocusFrameColor, B_DARKEN_2_TINT);
1617f9368caSlooncraz				_colors[5] = tint_color(fFocusFrameColor, B_DARKEN_3_TINT);
1625a32087bSJohn Scipione			} else {
1637f9368caSlooncraz				_colors[0] = tint_color(fNonFocusFrameColor, B_DARKEN_2_TINT);
1647f9368caSlooncraz				_colors[1] = tint_color(fNonFocusFrameColor, B_LIGHTEN_2_TINT);
1657f9368caSlooncraz				_colors[2] = fNonFocusFrameColor;
1667f9368caSlooncraz				_colors[3] = tint_color(fNonFocusFrameColor,
1675a32087bSJohn Scipione					(B_DARKEN_1_TINT + B_NO_TINT) / 2);
1687f9368caSlooncraz				_colors[4] = tint_color(fNonFocusFrameColor, B_DARKEN_2_TINT);
1697f9368caSlooncraz				_colors[5] = tint_color(fNonFocusFrameColor, B_DARKEN_3_TINT);
1705a32087bSJohn Scipione			}
1715a32087bSJohn Scipione
1725a32087bSJohn Scipione			// for the resize-border highlight dye everything bluish.
1735a32087bSJohn Scipione			if (highlight == HIGHLIGHT_RESIZE_BORDER) {
1745a32087bSJohn Scipione				for (int32 i = 0; i < 6; i++) {
1755a32087bSJohn Scipione					_colors[i].red = std::max((int)_colors[i].red - 80, 0);
1765a32087bSJohn Scipione					_colors[i].green = std::max((int)_colors[i].green - 80, 0);
1775a32087bSJohn Scipione					_colors[i].blue = 255;
1785a32087bSJohn Scipione				}
1795a32087bSJohn Scipione			}
1805a32087bSJohn Scipione			break;
1815a32087bSJohn Scipione	}
1825a32087bSJohn Scipione}
1835a32087bSJohn Scipione
1845a32087bSJohn Scipione
1857f9368caSlooncrazvoid
1867f9368caSlooncrazDefaultDecorator::UpdateColors(DesktopSettings& settings)
1877f9368caSlooncraz{
1887f9368caSlooncraz	TabDecorator::UpdateColors(settings);
1897f9368caSlooncraz}
1907f9368caSlooncraz
1917f9368caSlooncraz
192106fe8b3SJohn Scipione// #pragma mark - Protected methods
193bb2e9b06SClemens Zeidler
194bb2e9b06SClemens Zeidler
19559345e26SStephan Aßmusvoid
196cfe0652aSJohn ScipioneDefaultDecorator::_DrawFrame(BRect rect)
197ae01fc9bSDarkWyrm{
198cfe0652aSJohn Scipione	STRACE(("_DrawFrame(%f,%f,%f,%f)\n", rect.left, rect.top,
199cfe0652aSJohn Scipione		rect.right, rect.bottom));
200ae01fc9bSDarkWyrm
201e067fed5SStephan Aßmus	// NOTE: the DrawingEngine needs to be locked for the entire
202e067fed5SStephan Aßmus	// time for the clipping to stay valid for this decorator
20356f043edSAdi Oanca
2041c141573SClemens Zeidler	if (fTopTab->look == B_NO_BORDER_WINDOW_LOOK)
20559345e26SStephan Aßmus		return;
20656f043edSAdi Oanca
207cfe0652aSJohn Scipione	if (fBorderWidth <= 0)
20859345e26SStephan Aßmus		return;
20956f043edSAdi Oanca
21059345e26SStephan Aßmus	// Draw the border frame
21159345e26SStephan Aßmus	BRect r = BRect(fTopBorder.LeftTop(), fBottomBorder.RightBottom());
2121c141573SClemens Zeidler	switch ((int)fTopTab->look) {
21359345e26SStephan Aßmus		case B_TITLED_WINDOW_LOOK:
21459345e26SStephan Aßmus		case B_DOCUMENT_WINDOW_LOOK:
215083ec975SAxel Dörfler		case B_MODAL_WINDOW_LOOK:
216083ec975SAxel Dörfler		{
217083ec975SAxel Dörfler			// top
218cfe0652aSJohn Scipione			if (rect.Intersects(fTopBorder)) {
219e3ab8648SIngo Weinhold				ComponentColors colors;
22030d17caaSJohn Scipione				_GetComponentColors(COMPONENT_TOP_BORDER, colors, fTopTab);
221e3ab8648SIngo Weinhold
222e067fed5SStephan Aßmus				for (int8 i = 0; i < 5; i++) {
2232cfe93e7SStephan Aßmus					fDrawingEngine->StrokeLine(BPoint(r.left + i, r.top + i),
224e3ab8648SIngo Weinhold						BPoint(r.right - i, r.top + i), colors[i]);
225e067fed5SStephan Aßmus				}
226bb2e9b06SClemens Zeidler				if (fTitleBarRect.IsValid()) {
227f7e1df75SStephan Aßmus					// grey along the bottom of the tab
228f7e1df75SStephan Aßmus					// (overwrites "white" from frame)
229f7e1df75SStephan Aßmus					fDrawingEngine->StrokeLine(
230bb2e9b06SClemens Zeidler						BPoint(fTitleBarRect.left + 2,
231bb2e9b06SClemens Zeidler							fTitleBarRect.bottom + 1),
232bb2e9b06SClemens Zeidler						BPoint(fTitleBarRect.right - 2,
233bb2e9b06SClemens Zeidler							fTitleBarRect.bottom + 1),
234e3ab8648SIngo Weinhold						colors[2]);
23521625cdcSStephan Aßmus				}
23659345e26SStephan Aßmus			}
237083ec975SAxel Dörfler			// left
238cfe0652aSJohn Scipione			if (rect.Intersects(fLeftBorder.InsetByCopy(0, -fBorderWidth))) {
239e3ab8648SIngo Weinhold				ComponentColors colors;
24030d17caaSJohn Scipione				_GetComponentColors(COMPONENT_LEFT_BORDER, colors, fTopTab);
241e3ab8648SIngo Weinhold
242e067fed5SStephan Aßmus				for (int8 i = 0; i < 5; i++) {
2432cfe93e7SStephan Aßmus					fDrawingEngine->StrokeLine(BPoint(r.left + i, r.top + i),
244e3ab8648SIngo Weinhold						BPoint(r.left + i, r.bottom - i), colors[i]);
245e067fed5SStephan Aßmus				}
24659345e26SStephan Aßmus			}
247083ec975SAxel Dörfler			// bottom
248cfe0652aSJohn Scipione			if (rect.Intersects(fBottomBorder)) {
249e3ab8648SIngo Weinhold				ComponentColors colors;
25030d17caaSJohn Scipione				_GetComponentColors(COMPONENT_BOTTOM_BORDER, colors, fTopTab);
251e3ab8648SIngo Weinhold
252e067fed5SStephan Aßmus				for (int8 i = 0; i < 5; i++) {
2532cfe93e7SStephan Aßmus					fDrawingEngine->StrokeLine(BPoint(r.left + i, r.bottom - i),
254f7e1df75SStephan Aßmus						BPoint(r.right - i, r.bottom - i),
255e3ab8648SIngo Weinhold						colors[(4 - i) == 4 ? 5 : (4 - i)]);
256e067fed5SStephan Aßmus				}
25759345e26SStephan Aßmus			}
258083ec975SAxel Dörfler			// right
259cfe0652aSJohn Scipione			if (rect.Intersects(fRightBorder.InsetByCopy(0, -fBorderWidth))) {
260e3ab8648SIngo Weinhold				ComponentColors colors;
26130d17caaSJohn Scipione				_GetComponentColors(COMPONENT_RIGHT_BORDER, colors, fTopTab);
262e3ab8648SIngo Weinhold
263e067fed5SStephan Aßmus				for (int8 i = 0; i < 5; i++) {
2642cfe93e7SStephan Aßmus					fDrawingEngine->StrokeLine(BPoint(r.right - i, r.top + i),
265f7e1df75SStephan Aßmus						BPoint(r.right - i, r.bottom - i),
266e3ab8648SIngo Weinhold						colors[(4 - i) == 4 ? 5 : (4 - i)]);
267e067fed5SStephan Aßmus				}
26859345e26SStephan Aßmus			}
26959345e26SStephan Aßmus			break;
27059345e26SStephan Aßmus		}
2713ba76c14SMichael Lotz
272083ec975SAxel Dörfler		case B_FLOATING_WINDOW_LOOK:
273083ec975SAxel Dörfler		case kLeftTitledWindowLook:
274083ec975SAxel Dörfler		{
275083ec975SAxel Dörfler			// top
276cfe0652aSJohn Scipione			if (rect.Intersects(fTopBorder)) {
277e3ab8648SIngo Weinhold				ComponentColors colors;
27830d17caaSJohn Scipione				_GetComponentColors(COMPONENT_TOP_BORDER, colors, fTopTab);
279e3ab8648SIngo Weinhold
280e067fed5SStephan Aßmus				for (int8 i = 0; i < 3; i++) {
2812cfe93e7SStephan Aßmus					fDrawingEngine->StrokeLine(BPoint(r.left + i, r.top + i),
282e3ab8648SIngo Weinhold						BPoint(r.right - i, r.top + i), colors[i * 2]);
283e067fed5SStephan Aßmus				}
28445b17fdeSJohn Scipione				if (fTitleBarRect.IsValid() && fTopTab->look != kLeftTitledWindowLook) {
285f7e1df75SStephan Aßmus					// grey along the bottom of the tab
286f7e1df75SStephan Aßmus					// (overwrites "white" from frame)
287f7e1df75SStephan Aßmus					fDrawingEngine->StrokeLine(
288bb2e9b06SClemens Zeidler						BPoint(fTitleBarRect.left + 2,
289bb2e9b06SClemens Zeidler							fTitleBarRect.bottom + 1),
290bb2e9b06SClemens Zeidler						BPoint(fTitleBarRect.right - 2,
291bb2e9b06SClemens Zeidler							fTitleBarRect.bottom + 1), colors[2]);
29221625cdcSStephan Aßmus				}
29359345e26SStephan Aßmus			}
294083ec975SAxel Dörfler			// left
295cfe0652aSJohn Scipione			if (rect.Intersects(fLeftBorder.InsetByCopy(0, -fBorderWidth))) {
296e3ab8648SIngo Weinhold				ComponentColors colors;
29730d17caaSJohn Scipione				_GetComponentColors(COMPONENT_LEFT_BORDER, colors, fTopTab);
298e3ab8648SIngo Weinhold
299e067fed5SStephan Aßmus				for (int8 i = 0; i < 3; i++) {
3002cfe93e7SStephan Aßmus					fDrawingEngine->StrokeLine(BPoint(r.left + i, r.top + i),
301e3ab8648SIngo Weinhold						BPoint(r.left + i, r.bottom - i), colors[i * 2]);
302e067fed5SStephan Aßmus				}
3031c141573SClemens Zeidler				if (fTopTab->look == kLeftTitledWindowLook
3041c141573SClemens Zeidler					&& fTitleBarRect.IsValid()) {
305f7e1df75SStephan Aßmus					// grey along the right side of the tab
306f7e1df75SStephan Aßmus					// (overwrites "white" from frame)
307f7e1df75SStephan Aßmus					fDrawingEngine->StrokeLine(
308bb2e9b06SClemens Zeidler						BPoint(fTitleBarRect.right + 1,
309bb2e9b06SClemens Zeidler							fTitleBarRect.top + 2),
310bb2e9b06SClemens Zeidler						BPoint(fTitleBarRect.right + 1,
311bb2e9b06SClemens Zeidler							fTitleBarRect.bottom - 2), colors[2]);
312083ec975SAxel Dörfler				}
31359345e26SStephan Aßmus			}
314083ec975SAxel Dörfler			// bottom
315cfe0652aSJohn Scipione			if (rect.Intersects(fBottomBorder)) {
316e3ab8648SIngo Weinhold				ComponentColors colors;
31730d17caaSJohn Scipione				_GetComponentColors(COMPONENT_BOTTOM_BORDER, colors, fTopTab);
318e3ab8648SIngo Weinhold
319e067fed5SStephan Aßmus				for (int8 i = 0; i < 3; i++) {
3202cfe93e7SStephan Aßmus					fDrawingEngine->StrokeLine(BPoint(r.left + i, r.bottom - i),
321f7e1df75SStephan Aßmus						BPoint(r.right - i, r.bottom - i),
322e3ab8648SIngo Weinhold						colors[(2 - i) == 2 ? 5 : (2 - i) * 2]);
323e067fed5SStephan Aßmus				}
32459345e26SStephan Aßmus			}
325083ec975SAxel Dörfler			// right
326cfe0652aSJohn Scipione			if (rect.Intersects(fRightBorder.InsetByCopy(0, -fBorderWidth))) {
327e3ab8648SIngo Weinhold				ComponentColors colors;
32830d17caaSJohn Scipione				_GetComponentColors(COMPONENT_RIGHT_BORDER, colors, fTopTab);
329e3ab8648SIngo Weinhold
330e067fed5SStephan Aßmus				for (int8 i = 0; i < 3; i++) {
3312cfe93e7SStephan Aßmus					fDrawingEngine->StrokeLine(BPoint(r.right - i, r.top + i),
332f7e1df75SStephan Aßmus						BPoint(r.right - i, r.bottom - i),
333e3ab8648SIngo Weinhold						colors[(2 - i) == 2 ? 5 : (2 - i) * 2]);
334e067fed5SStephan Aßmus				}
33559345e26SStephan Aßmus			}
33659345e26SStephan Aßmus			break;
33759345e26SStephan Aßmus		}
338083ec975SAxel Dörfler
339083ec975SAxel Dörfler		case B_BORDERED_WINDOW_LOOK:
340e3ab8648SIngo Weinhold		{
341e3ab8648SIngo Weinhold			// TODO: Draw the borders individually!
342e3ab8648SIngo Weinhold			ComponentColors colors;
34330d17caaSJohn Scipione			_GetComponentColors(COMPONENT_LEFT_BORDER, colors, fTopTab);
344e3ab8648SIngo Weinhold
345e3ab8648SIngo Weinhold			fDrawingEngine->StrokeRect(r, colors[5]);
34659345e26SStephan Aßmus			break;
347e3ab8648SIngo Weinhold		}
34859345e26SStephan Aßmus
34959345e26SStephan Aßmus		default:
35059345e26SStephan Aßmus			// don't draw a border frame
35159345e26SStephan Aßmus			break;
35259345e26SStephan Aßmus	}
35359345e26SStephan Aßmus
354db4da598SRyan Leavengood	// Draw the resize knob if we're supposed to
3551c141573SClemens Zeidler	if (!(fTopTab->flags & B_NOT_RESIZABLE)) {
3562cfe93e7SStephan Aßmus		r = fResizeRect;
35759345e26SStephan Aßmus
358e3ab8648SIngo Weinhold		ComponentColors colors;
35930d17caaSJohn Scipione		_GetComponentColors(COMPONENT_RESIZE_CORNER, colors, fTopTab);
360e3ab8648SIngo Weinhold
3611c141573SClemens Zeidler		switch ((int)fTopTab->look) {
362083ec975SAxel Dörfler			case B_DOCUMENT_WINDOW_LOOK:
363083ec975SAxel Dörfler			{
364cfe0652aSJohn Scipione				if (!rect.Intersects(r))
36543307330SStephan Aßmus					break;
36643307330SStephan Aßmus
367e83820edSAxel Dörfler				float x = r.right - 3;
368e83820edSAxel Dörfler				float y = r.bottom - 3;
369e067fed5SStephan Aßmus
370ce5d6472SStephan Aßmus				BRect bg(x - 13, y - 13, x, y);
371ce5d6472SStephan Aßmus
372ce5d6472SStephan Aßmus				BGradientLinear gradient;
373ce5d6472SStephan Aßmus				gradient.SetStart(bg.LeftTop());
374ce5d6472SStephan Aßmus				gradient.SetEnd(bg.RightBottom());
375e3ab8648SIngo Weinhold				gradient.AddColor(colors[1], 0);
376e3ab8648SIngo Weinhold				gradient.AddColor(colors[2], 255);
377dacf06e6SAxel Dörfler
378ce5d6472SStephan Aßmus				fDrawingEngine->FillRect(bg, gradient);
379ce5d6472SStephan Aßmus
380f7e1df75SStephan Aßmus				fDrawingEngine->StrokeLine(BPoint(x - 15, y - 15),
381e3ab8648SIngo Weinhold					BPoint(x - 15, y - 2), colors[0]);
382f7e1df75SStephan Aßmus				fDrawingEngine->StrokeLine(BPoint(x - 14, y - 14),
383e3ab8648SIngo Weinhold					BPoint(x - 14, y - 1), colors[1]);
384f7e1df75SStephan Aßmus				fDrawingEngine->StrokeLine(BPoint(x - 15, y - 15),
385e3ab8648SIngo Weinhold					BPoint(x - 2, y - 15), colors[0]);
386f7e1df75SStephan Aßmus				fDrawingEngine->StrokeLine(BPoint(x - 14, y - 14),
387e3ab8648SIngo Weinhold					BPoint(x - 1, y - 14), colors[1]);
38859345e26SStephan Aßmus
389bb2e9b06SClemens Zeidler				if (fTopTab && !IsFocus(fTopTab))
39043307330SStephan Aßmus					break;
39143307330SStephan Aßmus
392ce5d6472SStephan Aßmus				static const rgb_color kWhite
393ce5d6472SStephan Aßmus					= (rgb_color){ 255, 255, 255, 255 };
39459345e26SStephan Aßmus				for (int8 i = 1; i <= 4; i++) {
39559345e26SStephan Aßmus					for (int8 j = 1; j <= i; j++) {
396f7e1df75SStephan Aßmus						BPoint pt1(x - (3 * j) + 1, y - (3 * (5 - i)) + 1);
397f7e1df75SStephan Aßmus						BPoint pt2(x - (3 * j) + 2, y - (3 * (5 - i)) + 2);
398e3ab8648SIngo Weinhold						fDrawingEngine->StrokePoint(pt1, colors[0]);
399ce5d6472SStephan Aßmus						fDrawingEngine->StrokePoint(pt2, kWhite);
40059345e26SStephan Aßmus					}
40159345e26SStephan Aßmus				}
40259345e26SStephan Aßmus				break;
40359345e26SStephan Aßmus			}
40459345e26SStephan Aßmus
40559345e26SStephan Aßmus			case B_TITLED_WINDOW_LOOK:
40659345e26SStephan Aßmus			case B_FLOATING_WINDOW_LOOK:
407083ec975SAxel Dörfler			case B_MODAL_WINDOW_LOOK:
408083ec975SAxel Dörfler			case kLeftTitledWindowLook:
409083ec975SAxel Dörfler			{
410cfe0652aSJohn Scipione				if (!rect.Intersects(BRect(fRightBorder.right - kBorderResizeLength,
411db4da598SRyan Leavengood					fBottomBorder.bottom - kBorderResizeLength, fRightBorder.right - 1,
412f7e1df75SStephan Aßmus					fBottomBorder.bottom - 1)))
413e067fed5SStephan Aßmus					break;
4143ba76c14SMichael Lotz
415f7e1df75SStephan Aßmus				fDrawingEngine->StrokeLine(
416db4da598SRyan Leavengood					BPoint(fRightBorder.left, fBottomBorder.bottom - kBorderResizeLength),
417db4da598SRyan Leavengood					BPoint(fRightBorder.right - 1, fBottomBorder.bottom - kBorderResizeLength),
418e3ab8648SIngo Weinhold					colors[0]);
419f7e1df75SStephan Aßmus				fDrawingEngine->StrokeLine(
420db4da598SRyan Leavengood					BPoint(fRightBorder.right - kBorderResizeLength, fBottomBorder.top),
421db4da598SRyan Leavengood					BPoint(fRightBorder.right - kBorderResizeLength, fBottomBorder.bottom - 1),
422e3ab8648SIngo Weinhold					colors[0]);
42359345e26SStephan Aßmus				break;
42459345e26SStephan Aßmus			}
425e83820edSAxel Dörfler
426083ec975SAxel Dörfler			default:
42759345e26SStephan Aßmus				// don't draw resize corner
42859345e26SStephan Aßmus				break;
42959345e26SStephan Aßmus		}
43059345e26SStephan Aßmus	}
43156f043edSAdi Oanca}
43256f043edSAdi Oanca
433e13a79e0SMichael Lotz
434cfe0652aSJohn Scipione/*!	\brief Actually draws the tab
435cfe0652aSJohn Scipione
436cfe0652aSJohn Scipione	This function is called when the tab itself needs drawn. Other items,
437cfe0652aSJohn Scipione	like the window title or buttons, should not be drawn here.
438cfe0652aSJohn Scipione
439cfe0652aSJohn Scipione	\param tab The \a tab to update.
440cfe0652aSJohn Scipione	\param rect The area of the \a tab to update.
441cfe0652aSJohn Scipione*/
44259345e26SStephan Aßmusvoid
443bb2e9b06SClemens ZeidlerDefaultDecorator::_DrawTab(Decorator::Tab* tab, BRect invalid)
444ae01fc9bSDarkWyrm{
445e067fed5SStephan Aßmus	STRACE(("_DrawTab(%.1f,%.1f,%.1f,%.1f)\n",
446bb2e9b06SClemens Zeidler		invalid.left, invalid.top, invalid.right, invalid.bottom));
447bb2e9b06SClemens Zeidler	const BRect& tabRect = tab->tabRect;
44859345e26SStephan Aßmus	// If a window has a tab, this will draw it and any buttons which are
44959345e26SStephan Aßmus	// in it.
450bb2e9b06SClemens Zeidler	if (!tabRect.IsValid() || !invalid.Intersects(tabRect))
4513231b95eSDarkWyrm		return;
45247007fb0SAdi Oanca
453e3ab8648SIngo Weinhold	ComponentColors colors;
454bb2e9b06SClemens Zeidler	_GetComponentColors(COMPONENT_TAB, colors, tab);
455e3ab8648SIngo Weinhold
45659345e26SStephan Aßmus	// outer frame
457bb2e9b06SClemens Zeidler	fDrawingEngine->StrokeLine(tabRect.LeftTop(), tabRect.LeftBottom(),
458e3ab8648SIngo Weinhold		colors[COLOR_TAB_FRAME_LIGHT]);
459bb2e9b06SClemens Zeidler	fDrawingEngine->StrokeLine(tabRect.LeftTop(), tabRect.RightTop(),
460e3ab8648SIngo Weinhold		colors[COLOR_TAB_FRAME_LIGHT]);
4611c141573SClemens Zeidler	if (tab->look != kLeftTitledWindowLook) {
462bb2e9b06SClemens Zeidler		fDrawingEngine->StrokeLine(tabRect.RightTop(), tabRect.RightBottom(),
463e3ab8648SIngo Weinhold			colors[COLOR_TAB_FRAME_DARK]);
464f7e1df75SStephan Aßmus	} else {
465bb2e9b06SClemens Zeidler		fDrawingEngine->StrokeLine(tabRect.LeftBottom(),
466bb2e9b06SClemens Zeidler			tabRect.RightBottom(), colors[COLOR_TAB_FRAME_DARK]);
467f7e1df75SStephan Aßmus	}
46816108979SAdi Oanca
469bb2e9b06SClemens Zeidler	float tabBotton = tabRect.bottom;
470bb2e9b06SClemens Zeidler	if (fTopTab != tab)
471bb2e9b06SClemens Zeidler		tabBotton -= 1;
472bb2e9b06SClemens Zeidler
47359345e26SStephan Aßmus	// bevel
474bb2e9b06SClemens Zeidler	fDrawingEngine->StrokeLine(BPoint(tabRect.left + 1, tabRect.top + 1),
475bb2e9b06SClemens Zeidler		BPoint(tabRect.left + 1,
4761c141573SClemens Zeidler			tabBotton - (tab->look == kLeftTitledWindowLook ? 1 : 0)),
477e3ab8648SIngo Weinhold		colors[COLOR_TAB_BEVEL]);
478bb2e9b06SClemens Zeidler	fDrawingEngine->StrokeLine(BPoint(tabRect.left + 1, tabRect.top + 1),
4791c141573SClemens Zeidler		BPoint(tabRect.right - (tab->look == kLeftTitledWindowLook ? 0 : 1),
480bb2e9b06SClemens Zeidler			tabRect.top + 1),
481e3ab8648SIngo Weinhold		colors[COLOR_TAB_BEVEL]);
48216108979SAdi Oanca
4831c141573SClemens Zeidler	if (tab->look != kLeftTitledWindowLook) {
484bb2e9b06SClemens Zeidler		fDrawingEngine->StrokeLine(BPoint(tabRect.right - 1, tabRect.top + 2),
485bb2e9b06SClemens Zeidler			BPoint(tabRect.right - 1, tabBotton),
486e3ab8648SIngo Weinhold			colors[COLOR_TAB_SHADOW]);
487083ec975SAxel Dörfler	} else {
488f7e1df75SStephan Aßmus		fDrawingEngine->StrokeLine(
489bb2e9b06SClemens Zeidler			BPoint(tabRect.left + 2, tabRect.bottom - 1),
490bb2e9b06SClemens Zeidler			BPoint(tabRect.right, tabRect.bottom - 1),
491e3ab8648SIngo Weinhold			colors[COLOR_TAB_SHADOW]);
492083ec975SAxel Dörfler	}
493ae01fc9bSDarkWyrm
49459345e26SStephan Aßmus	// fill
495ce5d6472SStephan Aßmus	BGradientLinear gradient;
496bb2e9b06SClemens Zeidler	gradient.SetStart(tabRect.LeftTop());
497e3ab8648SIngo Weinhold	gradient.AddColor(colors[COLOR_TAB_LIGHT], 0);
498e3ab8648SIngo Weinhold	gradient.AddColor(colors[COLOR_TAB], 255);
499ce5d6472SStephan Aßmus
5001c141573SClemens Zeidler	if (tab->look != kLeftTitledWindowLook) {
501bb2e9b06SClemens Zeidler		gradient.SetEnd(tabRect.LeftBottom());
502bb2e9b06SClemens Zeidler		fDrawingEngine->FillRect(BRect(tabRect.left + 2, tabRect.top + 2,
503bb2e9b06SClemens Zeidler			tabRect.right - 2, tabBotton), gradient);
504083ec975SAxel Dörfler	} else {
505bb2e9b06SClemens Zeidler		gradient.SetEnd(tabRect.RightTop());
506bb2e9b06SClemens Zeidler		fDrawingEngine->FillRect(BRect(tabRect.left + 2, tabRect.top + 2,
507bb2e9b06SClemens Zeidler			tabRect.right, tabRect.bottom - 2), gradient);
508083ec975SAxel Dörfler	}
50967f4247fSAdi Oanca
510bb2e9b06SClemens Zeidler	_DrawTitle(tab, tabRect);
511cc10522eSDarkWyrm
512cfe0652aSJohn Scipione	_DrawButtons(tab, invalid);
513ae01fc9bSDarkWyrm}
514ae01fc9bSDarkWyrm
515e13a79e0SMichael Lotz
516cfe0652aSJohn Scipione/*!	\brief Actually draws the title
517cfe0652aSJohn Scipione
518cfe0652aSJohn Scipione	The main tasks for this function are to ensure that the decorator draws
519cfe0652aSJohn Scipione	the title only in its own area and drawing the title itself.
520cfe0652aSJohn Scipione	Using B_OP_COPY for drawing the title is recommended because of the marked
521cfe0652aSJohn Scipione	performance hit of the other drawing modes, but it is not a requirement.
522cfe0652aSJohn Scipione
523cfe0652aSJohn Scipione	\param tab The \a tab to update.
524cfe0652aSJohn Scipione	\param rect area of the title to update.
525cfe0652aSJohn Scipione*/
52659345e26SStephan Aßmusvoid
527106fe8b3SJohn ScipioneDefaultDecorator::_DrawTitle(Decorator::Tab* _tab, BRect rect)
528ae01fc9bSDarkWyrm{
529106fe8b3SJohn Scipione	STRACE(("_DrawTitle(%f,%f,%f,%f)\n", rect.left, rect.top, rect.right,
530106fe8b3SJohn Scipione		rect.bottom));
531106fe8b3SJohn Scipione
532cfe0652aSJohn Scipione	Decorator::Tab* tab = static_cast<Decorator::Tab*>(_tab);
533bb2e9b06SClemens Zeidler
534bb2e9b06SClemens Zeidler	const BRect& tabRect = tab->tabRect;
535bb2e9b06SClemens Zeidler	const BRect& closeRect = tab->closeRect;
536bb2e9b06SClemens Zeidler	const BRect& zoomRect = tab->zoomRect;
537bb2e9b06SClemens Zeidler
538e3ab8648SIngo Weinhold	ComponentColors colors;
539bb2e9b06SClemens Zeidler	_GetComponentColors(COMPONENT_TAB, colors, tab);
540e3ab8648SIngo Weinhold
541ce5d6472SStephan Aßmus	fDrawingEngine->SetDrawingMode(B_OP_OVER);
542e3ab8648SIngo Weinhold	fDrawingEngine->SetHighColor(colors[COLOR_TAB_TEXT]);
54338287e02SStephan Aßmus	fDrawingEngine->SetFont(fDrawState.Font());
544ae01fc9bSDarkWyrm
54559345e26SStephan Aßmus	// figure out position of text
5468365d9ecSAxel Dörfler	font_height fontHeight;
547aca4f50dSAxel Dörfler	fDrawState.Font().GetHeight(fontHeight);
548ae01fc9bSDarkWyrm
54959345e26SStephan Aßmus	BPoint titlePos;
5501c141573SClemens Zeidler	if (tab->look != kLeftTitledWindowLook) {
551bb2e9b06SClemens Zeidler		titlePos.x = closeRect.IsValid() ? closeRect.right + tab->textOffset
552bb2e9b06SClemens Zeidler			: tabRect.left + tab->textOffset;
553bb2e9b06SClemens Zeidler		titlePos.y = floorf(((tabRect.top + 2.0) + tabRect.bottom
554f7e1df75SStephan Aßmus			+ fontHeight.ascent + fontHeight.descent) / 2.0
555f7e1df75SStephan Aßmus			- fontHeight.descent + 0.5);
556083ec975SAxel Dörfler	} else {
557bb2e9b06SClemens Zeidler		titlePos.x = floorf(((tabRect.left + 2.0) + tabRect.right
558f7e1df75SStephan Aßmus			+ fontHeight.ascent + fontHeight.descent) / 2.0
559f7e1df75SStephan Aßmus			- fontHeight.descent + 0.5);
560bb2e9b06SClemens Zeidler		titlePos.y = zoomRect.IsValid() ? zoomRect.top - tab->textOffset
561bb2e9b06SClemens Zeidler			: tabRect.bottom - tab->textOffset;
562083ec975SAxel Dörfler	}
5638365d9ecSAxel Dörfler
564bb2e9b06SClemens Zeidler	fDrawingEngine->DrawString(tab->truncatedTitle, tab->truncatedTitleLength,
56538287e02SStephan Aßmus		titlePos);
566ce5d6472SStephan Aßmus
567ce5d6472SStephan Aßmus	fDrawingEngine->SetDrawingMode(B_OP_COPY);
568ae01fc9bSDarkWyrm}
569ae01fc9bSDarkWyrm
570b31df46fSAxel Dörfler
571cfe0652aSJohn Scipione/*!	\brief Actually draws the close button
572cfe0652aSJohn Scipione
573cfe0652aSJohn Scipione	Unless a subclass has a particularly large button, it is probably
574cfe0652aSJohn Scipione	unnecessary to check the update rectangle.
575cfe0652aSJohn Scipione
576cfe0652aSJohn Scipione	\param _tab The \a tab to update.
577cfe0652aSJohn Scipione	\param direct Draw without double buffering.
578cfe0652aSJohn Scipione	\param rect The area of the button to update.
579cfe0652aSJohn Scipione*/
5805a32087bSJohn Scipionevoid
5815a32087bSJohn ScipioneDefaultDecorator::_DrawClose(Decorator::Tab* _tab, bool direct, BRect rect)
5825a32087bSJohn Scipione{
5835a32087bSJohn Scipione	STRACE(("_DrawClose(%f,%f,%f,%f)\n", rect.left, rect.top, rect.right,
5845a32087bSJohn Scipione		rect.bottom));
5855a32087bSJohn Scipione
586cfe0652aSJohn Scipione	Decorator::Tab* tab = static_cast<Decorator::Tab*>(_tab);
5875a32087bSJohn Scipione
5885a32087bSJohn Scipione	int32 index = (tab->buttonFocus ? 0 : 1) + (tab->closePressed ? 0 : 2);
5895a32087bSJohn Scipione	ServerBitmap* bitmap = tab->closeBitmaps[index];
5905a32087bSJohn Scipione	if (bitmap == NULL) {
5915a32087bSJohn Scipione		bitmap = _GetBitmapForButton(tab, COMPONENT_CLOSE_BUTTON,
5925a32087bSJohn Scipione			tab->closePressed, rect.IntegerWidth(), rect.IntegerHeight());
5935a32087bSJohn Scipione		tab->closeBitmaps[index] = bitmap;
5945a32087bSJohn Scipione	}
5955a32087bSJohn Scipione
5965a32087bSJohn Scipione	_DrawButtonBitmap(bitmap, direct, rect);
5975a32087bSJohn Scipione}
5985a32087bSJohn Scipione
5995a32087bSJohn Scipione
600cfe0652aSJohn Scipione/*!	\brief Actually draws the zoom button
601cfe0652aSJohn Scipione
602cfe0652aSJohn Scipione	Unless a subclass has a particularly large button, it is probably
603cfe0652aSJohn Scipione	unnecessary to check the update rectangle.
604cfe0652aSJohn Scipione
605cfe0652aSJohn Scipione	\param _tab The \a tab to update.
606cfe0652aSJohn Scipione	\param direct Draw without double buffering.
607cfe0652aSJohn Scipione	\param rect The area of the button to update.
608cfe0652aSJohn Scipione*/
60959345e26SStephan Aßmusvoid
61086b01082SClemens ZeidlerDefaultDecorator::_DrawZoom(Decorator::Tab* _tab, bool direct, BRect rect)
611ae01fc9bSDarkWyrm{
612e13a79e0SMichael Lotz	STRACE(("_DrawZoom(%f,%f,%f,%f)\n", rect.left, rect.top, rect.right,
613e13a79e0SMichael Lotz		rect.bottom));
614106fe8b3SJohn Scipione
615bb2e9b06SClemens Zeidler	if (rect.IntegerWidth() < 1)
616bb2e9b06SClemens Zeidler		return;
617e13a79e0SMichael Lotz
618cfe0652aSJohn Scipione	Decorator::Tab* tab = static_cast<Decorator::Tab*>(_tab);
619bb2e9b06SClemens Zeidler	int32 index = (tab->buttonFocus ? 0 : 1) + (tab->zoomPressed ? 0 : 2);
620bb2e9b06SClemens Zeidler	ServerBitmap* bitmap = tab->zoomBitmaps[index];
621e13a79e0SMichael Lotz	if (bitmap == NULL) {
622bb2e9b06SClemens Zeidler		bitmap = _GetBitmapForButton(tab, COMPONENT_ZOOM_BUTTON,
623bb2e9b06SClemens Zeidler			tab->zoomPressed, rect.IntegerWidth(), rect.IntegerHeight());
624bb2e9b06SClemens Zeidler		tab->zoomBitmaps[index] = bitmap;
625e13a79e0SMichael Lotz	}
626e60b1ff1SAxel Dörfler
62786b01082SClemens Zeidler	_DrawButtonBitmap(bitmap, direct, rect);
628ae01fc9bSDarkWyrm}
629ae01fc9bSDarkWyrm
630b31df46fSAxel Dörfler
631cfe0652aSJohn Scipionevoid
632cfe0652aSJohn ScipioneDefaultDecorator::_DrawMinimize(Decorator::Tab* tab, bool direct, BRect rect)
633cfe0652aSJohn Scipione{
634cfe0652aSJohn Scipione	// This decorator doesn't have this button
635cfe0652aSJohn Scipione}
636cfe0652aSJohn Scipione
637cfe0652aSJohn Scipione
638106fe8b3SJohn Scipione// #pragma mark - Private methods
6390a3f410fSAxel Dörfler
6400a3f410fSAxel Dörfler
6416309b004SMichael Lotzvoid
64286b01082SClemens ZeidlerDefaultDecorator::_DrawButtonBitmap(ServerBitmap* bitmap, bool direct,
64386b01082SClemens Zeidler	BRect rect)
6446309b004SMichael Lotz{
6456309b004SMichael Lotz	if (bitmap == NULL)
6466309b004SMichael Lotz		return;
6476309b004SMichael Lotz
648d0b2c3e1SMichael Lotz	bool copyToFrontEnabled = fDrawingEngine->CopyToFrontEnabled();
64986b01082SClemens Zeidler	fDrawingEngine->SetCopyToFrontEnabled(direct);
650ce5d6472SStephan Aßmus	drawing_mode oldMode;
651ce5d6472SStephan Aßmus	fDrawingEngine->SetDrawingMode(B_OP_OVER, oldMode);
652d0b2c3e1SMichael Lotz	fDrawingEngine->DrawBitmap(bitmap, rect.OffsetToCopy(0, 0), rect);
653ce5d6472SStephan Aßmus	fDrawingEngine->SetDrawingMode(oldMode);
654d0b2c3e1SMichael Lotz	fDrawingEngine->SetCopyToFrontEnabled(copyToFrontEnabled);
6556309b004SMichael Lotz}
6566309b004SMichael Lotz
6576309b004SMichael Lotz
658dacf06e6SAxel Dörfler/*!	\brief Draws a framed rectangle with a gradient.
6595a32087bSJohn Scipione	\param engine The drawing engine to use.
6605a32087bSJohn Scipione	\param rect The rectangular area to draw in.
66106aa76e2SIngo Weinhold	\param down The rectangle should be drawn recessed or not.
6625a32087bSJohn Scipione	\param colors A button color array of the colors to be used.
66314fb2b69SAxel Dörfler*/
66459345e26SStephan Aßmusvoid
6655a32087bSJohn ScipioneDefaultDecorator::_DrawBlendedRect(DrawingEngine* engine, const BRect rect,
66606aa76e2SIngo Weinhold	bool down, const ComponentColors& colors)
667ae01fc9bSDarkWyrm{
668ce5d6472SStephan Aßmus	// figure out which colors to use
669e13a79e0SMichael Lotz	rgb_color startColor, endColor;
67059345e26SStephan Aßmus	if (down) {
67106aa76e2SIngo Weinhold		startColor = tint_color(colors[COLOR_BUTTON], B_DARKEN_1_TINT);
67206aa76e2SIngo Weinhold		endColor = colors[COLOR_BUTTON_LIGHT];
67359345e26SStephan Aßmus	} else {
67406aa76e2SIngo Weinhold		startColor = tint_color(colors[COLOR_BUTTON], B_LIGHTEN_MAX_TINT);
67506aa76e2SIngo Weinhold		endColor = colors[COLOR_BUTTON];
676ae01fc9bSDarkWyrm	}
677e13a79e0SMichael Lotz
678ce5d6472SStephan Aßmus	// fill
6795a32087bSJohn Scipione	BRect fillRect(rect.InsetByCopy(1.0f, 1.0f));
6805a32087bSJohn Scipione
681ce5d6472SStephan Aßmus	BGradientLinear gradient;
6825a32087bSJohn Scipione	gradient.SetStart(fillRect.LeftTop());
6835a32087bSJohn Scipione	gradient.SetEnd(fillRect.RightBottom());
684ce5d6472SStephan Aßmus	gradient.AddColor(startColor, 0);
685ce5d6472SStephan Aßmus	gradient.AddColor(endColor, 255);
686ce5d6472SStephan Aßmus
6875a32087bSJohn Scipione	engine->FillRect(fillRect, gradient);
688ce5d6472SStephan Aßmus
689ce5d6472SStephan Aßmus	// outline
69006aa76e2SIngo Weinhold	engine->StrokeRect(rect, tint_color(colors[COLOR_BUTTON], B_DARKEN_2_TINT));
691ae01fc9bSDarkWyrm}
692ae01fc9bSDarkWyrm
693b31df46fSAxel Dörfler
694b31df46fSAxel DörflerServerBitmap*
695bb2e9b06SClemens ZeidlerDefaultDecorator::_GetBitmapForButton(Decorator::Tab* tab, Component item,
696bb2e9b06SClemens Zeidler	bool down, int32 width, int32 height)
697e13a79e0SMichael Lotz{
698e13a79e0SMichael Lotz	// TODO: the list of shared bitmaps is never freed
699e13a79e0SMichael Lotz	struct decorator_bitmap {
70009b19da8SIngo Weinhold		Component			item;
701e13a79e0SMichael Lotz		bool				down;
702e13a79e0SMichael Lotz		int32				width;
703e13a79e0SMichael Lotz		int32				height;
70406aa76e2SIngo Weinhold		rgb_color			baseColor;
70506aa76e2SIngo Weinhold		rgb_color			lightColor;
706b31df46fSAxel Dörfler		UtilityBitmap*		bitmap;
707b31df46fSAxel Dörfler		decorator_bitmap*	next;
708e13a79e0SMichael Lotz	};
709e13a79e0SMichael Lotz
710e13a79e0SMichael Lotz	static BLocker sBitmapListLock("decorator lock", true);
711b31df46fSAxel Dörfler	static decorator_bitmap* sBitmapList = NULL;
71206aa76e2SIngo Weinhold
71306aa76e2SIngo Weinhold	ComponentColors colors;
714bb2e9b06SClemens Zeidler	_GetComponentColors(item, colors, tab);
71506aa76e2SIngo Weinhold
716e13a79e0SMichael Lotz	BAutolock locker(sBitmapListLock);
717e13a79e0SMichael Lotz
718e13a79e0SMichael Lotz	// search our list for a matching bitmap
7190d1d2de5SAxel Dörfler	// TODO: use a hash map instead?
720b31df46fSAxel Dörfler	decorator_bitmap* current = sBitmapList;
721e13a79e0SMichael Lotz	while (current) {
722e13a79e0SMichael Lotz		if (current->item == item && current->down == down
72306aa76e2SIngo Weinhold			&& current->width == width && current->height == height
72406aa76e2SIngo Weinhold			&& current->baseColor == colors[COLOR_BUTTON]
72506aa76e2SIngo Weinhold			&& current->lightColor == colors[COLOR_BUTTON_LIGHT]) {
726e13a79e0SMichael Lotz			return current->bitmap;
727e13a79e0SMichael Lotz		}
728e13a79e0SMichael Lotz
729e13a79e0SMichael Lotz		current = current->next;
730e13a79e0SMichael Lotz	}
731e13a79e0SMichael Lotz
732b31df46fSAxel Dörfler	static BitmapDrawingEngine* sBitmapDrawingEngine = NULL;
733e13a79e0SMichael Lotz
734e13a79e0SMichael Lotz	// didn't find any bitmap, create a new one
735e13a79e0SMichael Lotz	if (sBitmapDrawingEngine == NULL)
736e13a79e0SMichael Lotz		sBitmapDrawingEngine = new(std::nothrow) BitmapDrawingEngine();
737e13a79e0SMichael Lotz	if (sBitmapDrawingEngine == NULL
738e13a79e0SMichael Lotz		|| sBitmapDrawingEngine->SetSize(width, height) != B_OK)
739e13a79e0SMichael Lotz		return NULL;
740e13a79e0SMichael Lotz
741e13a79e0SMichael Lotz	BRect rect(0, 0, width - 1, height - 1);
742e13a79e0SMichael Lotz
74306aa76e2SIngo Weinhold	STRACE(("DefaultDecorator creating bitmap for %s %s at size %ldx%ld\n",
74406aa76e2SIngo Weinhold		item == COMPONENT_CLOSE_BUTTON ? "close" : "zoom",
745e13a79e0SMichael Lotz		down ? "down" : "up", width, height));
746e13a79e0SMichael Lotz	switch (item) {
74709b19da8SIngo Weinhold		case COMPONENT_CLOSE_BUTTON:
74806aa76e2SIngo Weinhold			_DrawBlendedRect(sBitmapDrawingEngine, rect, down, colors);
749e13a79e0SMichael Lotz			break;
750e13a79e0SMichael Lotz
75109b19da8SIngo Weinhold		case COMPONENT_ZOOM_BUTTON:
752e13a79e0SMichael Lotz		{
753ce5d6472SStephan Aßmus			sBitmapDrawingEngine->FillRect(rect, B_TRANSPARENT_COLOR);
7545a32087bSJohn Scipione				// init the background
755ce5d6472SStephan Aßmus
756e13a79e0SMichael Lotz			float inset = floorf(width / 4.0);
757e13a79e0SMichael Lotz			BRect zoomRect(rect);
758e13a79e0SMichael Lotz			zoomRect.left += inset;
759e13a79e0SMichael Lotz			zoomRect.top += inset;
76006aa76e2SIngo Weinhold			_DrawBlendedRect(sBitmapDrawingEngine, zoomRect, down, colors);
761e13a79e0SMichael Lotz
762e13a79e0SMichael Lotz			inset = floorf(width / 2.1);
763e13a79e0SMichael Lotz			zoomRect = rect;
764e13a79e0SMichael Lotz			zoomRect.right -= inset;
765e13a79e0SMichael Lotz			zoomRect.bottom -= inset;
76606aa76e2SIngo Weinhold			_DrawBlendedRect(sBitmapDrawingEngine, zoomRect, down, colors);
767e13a79e0SMichael Lotz			break;
768e13a79e0SMichael Lotz		}
7690fd53296SIngo Weinhold
7700fd53296SIngo Weinhold		default:
7710fd53296SIngo Weinhold			break;
772e13a79e0SMichael Lotz	}
773e13a79e0SMichael Lotz
774b31df46fSAxel Dörfler	UtilityBitmap* bitmap = sBitmapDrawingEngine->ExportToBitmap(width, height,
775e13a79e0SMichael Lotz		B_RGB32);
776e13a79e0SMichael Lotz	if (bitmap == NULL)
777e13a79e0SMichael Lotz		return NULL;
778e13a79e0SMichael Lotz
779e13a79e0SMichael Lotz	// bitmap ready, put it into the list
780b31df46fSAxel Dörfler	decorator_bitmap* entry = new(std::nothrow) decorator_bitmap;
781e13a79e0SMichael Lotz	if (entry == NULL) {
782e13a79e0SMichael Lotz		delete bitmap;
783e13a79e0SMichael Lotz		return NULL;
784e13a79e0SMichael Lotz	}
785e13a79e0SMichael Lotz
786e13a79e0SMichael Lotz	entry->item = item;
787e13a79e0SMichael Lotz	entry->down = down;
788e13a79e0SMichael Lotz	entry->width = width;
789e13a79e0SMichael Lotz	entry->height = height;
790e13a79e0SMichael Lotz	entry->bitmap = bitmap;
79106aa76e2SIngo Weinhold	entry->baseColor = colors[COLOR_BUTTON];
79206aa76e2SIngo Weinhold	entry->lightColor = colors[COLOR_BUTTON_LIGHT];
793e13a79e0SMichael Lotz	entry->next = sBitmapList;
794e13a79e0SMichael Lotz	sBitmapList = entry;
7955a32087bSJohn Scipione
796e13a79e0SMichael Lotz	return bitmap;
797e13a79e0SMichael Lotz}
7982b602c73SIngo Weinhold
7992b602c73SIngo Weinhold
8002b602c73SIngo Weinholdvoid
8012b602c73SIngo WeinholdDefaultDecorator::_GetComponentColors(Component component,
802bb2e9b06SClemens Zeidler	ComponentColors _colors, Decorator::Tab* tab)
8032b602c73SIngo Weinhold{
8042b602c73SIngo Weinhold	// get the highlight for our component
805003b80f0SIngo Weinhold	Region region = REGION_NONE;
8062b602c73SIngo Weinhold	switch (component) {
8072b602c73SIngo Weinhold		case COMPONENT_TAB:
8082b602c73SIngo Weinhold			region = REGION_TAB;
8092b602c73SIngo Weinhold			break;
8102b602c73SIngo Weinhold		case COMPONENT_CLOSE_BUTTON:
8112b602c73SIngo Weinhold			region = REGION_CLOSE_BUTTON;
8122b602c73SIngo Weinhold			break;
8132b602c73SIngo Weinhold		case COMPONENT_ZOOM_BUTTON:
8142b602c73SIngo Weinhold			region = REGION_ZOOM_BUTTON;
8152b602c73SIngo Weinhold			break;
8162b602c73SIngo Weinhold		case COMPONENT_LEFT_BORDER:
8172b602c73SIngo Weinhold			region = REGION_LEFT_BORDER;
8182b602c73SIngo Weinhold			break;
8192b602c73SIngo Weinhold		case COMPONENT_RIGHT_BORDER:
8202b602c73SIngo Weinhold			region = REGION_RIGHT_BORDER;
8212b602c73SIngo Weinhold			break;
8222b602c73SIngo Weinhold		case COMPONENT_TOP_BORDER:
8232b602c73SIngo Weinhold			region = REGION_TOP_BORDER;
8242b602c73SIngo Weinhold			break;
8252b602c73SIngo Weinhold		case COMPONENT_BOTTOM_BORDER:
8262b602c73SIngo Weinhold			region = REGION_BOTTOM_BORDER;
8272b602c73SIngo Weinhold			break;
8282b602c73SIngo Weinhold		case COMPONENT_RESIZE_CORNER:
8292b602c73SIngo Weinhold			region = REGION_RIGHT_BOTTOM_CORNER;
8302b602c73SIngo Weinhold			break;
8312b602c73SIngo Weinhold	}
8322b602c73SIngo Weinhold
833bb2e9b06SClemens Zeidler	return GetComponentColors(component, RegionHighlight(region), _colors, tab);
834bb2e9b06SClemens Zeidler}
835