DefaultDecorator.cpp revision 87c51182
1b5436616SAxel Dörfler/*
287c51182SJohn Scipione * Copyright 2001-2013 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
13b5436616SAxel Dörfler */
14b5436616SAxel Dörfler
15ba1d39e4SAxel Dörfler
16437b1927SAxel Dörfler/*!	Default and fallback decorator for the app_server - the yellow tabs */
17b5436616SAxel Dörfler
18e742e3e1SStephan Aßmus
1905bd1efeSAxel Dörfler#include "DefaultDecorator.h"
20e742e3e1SStephan Aßmus
2192fe8be9SIngo Weinhold#include <algorithm>
22bb2e9b06SClemens Zeidler#include <cmath>
23926e63c8SBrecht Machiels#include <new>
24926e63c8SBrecht Machiels#include <stdio.h>
25926e63c8SBrecht Machiels
26926e63c8SBrecht Machiels#include <Autolock.h>
27bb2e9b06SClemens Zeidler#include <Debug.h>
28926e63c8SBrecht Machiels#include <GradientLinear.h>
29926e63c8SBrecht Machiels#include <Rect.h>
30926e63c8SBrecht Machiels#include <View.h>
31926e63c8SBrecht Machiels
32926e63c8SBrecht Machiels#include <WindowPrivate.h>
33926e63c8SBrecht Machiels
34e13a79e0SMichael Lotz#include "BitmapDrawingEngine.h"
3505bd1efeSAxel Dörfler#include "DesktopSettings.h"
366ed89418SStephan Aßmus#include "DrawingEngine.h"
37aca4f50dSAxel Dörfler#include "DrawState.h"
38bdd34c02SAxel Dörfler#include "FontManager.h"
39a7e4fa4cSDarkWyrm#include "PatternHandler.h"
40e13a79e0SMichael Lotz#include "ServerBitmap.h"
4147b0fc0eSDarkWyrm
4267f4247fSAdi Oanca
437641924eSAdi Oanca//#define DEBUG_DECORATOR
4483742972SDarkWyrm#ifdef DEBUG_DECORATOR
453ecfa8e1SAdi Oanca#	define STRACE(x) printf x
463ecfa8e1SAdi Oanca#else
473ecfa8e1SAdi Oanca#	define STRACE(x) ;
4883742972SDarkWyrm#endif
4983742972SDarkWyrm
5005bd1efeSAxel Dörfler
51bb2e9b06SClemens ZeidlerDefaultDecorator::Tab::Tab()
52bb2e9b06SClemens Zeidler	:
53bb2e9b06SClemens Zeidler	tabOffset(0),
54bb2e9b06SClemens Zeidler	tabLocation(0.0),
55bb2e9b06SClemens Zeidler	isHighlighted(false)
56bb2e9b06SClemens Zeidler{
57bb2e9b06SClemens Zeidler	closeBitmaps[0] = closeBitmaps[1] = closeBitmaps[2] = closeBitmaps[3]
58bb2e9b06SClemens Zeidler		= zoomBitmaps[0] = zoomBitmaps[1] = zoomBitmaps[2] = zoomBitmaps[3]
59bb2e9b06SClemens Zeidler		= NULL;
60bb2e9b06SClemens Zeidler}
61bb2e9b06SClemens Zeidler
62bb2e9b06SClemens Zeidler
63db4da598SRyan Leavengoodstatic const float kBorderResizeLength = 22.0;
64db4da598SRyan Leavengoodstatic const float kResizeKnobSize = 18.0;
65db4da598SRyan Leavengood
66a17770f4SRyan Leavengood
6749fe9677SAxel Dörflerstatic inline uint8
6849fe9677SAxel Dörflerblend_color_value(uint8 a, uint8 b, float position)
6949fe9677SAxel Dörfler{
70c16fda11SAxel Dörfler	int16 delta = (int16)b - a;
7149fe9677SAxel Dörfler	int32 value = a + (int32)(position * delta);
7249fe9677SAxel Dörfler	if (value > 255)
7349fe9677SAxel Dörfler		return 255;
7449fe9677SAxel Dörfler	if (value < 0)
7549fe9677SAxel Dörfler		return 0;
7649fe9677SAxel Dörfler
7749fe9677SAxel Dörfler	return (uint8)value;
7849fe9677SAxel Dörfler}
7949fe9677SAxel Dörfler
8049fe9677SAxel Dörfler
8149fe9677SAxel Dörfler//	#pragma mark -
8249fe9677SAxel Dörfler
8349fe9677SAxel Dörfler
84e3ab8648SIngo Weinholdconst rgb_color DefaultDecorator::kFrameColors[4] = {
85e3ab8648SIngo Weinhold	{ 152, 152, 152, 255 },
86e3ab8648SIngo Weinhold	{ 240, 240, 240, 255 },
87e3ab8648SIngo Weinhold	{ 152, 152, 152, 255 },
88e3ab8648SIngo Weinhold	{ 108, 108, 108, 255 }
89e3ab8648SIngo Weinhold};
90e3ab8648SIngo Weinhold
91e3ab8648SIngo Weinhold
9285f8bb71SAxel Dörfler// TODO: get rid of DesktopSettings here, and introduce private accessor
9385f8bb71SAxel Dörfler//	methods to the Decorator base class
941c141573SClemens ZeidlerDefaultDecorator::DefaultDecorator(DesktopSettings& settings, BRect rect)
95e3ab8648SIngo Weinhold	:
961c141573SClemens Zeidler	Decorator(settings, rect),
97e3ab8648SIngo Weinhold	// focus color constants
9830d17caaSJohn Scipione	kFocusFrameColor(settings.UIColor(B_WINDOW_BORDER_COLOR)),
99e3ab8648SIngo Weinhold	kFocusTabColor(settings.UIColor(B_WINDOW_TAB_COLOR)),
100e3ab8648SIngo Weinhold	kFocusTabColorLight(tint_color(kFocusTabColor,
101e3ab8648SIngo Weinhold 		(B_LIGHTEN_MAX_TINT + B_LIGHTEN_2_TINT) / 2)),
102e3ab8648SIngo Weinhold	kFocusTabColorBevel(tint_color(kFocusTabColor, B_LIGHTEN_2_TINT)),
103e3ab8648SIngo Weinhold	kFocusTabColorShadow(tint_color(kFocusTabColor,
104e3ab8648SIngo Weinhold 		(B_DARKEN_1_TINT + B_NO_TINT) / 2)),
105e3ab8648SIngo Weinhold	kFocusTextColor(settings.UIColor(B_WINDOW_TEXT_COLOR)),
106e3ab8648SIngo Weinhold	// non-focus color constants
10730d17caaSJohn Scipione	kNonFocusFrameColor(settings.UIColor(B_WINDOW_INACTIVE_BORDER_COLOR)),
108e3ab8648SIngo Weinhold	kNonFocusTabColor(settings.UIColor(B_WINDOW_INACTIVE_TAB_COLOR)),
109e3ab8648SIngo Weinhold	kNonFocusTabColorLight(tint_color(kNonFocusTabColor,
110e3ab8648SIngo Weinhold 		(B_LIGHTEN_MAX_TINT + B_LIGHTEN_2_TINT) / 2)),
111e3ab8648SIngo Weinhold	kNonFocusTabColorBevel(tint_color(kNonFocusTabColor, B_LIGHTEN_2_TINT)),
112e3ab8648SIngo Weinhold	kNonFocusTabColorShadow(tint_color(kNonFocusTabColor,
113e3ab8648SIngo Weinhold 		(B_DARKEN_1_TINT + B_NO_TINT) / 2)),
114e3ab8648SIngo Weinhold	kNonFocusTextColor(settings.UIColor(B_WINDOW_INACTIVE_TEXT_COLOR)),
115bb2e9b06SClemens Zeidler
116bb2e9b06SClemens Zeidler	fOldMovingTab(0, 0, -1, -1)
117ae01fc9bSDarkWyrm{
1187f6629a9SStephan Aßmus	// TODO: If the decorator was created with a frame too small, it should
1197f6629a9SStephan Aßmus	// resize itself!
12008d9a6e3SAxel Dörfler
12137aec728SDarkWyrm	STRACE(("DefaultDecorator:\n"));
12208d9a6e3SAxel Dörfler	STRACE(("\tFrame (%.1f,%.1f,%.1f,%.1f)\n",
12308d9a6e3SAxel Dörfler		rect.left, rect.top, rect.right, rect.bottom));
124ae01fc9bSDarkWyrm}
125ae01fc9bSDarkWyrm
126614de12dSAxel Dörfler
127614de12dSAxel DörflerDefaultDecorator::~DefaultDecorator()
128ae01fc9bSDarkWyrm{
12937aec728SDarkWyrm	STRACE(("DefaultDecorator: ~DefaultDecorator()\n"));
13059345e26SStephan Aßmus}
13159345e26SStephan Aßmus
132614de12dSAxel Dörfler
133bb2e9b06SClemens Zeidlerfloat
134bb2e9b06SClemens ZeidlerDefaultDecorator::TabLocation(int32 tab) const
135bb2e9b06SClemens Zeidler{
136bb2e9b06SClemens Zeidler	DefaultDecorator::Tab* decoratorTab = _TabAt(tab);
137bb2e9b06SClemens Zeidler	if (decoratorTab == NULL)
13830d17caaSJohn Scipione		return 0.0f;
139bb2e9b06SClemens Zeidler	return (float)decoratorTab->tabOffset;
140bb2e9b06SClemens Zeidler}
141bb2e9b06SClemens Zeidler
142bb2e9b06SClemens Zeidler
143b30e9021SStephan Aßmusbool
144b30e9021SStephan AßmusDefaultDecorator::GetSettings(BMessage* settings) const
145b30e9021SStephan Aßmus{
146bb2e9b06SClemens Zeidler	if (!fTitleBarRect.IsValid())
147ef831a1dSPhilippe Houdoin		return false;
148ef831a1dSPhilippe Houdoin
149bb2e9b06SClemens Zeidler	if (settings->AddRect("tab frame", fTitleBarRect) != B_OK)
150ef831a1dSPhilippe Houdoin		return false;
151ef831a1dSPhilippe Houdoin
15285d512edSPhilippe Houdoin	if (settings->AddFloat("border width", fBorderWidth) != B_OK)
153ef831a1dSPhilippe Houdoin		return false;
154ef831a1dSPhilippe Houdoin
155bb2e9b06SClemens Zeidler	// TODO only add the location of the tab of the window who requested the
156bb2e9b06SClemens Zeidler	// settings
157bb2e9b06SClemens Zeidler	for (int32 i = 0; i < fTabList.CountItems(); i++) {
158bb2e9b06SClemens Zeidler		DefaultDecorator::Tab* tab = _TabAt(i);
159bb2e9b06SClemens Zeidler		if (settings->AddFloat("tab location", (float)tab->tabOffset) != B_OK)
160bb2e9b06SClemens Zeidler			return false;
161bb2e9b06SClemens Zeidler	}
162bb2e9b06SClemens Zeidler	return true;
163ef831a1dSPhilippe Houdoin}
164ef831a1dSPhilippe Houdoin
165b30e9021SStephan Aßmus
166ef831a1dSPhilippe Houdoin// #pragma mark -
167b30e9021SStephan Aßmus
16823e00a25SAxel Dörfler
16959345e26SStephan Aßmusvoid
170719b56b0SJohn ScipioneDefaultDecorator::Draw(BRect updateRect)
17159345e26SStephan Aßmus{
172083ec975SAxel Dörfler	STRACE(("DefaultDecorator: Draw(%.1f,%.1f,%.1f,%.1f)\n",
173719b56b0SJohn Scipione		updateRect.left, updateRect.top, updateRect.right, updateRect.bottom));
17459345e26SStephan Aßmus
175db4da598SRyan Leavengood	// We need to draw a few things: the tab, the resize knob, the borders,
17659345e26SStephan Aßmus	// and the buttons
177ea6280b6SStephan Aßmus	fDrawingEngine->SetDrawState(&fDrawState);
17859345e26SStephan Aßmus
179719b56b0SJohn Scipione	_DrawFrame(updateRect);
180719b56b0SJohn Scipione	_DrawTabs(updateRect);
18159345e26SStephan Aßmus}
18259345e26SStephan Aßmus
183e13a79e0SMichael Lotz
18459345e26SStephan Aßmusvoid
18559345e26SStephan AßmusDefaultDecorator::Draw()
18659345e26SStephan Aßmus{
18759345e26SStephan Aßmus	// Easy way to draw everything - no worries about drawing only certain
18859345e26SStephan Aßmus	// things
189ea6280b6SStephan Aßmus	fDrawingEngine->SetDrawState(&fDrawState);
19059345e26SStephan Aßmus
19159345e26SStephan Aßmus	_DrawFrame(BRect(fTopBorder.LeftTop(), fBottomBorder.RightBottom()));
192bb2e9b06SClemens Zeidler	_DrawTabs(fTitleBarRect);
19359345e26SStephan Aßmus}
19459345e26SStephan Aßmus
195e13a79e0SMichael Lotz
19659345e26SStephan Aßmusvoid
197e83820edSAxel DörflerDefaultDecorator::GetSizeLimits(int32* minWidth, int32* minHeight,
198b31df46fSAxel Dörfler	int32* maxWidth, int32* maxHeight) const
19959345e26SStephan Aßmus{
200bb2e9b06SClemens Zeidler	float minTabSize = 0;
201bb2e9b06SClemens Zeidler	if (CountTabs() > 0)
202bb2e9b06SClemens Zeidler		minTabSize = _TabAt(0)->minTabSize;
203bb2e9b06SClemens Zeidler	if (fTitleBarRect.IsValid()) {
204b31df46fSAxel Dörfler		*minWidth = (int32)roundf(max_c(*minWidth,
205bb2e9b06SClemens Zeidler			minTabSize - 2 * fBorderWidth));
206b31df46fSAxel Dörfler	}
207b31df46fSAxel Dörfler	if (fResizeRect.IsValid()) {
208b31df46fSAxel Dörfler		*minHeight = (int32)roundf(max_c(*minHeight,
209b31df46fSAxel Dörfler			fResizeRect.Height() - fBorderWidth));
210b31df46fSAxel Dörfler	}
21159345e26SStephan Aßmus}
21259345e26SStephan Aßmus
213e13a79e0SMichael Lotz
21489d652d5SIngo WeinholdDecorator::Region
215bb2e9b06SClemens ZeidlerDefaultDecorator::RegionAt(BPoint where, int32& tab) const
21659345e26SStephan Aßmus{
21789d652d5SIngo Weinhold	// Let the base class version identify hits of the buttons and the tab.
218bb2e9b06SClemens Zeidler	Region region = Decorator::RegionAt(where, tab);
21989d652d5SIngo Weinhold	if (region != REGION_NONE)
22089d652d5SIngo Weinhold		return region;
22189d652d5SIngo Weinhold
22289d652d5SIngo Weinhold	// check the resize corner
2231c141573SClemens Zeidler	if (fTopTab->look == B_DOCUMENT_WINDOW_LOOK && fResizeRect.Contains(where))
22489d652d5SIngo Weinhold		return REGION_RIGHT_BOTTOM_CORNER;
22589d652d5SIngo Weinhold
22689d652d5SIngo Weinhold	// hit-test the borders
22789d652d5SIngo Weinhold	if (fLeftBorder.Contains(where))
22889d652d5SIngo Weinhold		return REGION_LEFT_BORDER;
22989d652d5SIngo Weinhold	if (fTopBorder.Contains(where))
23089d652d5SIngo Weinhold		return REGION_TOP_BORDER;
23189d652d5SIngo Weinhold
23289d652d5SIngo Weinhold	// Part of the bottom and right borders may be a resize-region, so we have
23389d652d5SIngo Weinhold	// to check explicitly, if it has been it.
23489d652d5SIngo Weinhold	if (fRightBorder.Contains(where))
23589d652d5SIngo Weinhold		region = REGION_RIGHT_BORDER;
23689d652d5SIngo Weinhold	else if (fBottomBorder.Contains(where))
23789d652d5SIngo Weinhold		region = REGION_BOTTOM_BORDER;
23889d652d5SIngo Weinhold	else
23989d652d5SIngo Weinhold		return REGION_NONE;
24089d652d5SIngo Weinhold
24189d652d5SIngo Weinhold	// check resize area
2421c141573SClemens Zeidler	if ((fTopTab->flags & B_NOT_RESIZABLE) == 0
2431c141573SClemens Zeidler		&& (fTopTab->look == B_TITLED_WINDOW_LOOK
2441c141573SClemens Zeidler			|| fTopTab->look == B_FLOATING_WINDOW_LOOK
2451c141573SClemens Zeidler			|| fTopTab->look == B_MODAL_WINDOW_LOOK
2461c141573SClemens Zeidler			|| fTopTab->look == kLeftTitledWindowLook)) {
24789d652d5SIngo Weinhold		BRect resizeRect(BPoint(fBottomBorder.right - kBorderResizeLength,
24889d652d5SIngo Weinhold			fBottomBorder.bottom - kBorderResizeLength),
24989d652d5SIngo Weinhold			fBottomBorder.RightBottom());
25089d652d5SIngo Weinhold		if (resizeRect.Contains(where))
25189d652d5SIngo Weinhold			return REGION_RIGHT_BOTTOM_CORNER;
25214fb2b69SAxel Dörfler	}
25314fb2b69SAxel Dörfler
25489d652d5SIngo Weinhold	return region;
255ae01fc9bSDarkWyrm}
256ae01fc9bSDarkWyrm
25785f8bb71SAxel Dörfler
25837ba7e53SIngo Weinholdbool
25937ba7e53SIngo WeinholdDefaultDecorator::SetRegionHighlight(Region region, uint8 highlight,
260bb2e9b06SClemens Zeidler	BRegion* dirty, int32 tabIndex)
26137ba7e53SIngo Weinhold{
262bb2e9b06SClemens Zeidler	DefaultDecorator::Tab* tab = _TabAt(tabIndex);
263bb2e9b06SClemens Zeidler	if (tab != NULL) {
264bb2e9b06SClemens Zeidler		tab->isHighlighted = highlight != 0;
265bb2e9b06SClemens Zeidler		// Invalidate the bitmap caches for the close/zoom button, when the
266bb2e9b06SClemens Zeidler		// highlight changes.
267bb2e9b06SClemens Zeidler		switch (region) {
268bb2e9b06SClemens Zeidler			case REGION_CLOSE_BUTTON:
269bb2e9b06SClemens Zeidler				if (highlight != RegionHighlight(region))
270bb2e9b06SClemens Zeidler					memset(&tab->closeBitmaps, 0, sizeof(tab->closeBitmaps));
271bb2e9b06SClemens Zeidler				break;
272bb2e9b06SClemens Zeidler			case REGION_ZOOM_BUTTON:
273bb2e9b06SClemens Zeidler				if (highlight != RegionHighlight(region))
274bb2e9b06SClemens Zeidler					memset(&tab->zoomBitmaps, 0, sizeof(tab->zoomBitmaps));
275bb2e9b06SClemens Zeidler				break;
276bb2e9b06SClemens Zeidler			default:
277bb2e9b06SClemens Zeidler				break;
278bb2e9b06SClemens Zeidler		}
27937ba7e53SIngo Weinhold	}
28037ba7e53SIngo Weinhold
281bb2e9b06SClemens Zeidler	return Decorator::SetRegionHighlight(region, highlight, dirty, tabIndex);
28237ba7e53SIngo Weinhold}
28337ba7e53SIngo Weinhold
28437ba7e53SIngo Weinhold
2852b602c73SIngo Weinholdvoid
2862b602c73SIngo WeinholdDefaultDecorator::ExtendDirtyRegion(Region region, BRegion& dirty)
2872b602c73SIngo Weinhold{
2882b602c73SIngo Weinhold	switch (region) {
2892b602c73SIngo Weinhold		case REGION_TAB:
290bb2e9b06SClemens Zeidler			dirty.Include(fTitleBarRect);
2912b602c73SIngo Weinhold			break;
2922b602c73SIngo Weinhold
2932b602c73SIngo Weinhold		case REGION_CLOSE_BUTTON:
2941c141573SClemens Zeidler			if ((fTopTab->flags & B_NOT_CLOSABLE) == 0)
295bb2e9b06SClemens Zeidler				for (int32 i = 0; i < fTabList.CountItems(); i++)
296bb2e9b06SClemens Zeidler					dirty.Include(fTabList.ItemAt(i)->closeRect);
2972b602c73SIngo Weinhold			break;
2982b602c73SIngo Weinhold
2992b602c73SIngo Weinhold		case REGION_ZOOM_BUTTON:
3001c141573SClemens Zeidler			if ((fTopTab->flags & B_NOT_ZOOMABLE) == 0)
301bb2e9b06SClemens Zeidler				for (int32 i = 0; i < fTabList.CountItems(); i++)
302bb2e9b06SClemens Zeidler					dirty.Include(fTabList.ItemAt(i)->zoomRect);
3032b602c73SIngo Weinhold			break;
3042b602c73SIngo Weinhold
3052b602c73SIngo Weinhold		case REGION_LEFT_BORDER:
30692fe8be9SIngo Weinhold			if (fLeftBorder.IsValid()) {
30792fe8be9SIngo Weinhold				// fLeftBorder doesn't include the corners, so we have to add
30892fe8be9SIngo Weinhold				// them manually.
30992fe8be9SIngo Weinhold				BRect rect(fLeftBorder);
31092fe8be9SIngo Weinhold				rect.top = fTopBorder.top;
31192fe8be9SIngo Weinhold				rect.bottom = fBottomBorder.bottom;
31292fe8be9SIngo Weinhold				dirty.Include(rect);
31392fe8be9SIngo Weinhold			}
3142b602c73SIngo Weinhold			break;
3152b602c73SIngo Weinhold
3162b602c73SIngo Weinhold		case REGION_RIGHT_BORDER:
31792fe8be9SIngo Weinhold			if (fRightBorder.IsValid()) {
31892fe8be9SIngo Weinhold				// fRightBorder doesn't include the corners, so we have to add
31992fe8be9SIngo Weinhold				// them manually.
32092fe8be9SIngo Weinhold				BRect rect(fRightBorder);
32192fe8be9SIngo Weinhold				rect.top = fTopBorder.top;
32292fe8be9SIngo Weinhold				rect.bottom = fBottomBorder.bottom;
32392fe8be9SIngo Weinhold				dirty.Include(rect);
32492fe8be9SIngo Weinhold			}
3252b602c73SIngo Weinhold			break;
3262b602c73SIngo Weinhold
3272b602c73SIngo Weinhold		case REGION_TOP_BORDER:
3282b602c73SIngo Weinhold			dirty.Include(fTopBorder);
3292b602c73SIngo Weinhold			break;
3302b602c73SIngo Weinhold
3312b602c73SIngo Weinhold		case REGION_BOTTOM_BORDER:
3322b602c73SIngo Weinhold			dirty.Include(fBottomBorder);
3332b602c73SIngo Weinhold			break;
3342b602c73SIngo Weinhold
3352b602c73SIngo Weinhold		case REGION_RIGHT_BOTTOM_CORNER:
3361c141573SClemens Zeidler			if ((fTopTab->flags & B_NOT_RESIZABLE) == 0)
3372b602c73SIngo Weinhold				dirty.Include(fResizeRect);
3382b602c73SIngo Weinhold			break;
3392b602c73SIngo Weinhold
3402b602c73SIngo Weinhold		default:
3412b602c73SIngo Weinhold			break;
3422b602c73SIngo Weinhold	}
3432b602c73SIngo Weinhold}
3442b602c73SIngo Weinhold
3452b602c73SIngo Weinhold
346f1c707c4SClemens Zeidlerfloat
347f1c707c4SClemens ZeidlerDefaultDecorator::BorderWidth()
348f1c707c4SClemens Zeidler{
349f1c707c4SClemens Zeidler	return fBorderWidth;
350f1c707c4SClemens Zeidler}
351f1c707c4SClemens Zeidler
352f1c707c4SClemens Zeidler
353f1c707c4SClemens Zeidlerfloat
354f1c707c4SClemens ZeidlerDefaultDecorator::TabHeight()
355f1c707c4SClemens Zeidler{
356bb2e9b06SClemens Zeidler	if (fTitleBarRect.IsValid())
357bb2e9b06SClemens Zeidler		return fTitleBarRect.Height();
358f1c707c4SClemens Zeidler	return BorderWidth();
359f1c707c4SClemens Zeidler}
360f1c707c4SClemens Zeidler
361f1c707c4SClemens Zeidler
36259345e26SStephan Aßmusvoid
36359345e26SStephan AßmusDefaultDecorator::_DoLayout()
364ae01fc9bSDarkWyrm{
36537aec728SDarkWyrm	STRACE(("DefaultDecorator: Do Layout\n"));
366ae01fc9bSDarkWyrm	// Here we determine the size of every rectangle that we use
367ae01fc9bSDarkWyrm	// internally when we are given the size of the client rectangle.
368a7e4fa4cSDarkWyrm
36959345e26SStephan Aßmus	bool hasTab = false;
37059345e26SStephan Aßmus
3711c141573SClemens Zeidler	switch ((int)fTopTab->look) {
372a7e4fa4cSDarkWyrm		case B_MODAL_WINDOW_LOOK:
37359345e26SStephan Aßmus			fBorderWidth = 5;
37459345e26SStephan Aßmus			break;
37559345e26SStephan Aßmus
3762a8283e4SDarkWyrm		case B_TITLED_WINDOW_LOOK:
3772a8283e4SDarkWyrm		case B_DOCUMENT_WINDOW_LOOK:
37859345e26SStephan Aßmus			hasTab = true;
37959345e26SStephan Aßmus			fBorderWidth = 5;
38059345e26SStephan Aßmus			break;
38159345e26SStephan Aßmus		case B_FLOATING_WINDOW_LOOK:
382083ec975SAxel Dörfler		case kLeftTitledWindowLook:
38359345e26SStephan Aßmus			hasTab = true;
38459345e26SStephan Aßmus			fBorderWidth = 3;
3852a8283e4SDarkWyrm			break;
38659345e26SStephan Aßmus
38759345e26SStephan Aßmus		case B_BORDERED_WINDOW_LOOK:
38859345e26SStephan Aßmus			fBorderWidth = 1;
38959345e26SStephan Aßmus			break;
39059345e26SStephan Aßmus
3912a8283e4SDarkWyrm		default:
39259345e26SStephan Aßmus			fBorderWidth = 0;
3932a8283e4SDarkWyrm	}
394083ec975SAxel Dörfler
395bb2e9b06SClemens Zeidler	// calculate left/top/right/bottom borders
396bb2e9b06SClemens Zeidler	if (fBorderWidth > 0) {
397bb2e9b06SClemens Zeidler		// NOTE: no overlapping, the left and right border rects
398bb2e9b06SClemens Zeidler		// don't include the corners!
399bb2e9b06SClemens Zeidler		fLeftBorder.Set(fFrame.left - fBorderWidth, fFrame.top,
400bb2e9b06SClemens Zeidler			fFrame.left - 1, fFrame.bottom);
401bb2e9b06SClemens Zeidler
402bb2e9b06SClemens Zeidler		fRightBorder.Set(fFrame.right + 1, fFrame.top ,
403bb2e9b06SClemens Zeidler			fFrame.right + fBorderWidth, fFrame.bottom);
404bb2e9b06SClemens Zeidler
405bb2e9b06SClemens Zeidler		fTopBorder.Set(fFrame.left - fBorderWidth, fFrame.top - fBorderWidth,
406bb2e9b06SClemens Zeidler			fFrame.right + fBorderWidth, fFrame.top - 1);
407bb2e9b06SClemens Zeidler
408bb2e9b06SClemens Zeidler		fBottomBorder.Set(fFrame.left - fBorderWidth, fFrame.bottom + 1,
409bb2e9b06SClemens Zeidler			fFrame.right + fBorderWidth, fFrame.bottom + fBorderWidth);
410bb2e9b06SClemens Zeidler	} else {
411bb2e9b06SClemens Zeidler		// no border
412bb2e9b06SClemens Zeidler		fLeftBorder.Set(0.0, 0.0, -1.0, -1.0);
413bb2e9b06SClemens Zeidler		fRightBorder.Set(0.0, 0.0, -1.0, -1.0);
414bb2e9b06SClemens Zeidler		fTopBorder.Set(0.0, 0.0, -1.0, -1.0);
415bb2e9b06SClemens Zeidler		fBottomBorder.Set(0.0, 0.0, -1.0, -1.0);
416bb2e9b06SClemens Zeidler	}
417bb2e9b06SClemens Zeidler
418bb2e9b06SClemens Zeidler	// calculate resize rect
419bb2e9b06SClemens Zeidler	if (fBorderWidth > 1) {
420bb2e9b06SClemens Zeidler		fResizeRect.Set(fBottomBorder.right - kResizeKnobSize,
421bb2e9b06SClemens Zeidler			fBottomBorder.bottom - kResizeKnobSize, fBottomBorder.right,
422bb2e9b06SClemens Zeidler			fBottomBorder.bottom);
423bb2e9b06SClemens Zeidler	} else {
424bb2e9b06SClemens Zeidler		// no border or one pixel border (menus and such)
425bb2e9b06SClemens Zeidler		fResizeRect.Set(0, 0, -1, -1);
426bb2e9b06SClemens Zeidler	}
427bb2e9b06SClemens Zeidler
42859345e26SStephan Aßmus	if (hasTab) {
429bb2e9b06SClemens Zeidler		_DoTabLayout();
430bb2e9b06SClemens Zeidler		return;
431bb2e9b06SClemens Zeidler	} else {
432bb2e9b06SClemens Zeidler		// no tab
433c732cb56SClemens Zeidler		for (int32 i = 0; i < fTabList.CountItems(); i++) {
434c732cb56SClemens Zeidler			Decorator::Tab* tab = fTabList.ItemAt(i);
435c732cb56SClemens Zeidler			tab->tabRect.Set(0.0, 0.0, -1.0, -1.0);
436c732cb56SClemens Zeidler		}
437c732cb56SClemens Zeidler		fTabsRegion.MakeEmpty();
438bb2e9b06SClemens Zeidler		fTitleBarRect.Set(0.0, 0.0, -1.0, -1.0);
439bb2e9b06SClemens Zeidler	}
440bb2e9b06SClemens Zeidler}
441bb2e9b06SClemens Zeidler
442bb2e9b06SClemens Zeidler
443bb2e9b06SClemens Zeidlervoid
444bb2e9b06SClemens ZeidlerDefaultDecorator::_DoTabLayout()
445bb2e9b06SClemens Zeidler{
446e089170aSClemens Zeidler	float tabOffset = 0;
447e089170aSClemens Zeidler	if (fTabList.CountItems() == 1) {
448e089170aSClemens Zeidler		float tabSize;
449e089170aSClemens Zeidler		tabOffset = _SingleTabOffsetAndSize(tabSize);
450e089170aSClemens Zeidler	}
451e089170aSClemens Zeidler
452bb2e9b06SClemens Zeidler	float sumTabWidth = 0;
453bb2e9b06SClemens Zeidler	// calculate our tab rect
454bb2e9b06SClemens Zeidler	for (int32 i = 0; i < fTabList.CountItems(); i++) {
455bb2e9b06SClemens Zeidler		DefaultDecorator::Tab* tab = _TabAt(i);
456bb2e9b06SClemens Zeidler
457bb2e9b06SClemens Zeidler		BRect& tabRect = tab->tabRect;
45859345e26SStephan Aßmus		// distance from one item of the tab bar to another.
45959345e26SStephan Aßmus		// In this case the text and close/zoom rects
460bb2e9b06SClemens Zeidler		tab->textOffset = _DefaultTextOffset();
461e60b1ff1SAxel Dörfler
4628365d9ecSAxel Dörfler		font_height fontHeight;
463aca4f50dSAxel Dörfler		fDrawState.Font().GetHeight(fontHeight);
46459345e26SStephan Aßmus
4651c141573SClemens Zeidler		if (tab->look != kLeftTitledWindowLook) {
466bb2e9b06SClemens Zeidler			tabRect.Set(fFrame.left - fBorderWidth,
467f7e1df75SStephan Aßmus				fFrame.top - fBorderWidth
468f7e1df75SStephan Aßmus					- ceilf(fontHeight.ascent + fontHeight.descent + 7.0),
4692cfe93e7SStephan Aßmus				((fFrame.right - fFrame.left) < 35.0 ?
4702cfe93e7SStephan Aßmus					fFrame.left + 35.0 : fFrame.right) + fBorderWidth,
4712cfe93e7SStephan Aßmus				fFrame.top - fBorderWidth);
472083ec975SAxel Dörfler		} else {
473bb2e9b06SClemens Zeidler			tabRect.Set(fFrame.left - fBorderWidth
474f7e1df75SStephan Aßmus				- ceilf(fontHeight.ascent + fontHeight.descent + 5.0),
475f7e1df75SStephan Aßmus					fFrame.top - fBorderWidth, fFrame.left - fBorderWidth,
4762cfe93e7SStephan Aßmus				fFrame.bottom + fBorderWidth);
477083ec975SAxel Dörfler		}
47859345e26SStephan Aßmus
47959345e26SStephan Aßmus		// format tab rect for a floating window - make the rect smaller
4801c141573SClemens Zeidler		if (tab->look == B_FLOATING_WINDOW_LOOK) {
481bb2e9b06SClemens Zeidler			tabRect.InsetBy(0, 2);
482bb2e9b06SClemens Zeidler			tabRect.OffsetBy(0, 2);
48359345e26SStephan Aßmus		}
48459345e26SStephan Aßmus
48559345e26SStephan Aßmus		float offset;
48659345e26SStephan Aßmus		float size;
487f7e1df75SStephan Aßmus		float inset;
488bb2e9b06SClemens Zeidler		_GetButtonSizeAndOffset(tabRect, &offset, &size, &inset);
48959345e26SStephan Aßmus
490bb2e9b06SClemens Zeidler		// tab->minTabSize contains just the room for the buttons
491bb2e9b06SClemens Zeidler		tab->minTabSize = inset * 2 + tab->textOffset;
4921c141573SClemens Zeidler		if ((tab->flags & B_NOT_CLOSABLE) == 0)
493bb2e9b06SClemens Zeidler			tab->minTabSize += offset + size;
4941c141573SClemens Zeidler		if ((tab->flags & B_NOT_ZOOMABLE) == 0)
495bb2e9b06SClemens Zeidler			tab->minTabSize += offset + size;
496083ec975SAxel Dörfler
497bb2e9b06SClemens Zeidler		// tab->maxTabSize contains tab->minTabSize + the width required for the
498bb2e9b06SClemens Zeidler		// title
499bb2e9b06SClemens Zeidler		tab->maxTabSize = fDrawingEngine
500bb2e9b06SClemens Zeidler			? ceilf(fDrawingEngine->StringWidth(Title(tab), strlen(Title(tab)),
50138287e02SStephan Aßmus				fDrawState.Font())) : 0.0;
502bb2e9b06SClemens Zeidler		if (tab->maxTabSize > 0.0)
503bb2e9b06SClemens Zeidler			tab->maxTabSize += tab->textOffset;
504bb2e9b06SClemens Zeidler		tab->maxTabSize += tab->minTabSize;
505083ec975SAxel Dörfler
5061c141573SClemens Zeidler		float tabSize = (tab->look != kLeftTitledWindowLook
507a0d69d7dSMichael Lotz			? fFrame.Width() : fFrame.Height()) + fBorderWidth * 2;
508bb2e9b06SClemens Zeidler		if (tabSize < tab->minTabSize)
509bb2e9b06SClemens Zeidler			tabSize = tab->minTabSize;
510bb2e9b06SClemens Zeidler		if (tabSize > tab->maxTabSize)
511bb2e9b06SClemens Zeidler			tabSize = tab->maxTabSize;
51259345e26SStephan Aßmus
51359345e26SStephan Aßmus		// layout buttons and truncate text
5141c141573SClemens Zeidler		if (tab->look != kLeftTitledWindowLook)
515bb2e9b06SClemens Zeidler			tabRect.right = tabRect.left + tabSize;
516083ec975SAxel Dörfler		else
517bb2e9b06SClemens Zeidler			tabRect.bottom = tabRect.top + tabSize;
518bb2e9b06SClemens Zeidler
519bb2e9b06SClemens Zeidler		// make sure fTabOffset is within limits and apply it to
520bb2e9b06SClemens Zeidler		// the tabRect
521e089170aSClemens Zeidler		tab->tabOffset = (uint32)tabOffset;
522e089170aSClemens Zeidler		if (tab->tabLocation != 0.0 && fTabList.CountItems() == 1
523bb2e9b06SClemens Zeidler			&& tab->tabOffset > (fRightBorder.right - fLeftBorder.left
524bb2e9b06SClemens Zeidler				- tabRect.Width())) {
525bb2e9b06SClemens Zeidler			tab->tabOffset = uint32(fRightBorder.right - fLeftBorder.left
526bb2e9b06SClemens Zeidler				- tabRect.Width());
527bb2e9b06SClemens Zeidler		}
528bb2e9b06SClemens Zeidler		tabRect.OffsetBy(tab->tabOffset, 0);
529e089170aSClemens Zeidler		tabOffset += tabRect.Width();
530bb2e9b06SClemens Zeidler
531bb2e9b06SClemens Zeidler		sumTabWidth += tabRect.Width();
5327641924eSAdi Oanca	}
5337641924eSAdi Oanca
534bb2e9b06SClemens Zeidler	float windowWidth = fFrame.Width() + 2 * fBorderWidth;
535bb2e9b06SClemens Zeidler	if (CountTabs() > 1 && sumTabWidth > windowWidth)
536bb2e9b06SClemens Zeidler		_DistributeTabSize(sumTabWidth - windowWidth);
5377641924eSAdi Oanca
538bb2e9b06SClemens Zeidler	// finally, layout the buttons and text within the tab rect
539bb2e9b06SClemens Zeidler	for (int32 i = 0; i < fTabList.CountItems(); i++) {
540bb2e9b06SClemens Zeidler		Decorator::Tab* tab = fTabList.ItemAt(i);
5417641924eSAdi Oanca
542bb2e9b06SClemens Zeidler		if (i == 0)
543bb2e9b06SClemens Zeidler			fTitleBarRect = tab->tabRect;
544bb2e9b06SClemens Zeidler		else
545bb2e9b06SClemens Zeidler			fTitleBarRect = fTitleBarRect | tab->tabRect;
5467641924eSAdi Oanca
547bb2e9b06SClemens Zeidler		_LayoutTabItems(tab, tab->tabRect);
5487641924eSAdi Oanca	}
549bb2e9b06SClemens Zeidler	fTabsRegion = fTitleBarRect;
550bb2e9b06SClemens Zeidler}
551ae01fc9bSDarkWyrm
552bb2e9b06SClemens Zeidler
553bb2e9b06SClemens Zeidlerstatic bool
554bb2e9b06SClemens Zeidlerint_equal(float x, float y)
555bb2e9b06SClemens Zeidler{
556bb2e9b06SClemens Zeidler	return abs(x - y) <= 1;
557bb2e9b06SClemens Zeidler}
558bb2e9b06SClemens Zeidler
559bb2e9b06SClemens Zeidler
560bb2e9b06SClemens Zeidlervoid
561bb2e9b06SClemens ZeidlerDefaultDecorator::_DistributeTabSize(float delta)
562bb2e9b06SClemens Zeidler{
563bb2e9b06SClemens Zeidler	ASSERT(CountTabs() > 1);
564bb2e9b06SClemens Zeidler
565bb2e9b06SClemens Zeidler	float maxTabSize = 0;
566bb2e9b06SClemens Zeidler	float secMaxTabSize = 0;
567bb2e9b06SClemens Zeidler	int32 nTabsWithMaxSize = 0;
568bb2e9b06SClemens Zeidler	for (int32 i = 0; i < fTabList.CountItems(); i++) {
569bb2e9b06SClemens Zeidler		Decorator::Tab* tab = fTabList.ItemAt(i);
570bb2e9b06SClemens Zeidler		float tabWidth = tab->tabRect.Width();
571bb2e9b06SClemens Zeidler		if (int_equal(maxTabSize, tabWidth)) {
572bb2e9b06SClemens Zeidler			nTabsWithMaxSize++;
573bb2e9b06SClemens Zeidler			continue;
574bb2e9b06SClemens Zeidler		}
575bb2e9b06SClemens Zeidler		if (maxTabSize < tabWidth) {
576bb2e9b06SClemens Zeidler			secMaxTabSize = maxTabSize;
577bb2e9b06SClemens Zeidler			maxTabSize = tabWidth;
578bb2e9b06SClemens Zeidler			nTabsWithMaxSize = 1;
579bb2e9b06SClemens Zeidler		} else if (secMaxTabSize <= tabWidth)
580bb2e9b06SClemens Zeidler			secMaxTabSize = tabWidth;
581a21cfee7SStephan Aßmus	}
582d35ed1a6SStephan Aßmus
583bb2e9b06SClemens Zeidler	float minus = ceil(std::min(maxTabSize - secMaxTabSize, delta));
584bb2e9b06SClemens Zeidler	delta -= minus;
585bb2e9b06SClemens Zeidler	minus /= nTabsWithMaxSize;
586bb2e9b06SClemens Zeidler
587bb2e9b06SClemens Zeidler	Decorator::Tab* prevTab = NULL;
588bb2e9b06SClemens Zeidler	for (int32 i = 0; i < fTabList.CountItems(); i++) {
589bb2e9b06SClemens Zeidler		Decorator::Tab* tab = fTabList.ItemAt(i);
590bb2e9b06SClemens Zeidler		if (int_equal(maxTabSize, tab->tabRect.Width()))
591bb2e9b06SClemens Zeidler			tab->tabRect.right -= minus;
592bb2e9b06SClemens Zeidler
593bb2e9b06SClemens Zeidler		if (prevTab) {
594bb2e9b06SClemens Zeidler			tab->tabRect.OffsetBy(prevTab->tabRect.right - tab->tabRect.left,
595bb2e9b06SClemens Zeidler				0);
596bb2e9b06SClemens Zeidler		}
597bb2e9b06SClemens Zeidler
598bb2e9b06SClemens Zeidler		prevTab = tab;
599bb2e9b06SClemens Zeidler	}
600bb2e9b06SClemens Zeidler
601bb2e9b06SClemens Zeidler	if (delta > 0) {
602bb2e9b06SClemens Zeidler		_DistributeTabSize(delta);
603bb2e9b06SClemens Zeidler		return;
604bb2e9b06SClemens Zeidler	}
605bb2e9b06SClemens Zeidler
606bb2e9b06SClemens Zeidler	// done
607bb2e9b06SClemens Zeidler	prevTab->tabRect.right = floor(fFrame.right + fBorderWidth);
608bb2e9b06SClemens Zeidler
609bb2e9b06SClemens Zeidler	for (int32 i = 0; i < fTabList.CountItems(); i++) {
610bb2e9b06SClemens Zeidler		DefaultDecorator::Tab* tab = _TabAt(i);
611bb2e9b06SClemens Zeidler		tab->tabOffset = uint32(tab->tabRect.left - fLeftBorder.left);
612d35ed1a6SStephan Aßmus	}
613ae01fc9bSDarkWyrm}
614ae01fc9bSDarkWyrm
615e13a79e0SMichael Lotz
616bb2e9b06SClemens ZeidlerDecorator::Tab*
617bb2e9b06SClemens ZeidlerDefaultDecorator::_AllocateNewTab()
618bb2e9b06SClemens Zeidler{
619bb2e9b06SClemens Zeidler	Decorator::Tab* tab = new(std::nothrow) DefaultDecorator::Tab;
620bb2e9b06SClemens Zeidler	if (tab == NULL)
621bb2e9b06SClemens Zeidler		return NULL;
622bb2e9b06SClemens Zeidler	// Set appropriate colors based on the current focus value. In this case,
623bb2e9b06SClemens Zeidler	// each decorator defaults to not having the focus.
624bb2e9b06SClemens Zeidler	_SetFocus(tab);
625bb2e9b06SClemens Zeidler	return tab;
626bb2e9b06SClemens Zeidler}
627bb2e9b06SClemens Zeidler
628bb2e9b06SClemens Zeidler
629bb2e9b06SClemens ZeidlerDefaultDecorator::Tab*
630bb2e9b06SClemens ZeidlerDefaultDecorator::_TabAt(int32 index) const
631bb2e9b06SClemens Zeidler{
632bb2e9b06SClemens Zeidler	return static_cast<DefaultDecorator::Tab*>(fTabList.ItemAt(index));
633bb2e9b06SClemens Zeidler}
634bb2e9b06SClemens Zeidler
635bb2e9b06SClemens Zeidler
63659345e26SStephan Aßmusvoid
63759345e26SStephan AßmusDefaultDecorator::_DrawFrame(BRect invalid)
638ae01fc9bSDarkWyrm{
6390480cf1aSAxel Dörfler	STRACE(("_DrawFrame(%f,%f,%f,%f)\n", invalid.left, invalid.top,
6400480cf1aSAxel Dörfler		invalid.right, invalid.bottom));
641ae01fc9bSDarkWyrm
642e067fed5SStephan Aßmus	// NOTE: the DrawingEngine needs to be locked for the entire
643e067fed5SStephan Aßmus	// time for the clipping to stay valid for this decorator
64456f043edSAdi Oanca
6451c141573SClemens Zeidler	if (fTopTab->look == B_NO_BORDER_WINDOW_LOOK)
64659345e26SStephan Aßmus		return;
64756f043edSAdi Oanca
64859345e26SStephan Aßmus	if (fBorderWidth <= 0)
64959345e26SStephan Aßmus		return;
65056f043edSAdi Oanca
65159345e26SStephan Aßmus	// Draw the border frame
65259345e26SStephan Aßmus	BRect r = BRect(fTopBorder.LeftTop(), fBottomBorder.RightBottom());
6531c141573SClemens Zeidler	switch ((int)fTopTab->look) {
65459345e26SStephan Aßmus		case B_TITLED_WINDOW_LOOK:
65559345e26SStephan Aßmus		case B_DOCUMENT_WINDOW_LOOK:
656083ec975SAxel Dörfler		case B_MODAL_WINDOW_LOOK:
657083ec975SAxel Dörfler		{
658083ec975SAxel Dörfler			// top
659e067fed5SStephan Aßmus			if (invalid.Intersects(fTopBorder)) {
660e3ab8648SIngo Weinhold				ComponentColors colors;
66130d17caaSJohn Scipione				_GetComponentColors(COMPONENT_TOP_BORDER, colors, fTopTab);
662e3ab8648SIngo Weinhold
663e067fed5SStephan Aßmus				for (int8 i = 0; i < 5; i++) {
6642cfe93e7SStephan Aßmus					fDrawingEngine->StrokeLine(BPoint(r.left + i, r.top + i),
665e3ab8648SIngo Weinhold						BPoint(r.right - i, r.top + i), colors[i]);
666e067fed5SStephan Aßmus				}
667bb2e9b06SClemens Zeidler				if (fTitleBarRect.IsValid()) {
668f7e1df75SStephan Aßmus					// grey along the bottom of the tab
669f7e1df75SStephan Aßmus					// (overwrites "white" from frame)
670f7e1df75SStephan Aßmus					fDrawingEngine->StrokeLine(
671bb2e9b06SClemens Zeidler						BPoint(fTitleBarRect.left + 2,
672bb2e9b06SClemens Zeidler							fTitleBarRect.bottom + 1),
673bb2e9b06SClemens Zeidler						BPoint(fTitleBarRect.right - 2,
674bb2e9b06SClemens Zeidler							fTitleBarRect.bottom + 1),
675e3ab8648SIngo Weinhold						colors[2]);
67621625cdcSStephan Aßmus				}
67759345e26SStephan Aßmus			}
678083ec975SAxel Dörfler			// left
67921625cdcSStephan Aßmus			if (invalid.Intersects(fLeftBorder.InsetByCopy(0, -fBorderWidth))) {
680e3ab8648SIngo Weinhold				ComponentColors colors;
68130d17caaSJohn Scipione				_GetComponentColors(COMPONENT_LEFT_BORDER, colors, fTopTab);
682e3ab8648SIngo Weinhold
683e067fed5SStephan Aßmus				for (int8 i = 0; i < 5; i++) {
6842cfe93e7SStephan Aßmus					fDrawingEngine->StrokeLine(BPoint(r.left + i, r.top + i),
685e3ab8648SIngo Weinhold						BPoint(r.left + i, r.bottom - i), colors[i]);
686e067fed5SStephan Aßmus				}
68759345e26SStephan Aßmus			}
688083ec975SAxel Dörfler			// bottom
689e067fed5SStephan Aßmus			if (invalid.Intersects(fBottomBorder)) {
690e3ab8648SIngo Weinhold				ComponentColors colors;
69130d17caaSJohn Scipione				_GetComponentColors(COMPONENT_BOTTOM_BORDER, colors, fTopTab);
692e3ab8648SIngo Weinhold
693e067fed5SStephan Aßmus				for (int8 i = 0; i < 5; i++) {
6942cfe93e7SStephan Aßmus					fDrawingEngine->StrokeLine(BPoint(r.left + i, r.bottom - i),
695f7e1df75SStephan Aßmus						BPoint(r.right - i, r.bottom - i),
696e3ab8648SIngo Weinhold						colors[(4 - i) == 4 ? 5 : (4 - i)]);
697e067fed5SStephan Aßmus				}
69859345e26SStephan Aßmus			}
699083ec975SAxel Dörfler			// right
70021625cdcSStephan Aßmus			if (invalid.Intersects(fRightBorder.InsetByCopy(0, -fBorderWidth))) {
701e3ab8648SIngo Weinhold				ComponentColors colors;
70230d17caaSJohn Scipione				_GetComponentColors(COMPONENT_RIGHT_BORDER, colors, fTopTab);
703e3ab8648SIngo Weinhold
704e067fed5SStephan Aßmus				for (int8 i = 0; i < 5; i++) {
7052cfe93e7SStephan Aßmus					fDrawingEngine->StrokeLine(BPoint(r.right - i, r.top + i),
706f7e1df75SStephan Aßmus						BPoint(r.right - i, r.bottom - i),
707e3ab8648SIngo Weinhold						colors[(4 - i) == 4 ? 5 : (4 - i)]);
708e067fed5SStephan Aßmus				}
70959345e26SStephan Aßmus			}
71059345e26SStephan Aßmus			break;
71159345e26SStephan Aßmus		}
7123ba76c14SMichael Lotz
713083ec975SAxel Dörfler		case B_FLOATING_WINDOW_LOOK:
714083ec975SAxel Dörfler		case kLeftTitledWindowLook:
715083ec975SAxel Dörfler		{
716083ec975SAxel Dörfler			// top
717e067fed5SStephan Aßmus			if (invalid.Intersects(fTopBorder)) {
718e3ab8648SIngo Weinhold				ComponentColors colors;
71930d17caaSJohn Scipione				_GetComponentColors(COMPONENT_TOP_BORDER, colors, fTopTab);
720e3ab8648SIngo Weinhold
721e067fed5SStephan Aßmus				for (int8 i = 0; i < 3; i++) {
7222cfe93e7SStephan Aßmus					fDrawingEngine->StrokeLine(BPoint(r.left + i, r.top + i),
723e3ab8648SIngo Weinhold						BPoint(r.right - i, r.top + i), colors[i * 2]);
724e067fed5SStephan Aßmus				}
72545b17fdeSJohn Scipione				if (fTitleBarRect.IsValid() && fTopTab->look != kLeftTitledWindowLook) {
726f7e1df75SStephan Aßmus					// grey along the bottom of the tab
727f7e1df75SStephan Aßmus					// (overwrites "white" from frame)
728f7e1df75SStephan Aßmus					fDrawingEngine->StrokeLine(
729bb2e9b06SClemens Zeidler						BPoint(fTitleBarRect.left + 2,
730bb2e9b06SClemens Zeidler							fTitleBarRect.bottom + 1),
731bb2e9b06SClemens Zeidler						BPoint(fTitleBarRect.right - 2,
732bb2e9b06SClemens Zeidler							fTitleBarRect.bottom + 1), colors[2]);
73321625cdcSStephan Aßmus				}
73459345e26SStephan Aßmus			}
735083ec975SAxel Dörfler			// left
73621625cdcSStephan Aßmus			if (invalid.Intersects(fLeftBorder.InsetByCopy(0, -fBorderWidth))) {
737e3ab8648SIngo Weinhold				ComponentColors colors;
73830d17caaSJohn Scipione				_GetComponentColors(COMPONENT_LEFT_BORDER, colors, fTopTab);
739e3ab8648SIngo Weinhold
740e067fed5SStephan Aßmus				for (int8 i = 0; i < 3; i++) {
7412cfe93e7SStephan Aßmus					fDrawingEngine->StrokeLine(BPoint(r.left + i, r.top + i),
742e3ab8648SIngo Weinhold						BPoint(r.left + i, r.bottom - i), colors[i * 2]);
743e067fed5SStephan Aßmus				}
7441c141573SClemens Zeidler				if (fTopTab->look == kLeftTitledWindowLook
7451c141573SClemens Zeidler					&& fTitleBarRect.IsValid()) {
746f7e1df75SStephan Aßmus					// grey along the right side of the tab
747f7e1df75SStephan Aßmus					// (overwrites "white" from frame)
748f7e1df75SStephan Aßmus					fDrawingEngine->StrokeLine(
749bb2e9b06SClemens Zeidler						BPoint(fTitleBarRect.right + 1,
750bb2e9b06SClemens Zeidler							fTitleBarRect.top + 2),
751bb2e9b06SClemens Zeidler						BPoint(fTitleBarRect.right + 1,
752bb2e9b06SClemens Zeidler							fTitleBarRect.bottom - 2), colors[2]);
753083ec975SAxel Dörfler				}
75459345e26SStephan Aßmus			}
755083ec975SAxel Dörfler			// bottom
756e067fed5SStephan Aßmus			if (invalid.Intersects(fBottomBorder)) {
757e3ab8648SIngo Weinhold				ComponentColors colors;
75830d17caaSJohn Scipione				_GetComponentColors(COMPONENT_BOTTOM_BORDER, colors, fTopTab);
759e3ab8648SIngo Weinhold
760e067fed5SStephan Aßmus				for (int8 i = 0; i < 3; i++) {
7612cfe93e7SStephan Aßmus					fDrawingEngine->StrokeLine(BPoint(r.left + i, r.bottom - i),
762f7e1df75SStephan Aßmus						BPoint(r.right - i, r.bottom - i),
763e3ab8648SIngo Weinhold						colors[(2 - i) == 2 ? 5 : (2 - i) * 2]);
764e067fed5SStephan Aßmus				}
76559345e26SStephan Aßmus			}
766083ec975SAxel Dörfler			// right
76721625cdcSStephan Aßmus			if (invalid.Intersects(fRightBorder.InsetByCopy(0, -fBorderWidth))) {
768e3ab8648SIngo Weinhold				ComponentColors colors;
76930d17caaSJohn Scipione				_GetComponentColors(COMPONENT_RIGHT_BORDER, colors, fTopTab);
770e3ab8648SIngo Weinhold
771e067fed5SStephan Aßmus				for (int8 i = 0; i < 3; i++) {
7722cfe93e7SStephan Aßmus					fDrawingEngine->StrokeLine(BPoint(r.right - i, r.top + i),
773f7e1df75SStephan Aßmus						BPoint(r.right - i, r.bottom - i),
774e3ab8648SIngo Weinhold						colors[(2 - i) == 2 ? 5 : (2 - i) * 2]);
775e067fed5SStephan Aßmus				}
77659345e26SStephan Aßmus			}
77759345e26SStephan Aßmus			break;
77859345e26SStephan Aßmus		}
779083ec975SAxel Dörfler
780083ec975SAxel Dörfler		case B_BORDERED_WINDOW_LOOK:
781e3ab8648SIngo Weinhold		{
782e3ab8648SIngo Weinhold			// TODO: Draw the borders individually!
783e3ab8648SIngo Weinhold			ComponentColors colors;
78430d17caaSJohn Scipione			_GetComponentColors(COMPONENT_LEFT_BORDER, colors, fTopTab);
785e3ab8648SIngo Weinhold
786e3ab8648SIngo Weinhold			fDrawingEngine->StrokeRect(r, colors[5]);
78759345e26SStephan Aßmus			break;
788e3ab8648SIngo Weinhold		}
78959345e26SStephan Aßmus
79059345e26SStephan Aßmus		default:
79159345e26SStephan Aßmus			// don't draw a border frame
79259345e26SStephan Aßmus			break;
79359345e26SStephan Aßmus	}
79459345e26SStephan Aßmus
795db4da598SRyan Leavengood	// Draw the resize knob if we're supposed to
7961c141573SClemens Zeidler	if (!(fTopTab->flags & B_NOT_RESIZABLE)) {
7972cfe93e7SStephan Aßmus		r = fResizeRect;
79859345e26SStephan Aßmus
799e3ab8648SIngo Weinhold		ComponentColors colors;
80030d17caaSJohn Scipione		_GetComponentColors(COMPONENT_RESIZE_CORNER, colors, fTopTab);
801e3ab8648SIngo Weinhold
8021c141573SClemens Zeidler		switch ((int)fTopTab->look) {
803083ec975SAxel Dörfler			case B_DOCUMENT_WINDOW_LOOK:
804083ec975SAxel Dörfler			{
80543307330SStephan Aßmus				if (!invalid.Intersects(r))
80643307330SStephan Aßmus					break;
80743307330SStephan Aßmus
808e83820edSAxel Dörfler				float x = r.right - 3;
809e83820edSAxel Dörfler				float y = r.bottom - 3;
810e067fed5SStephan Aßmus
811ce5d6472SStephan Aßmus				BRect bg(x - 13, y - 13, x, y);
812ce5d6472SStephan Aßmus
813ce5d6472SStephan Aßmus				BGradientLinear gradient;
814ce5d6472SStephan Aßmus				gradient.SetStart(bg.LeftTop());
815ce5d6472SStephan Aßmus				gradient.SetEnd(bg.RightBottom());
816e3ab8648SIngo Weinhold				gradient.AddColor(colors[1], 0);
817e3ab8648SIngo Weinhold				gradient.AddColor(colors[2], 255);
818dacf06e6SAxel Dörfler
819ce5d6472SStephan Aßmus				fDrawingEngine->FillRect(bg, gradient);
820ce5d6472SStephan Aßmus
821f7e1df75SStephan Aßmus				fDrawingEngine->StrokeLine(BPoint(x - 15, y - 15),
822e3ab8648SIngo Weinhold					BPoint(x - 15, y - 2), colors[0]);
823f7e1df75SStephan Aßmus				fDrawingEngine->StrokeLine(BPoint(x - 14, y - 14),
824e3ab8648SIngo Weinhold					BPoint(x - 14, y - 1), colors[1]);
825f7e1df75SStephan Aßmus				fDrawingEngine->StrokeLine(BPoint(x - 15, y - 15),
826e3ab8648SIngo Weinhold					BPoint(x - 2, y - 15), colors[0]);
827f7e1df75SStephan Aßmus				fDrawingEngine->StrokeLine(BPoint(x - 14, y - 14),
828e3ab8648SIngo Weinhold					BPoint(x - 1, y - 14), colors[1]);
82959345e26SStephan Aßmus
830bb2e9b06SClemens Zeidler				if (fTopTab && !IsFocus(fTopTab))
83143307330SStephan Aßmus					break;
83243307330SStephan Aßmus
833ce5d6472SStephan Aßmus				static const rgb_color kWhite
834ce5d6472SStephan Aßmus					= (rgb_color){ 255, 255, 255, 255 };
83559345e26SStephan Aßmus				for (int8 i = 1; i <= 4; i++) {
83659345e26SStephan Aßmus					for (int8 j = 1; j <= i; j++) {
837f7e1df75SStephan Aßmus						BPoint pt1(x - (3 * j) + 1, y - (3 * (5 - i)) + 1);
838f7e1df75SStephan Aßmus						BPoint pt2(x - (3 * j) + 2, y - (3 * (5 - i)) + 2);
839e3ab8648SIngo Weinhold						fDrawingEngine->StrokePoint(pt1, colors[0]);
840ce5d6472SStephan Aßmus						fDrawingEngine->StrokePoint(pt2, kWhite);
84159345e26SStephan Aßmus					}
84259345e26SStephan Aßmus				}
84359345e26SStephan Aßmus				break;
84459345e26SStephan Aßmus			}
84559345e26SStephan Aßmus
84659345e26SStephan Aßmus			case B_TITLED_WINDOW_LOOK:
84759345e26SStephan Aßmus			case B_FLOATING_WINDOW_LOOK:
848083ec975SAxel Dörfler			case B_MODAL_WINDOW_LOOK:
849083ec975SAxel Dörfler			case kLeftTitledWindowLook:
850083ec975SAxel Dörfler			{
851db4da598SRyan Leavengood				if (!invalid.Intersects(BRect(fRightBorder.right - kBorderResizeLength,
852db4da598SRyan Leavengood					fBottomBorder.bottom - kBorderResizeLength, fRightBorder.right - 1,
853f7e1df75SStephan Aßmus					fBottomBorder.bottom - 1)))
854e067fed5SStephan Aßmus					break;
8553ba76c14SMichael Lotz
856f7e1df75SStephan Aßmus				fDrawingEngine->StrokeLine(
857db4da598SRyan Leavengood					BPoint(fRightBorder.left, fBottomBorder.bottom - kBorderResizeLength),
858db4da598SRyan Leavengood					BPoint(fRightBorder.right - 1, fBottomBorder.bottom - kBorderResizeLength),
859e3ab8648SIngo Weinhold					colors[0]);
860f7e1df75SStephan Aßmus				fDrawingEngine->StrokeLine(
861db4da598SRyan Leavengood					BPoint(fRightBorder.right - kBorderResizeLength, fBottomBorder.top),
862db4da598SRyan Leavengood					BPoint(fRightBorder.right - kBorderResizeLength, fBottomBorder.bottom - 1),
863e3ab8648SIngo Weinhold					colors[0]);
86459345e26SStephan Aßmus				break;
86559345e26SStephan Aßmus			}
866e83820edSAxel Dörfler
867083ec975SAxel Dörfler			default:
86859345e26SStephan Aßmus				// don't draw resize corner
86959345e26SStephan Aßmus				break;
87059345e26SStephan Aßmus		}
87159345e26SStephan Aßmus	}
87256f043edSAdi Oanca}
87356f043edSAdi Oanca
874e13a79e0SMichael Lotz
87559345e26SStephan Aßmusvoid
876bb2e9b06SClemens ZeidlerDefaultDecorator::_DrawTab(Decorator::Tab* tab, BRect invalid)
877ae01fc9bSDarkWyrm{
878e067fed5SStephan Aßmus	STRACE(("_DrawTab(%.1f,%.1f,%.1f,%.1f)\n",
879bb2e9b06SClemens Zeidler		invalid.left, invalid.top, invalid.right, invalid.bottom));
880bb2e9b06SClemens Zeidler	const BRect& tabRect = tab->tabRect;
88159345e26SStephan Aßmus	// If a window has a tab, this will draw it and any buttons which are
88259345e26SStephan Aßmus	// in it.
883bb2e9b06SClemens Zeidler	if (!tabRect.IsValid() || !invalid.Intersects(tabRect))
8843231b95eSDarkWyrm		return;
88547007fb0SAdi Oanca
886e3ab8648SIngo Weinhold	ComponentColors colors;
887bb2e9b06SClemens Zeidler	_GetComponentColors(COMPONENT_TAB, colors, tab);
888e3ab8648SIngo Weinhold
88959345e26SStephan Aßmus	// outer frame
890bb2e9b06SClemens Zeidler	fDrawingEngine->StrokeLine(tabRect.LeftTop(), tabRect.LeftBottom(),
891e3ab8648SIngo Weinhold		colors[COLOR_TAB_FRAME_LIGHT]);
892bb2e9b06SClemens Zeidler	fDrawingEngine->StrokeLine(tabRect.LeftTop(), tabRect.RightTop(),
893e3ab8648SIngo Weinhold		colors[COLOR_TAB_FRAME_LIGHT]);
8941c141573SClemens Zeidler	if (tab->look != kLeftTitledWindowLook) {
895bb2e9b06SClemens Zeidler		fDrawingEngine->StrokeLine(tabRect.RightTop(), tabRect.RightBottom(),
896e3ab8648SIngo Weinhold			colors[COLOR_TAB_FRAME_DARK]);
897f7e1df75SStephan Aßmus	} else {
898bb2e9b06SClemens Zeidler		fDrawingEngine->StrokeLine(tabRect.LeftBottom(),
899bb2e9b06SClemens Zeidler			tabRect.RightBottom(), colors[COLOR_TAB_FRAME_DARK]);
900f7e1df75SStephan Aßmus	}
90116108979SAdi Oanca
902bb2e9b06SClemens Zeidler	float tabBotton = tabRect.bottom;
903bb2e9b06SClemens Zeidler	if (fTopTab != tab)
904bb2e9b06SClemens Zeidler		tabBotton -= 1;
905bb2e9b06SClemens Zeidler
90659345e26SStephan Aßmus	// bevel
907bb2e9b06SClemens Zeidler	fDrawingEngine->StrokeLine(BPoint(tabRect.left + 1, tabRect.top + 1),
908bb2e9b06SClemens Zeidler		BPoint(tabRect.left + 1,
9091c141573SClemens Zeidler			tabBotton - (tab->look == kLeftTitledWindowLook ? 1 : 0)),
910e3ab8648SIngo Weinhold		colors[COLOR_TAB_BEVEL]);
911bb2e9b06SClemens Zeidler	fDrawingEngine->StrokeLine(BPoint(tabRect.left + 1, tabRect.top + 1),
9121c141573SClemens Zeidler		BPoint(tabRect.right - (tab->look == kLeftTitledWindowLook ? 0 : 1),
913bb2e9b06SClemens Zeidler			tabRect.top + 1),
914e3ab8648SIngo Weinhold		colors[COLOR_TAB_BEVEL]);
91516108979SAdi Oanca
9161c141573SClemens Zeidler	if (tab->look != kLeftTitledWindowLook) {
917bb2e9b06SClemens Zeidler		fDrawingEngine->StrokeLine(BPoint(tabRect.right - 1, tabRect.top + 2),
918bb2e9b06SClemens Zeidler			BPoint(tabRect.right - 1, tabBotton),
919e3ab8648SIngo Weinhold			colors[COLOR_TAB_SHADOW]);
920083ec975SAxel Dörfler	} else {
921f7e1df75SStephan Aßmus		fDrawingEngine->StrokeLine(
922bb2e9b06SClemens Zeidler			BPoint(tabRect.left + 2, tabRect.bottom - 1),
923bb2e9b06SClemens Zeidler			BPoint(tabRect.right, tabRect.bottom - 1),
924e3ab8648SIngo Weinhold			colors[COLOR_TAB_SHADOW]);
925083ec975SAxel Dörfler	}
926ae01fc9bSDarkWyrm
92759345e26SStephan Aßmus	// fill
928ce5d6472SStephan Aßmus	BGradientLinear gradient;
929bb2e9b06SClemens Zeidler	gradient.SetStart(tabRect.LeftTop());
930e3ab8648SIngo Weinhold	gradient.AddColor(colors[COLOR_TAB_LIGHT], 0);
931e3ab8648SIngo Weinhold	gradient.AddColor(colors[COLOR_TAB], 255);
932ce5d6472SStephan Aßmus
9331c141573SClemens Zeidler	if (tab->look != kLeftTitledWindowLook) {
934bb2e9b06SClemens Zeidler		gradient.SetEnd(tabRect.LeftBottom());
935bb2e9b06SClemens Zeidler		fDrawingEngine->FillRect(BRect(tabRect.left + 2, tabRect.top + 2,
936bb2e9b06SClemens Zeidler			tabRect.right - 2, tabBotton), gradient);
937083ec975SAxel Dörfler	} else {
938bb2e9b06SClemens Zeidler		gradient.SetEnd(tabRect.RightTop());
939bb2e9b06SClemens Zeidler		fDrawingEngine->FillRect(BRect(tabRect.left + 2, tabRect.top + 2,
940bb2e9b06SClemens Zeidler			tabRect.right, tabRect.bottom - 2), gradient);
941083ec975SAxel Dörfler	}
94267f4247fSAdi Oanca
943bb2e9b06SClemens Zeidler	_DrawTitle(tab, tabRect);
944cc10522eSDarkWyrm
945bb2e9b06SClemens Zeidler	DrawButtons(tab, invalid);
946ae01fc9bSDarkWyrm}
947ae01fc9bSDarkWyrm
948e13a79e0SMichael Lotz
94959345e26SStephan Aßmusvoid
95086b01082SClemens ZeidlerDefaultDecorator::_DrawClose(Decorator::Tab* _tab, bool direct, BRect rect)
951ae01fc9bSDarkWyrm{
952e13a79e0SMichael Lotz	STRACE(("_DrawClose(%f,%f,%f,%f)\n", rect.left, rect.top, rect.right,
953e13a79e0SMichael Lotz		rect.bottom));
954e13a79e0SMichael Lotz
955bb2e9b06SClemens Zeidler	DefaultDecorator::Tab* tab = static_cast<DefaultDecorator::Tab*>(_tab);
956bb2e9b06SClemens Zeidler
957bb2e9b06SClemens Zeidler	int32 index = (tab->buttonFocus ? 0 : 1) + (tab->closePressed ? 0 : 2);
958bb2e9b06SClemens Zeidler	ServerBitmap* bitmap = tab->closeBitmaps[index];
959e13a79e0SMichael Lotz	if (bitmap == NULL) {
960bb2e9b06SClemens Zeidler		bitmap = _GetBitmapForButton(tab, COMPONENT_CLOSE_BUTTON,
961bb2e9b06SClemens Zeidler			tab->closePressed, rect.IntegerWidth(), rect.IntegerHeight());
962bb2e9b06SClemens Zeidler		tab->closeBitmaps[index] = bitmap;
963e13a79e0SMichael Lotz	}
964e13a79e0SMichael Lotz
96586b01082SClemens Zeidler	_DrawButtonBitmap(bitmap, direct, rect);
966ae01fc9bSDarkWyrm}
967ae01fc9bSDarkWyrm
968e13a79e0SMichael Lotz
96959345e26SStephan Aßmusvoid
970bb2e9b06SClemens ZeidlerDefaultDecorator::_DrawTitle(Decorator::Tab* _tab, BRect r)
971ae01fc9bSDarkWyrm{
972bb2e9b06SClemens Zeidler	DefaultDecorator::Tab* tab = static_cast<DefaultDecorator::Tab*>(_tab);
973bb2e9b06SClemens Zeidler
974bb2e9b06SClemens Zeidler	const BRect& tabRect = tab->tabRect;
975bb2e9b06SClemens Zeidler	const BRect& closeRect = tab->closeRect;
976bb2e9b06SClemens Zeidler	const BRect& zoomRect = tab->zoomRect;
977bb2e9b06SClemens Zeidler
97859345e26SStephan Aßmus	STRACE(("_DrawTitle(%f,%f,%f,%f)\n", r.left, r.top, r.right, r.bottom));
979ae01fc9bSDarkWyrm
980e3ab8648SIngo Weinhold	ComponentColors colors;
981bb2e9b06SClemens Zeidler	_GetComponentColors(COMPONENT_TAB, colors, tab);
982e3ab8648SIngo Weinhold
983ce5d6472SStephan Aßmus	fDrawingEngine->SetDrawingMode(B_OP_OVER);
984e3ab8648SIngo Weinhold	fDrawingEngine->SetHighColor(colors[COLOR_TAB_TEXT]);
98538287e02SStephan Aßmus	fDrawingEngine->SetFont(fDrawState.Font());
986ae01fc9bSDarkWyrm
98759345e26SStephan Aßmus	// figure out position of text
9888365d9ecSAxel Dörfler	font_height fontHeight;
989aca4f50dSAxel Dörfler	fDrawState.Font().GetHeight(fontHeight);
990ae01fc9bSDarkWyrm
99159345e26SStephan Aßmus	BPoint titlePos;
9921c141573SClemens Zeidler	if (tab->look != kLeftTitledWindowLook) {
993bb2e9b06SClemens Zeidler		titlePos.x = closeRect.IsValid() ? closeRect.right + tab->textOffset
994bb2e9b06SClemens Zeidler			: tabRect.left + tab->textOffset;
995bb2e9b06SClemens Zeidler		titlePos.y = floorf(((tabRect.top + 2.0) + tabRect.bottom
996f7e1df75SStephan Aßmus			+ fontHeight.ascent + fontHeight.descent) / 2.0
997f7e1df75SStephan Aßmus			- fontHeight.descent + 0.5);
998083ec975SAxel Dörfler	} else {
999bb2e9b06SClemens Zeidler		titlePos.x = floorf(((tabRect.left + 2.0) + tabRect.right
1000f7e1df75SStephan Aßmus			+ fontHeight.ascent + fontHeight.descent) / 2.0
1001f7e1df75SStephan Aßmus			- fontHeight.descent + 0.5);
1002bb2e9b06SClemens Zeidler		titlePos.y = zoomRect.IsValid() ? zoomRect.top - tab->textOffset
1003bb2e9b06SClemens Zeidler			: tabRect.bottom - tab->textOffset;
1004083ec975SAxel Dörfler	}
10058365d9ecSAxel Dörfler
1006bb2e9b06SClemens Zeidler	fDrawingEngine->DrawString(tab->truncatedTitle, tab->truncatedTitleLength,
100738287e02SStephan Aßmus		titlePos);
1008ce5d6472SStephan Aßmus
1009ce5d6472SStephan Aßmus	fDrawingEngine->SetDrawingMode(B_OP_COPY);
1010ae01fc9bSDarkWyrm}
1011ae01fc9bSDarkWyrm
1012b31df46fSAxel Dörfler
101359345e26SStephan Aßmusvoid
101486b01082SClemens ZeidlerDefaultDecorator::_DrawZoom(Decorator::Tab* _tab, bool direct, BRect rect)
1015ae01fc9bSDarkWyrm{
1016e13a79e0SMichael Lotz	STRACE(("_DrawZoom(%f,%f,%f,%f)\n", rect.left, rect.top, rect.right,
1017e13a79e0SMichael Lotz		rect.bottom));
1018bb2e9b06SClemens Zeidler	if (rect.IntegerWidth() < 1)
1019bb2e9b06SClemens Zeidler		return;
1020bb2e9b06SClemens Zeidler	DefaultDecorator::Tab* tab = static_cast<DefaultDecorator::Tab*>(_tab);
1021e13a79e0SMichael Lotz
1022bb2e9b06SClemens Zeidler	int32 index = (tab->buttonFocus ? 0 : 1) + (tab->zoomPressed ? 0 : 2);
1023bb2e9b06SClemens Zeidler	ServerBitmap* bitmap = tab->zoomBitmaps[index];
1024e13a79e0SMichael Lotz	if (bitmap == NULL) {
1025bb2e9b06SClemens Zeidler		bitmap = _GetBitmapForButton(tab, COMPONENT_ZOOM_BUTTON,
1026bb2e9b06SClemens Zeidler			tab->zoomPressed, rect.IntegerWidth(), rect.IntegerHeight());
1027bb2e9b06SClemens Zeidler		tab->zoomBitmaps[index] = bitmap;
1028e13a79e0SMichael Lotz	}
1029e60b1ff1SAxel Dörfler
103086b01082SClemens Zeidler	_DrawButtonBitmap(bitmap, direct, rect);
1031ae01fc9bSDarkWyrm}
1032ae01fc9bSDarkWyrm
1033b31df46fSAxel Dörfler
1034e07ebdebSClemens Zeidlervoid
1035bb2e9b06SClemens ZeidlerDefaultDecorator::_SetTitle(Decorator::Tab* tab, const char* string,
1036bb2e9b06SClemens Zeidler	BRegion* updateRegion)
1037e07ebdebSClemens Zeidler{
1038e07ebdebSClemens Zeidler	// TODO: we could be much smarter about the update region
1039e07ebdebSClemens Zeidler
1040bb2e9b06SClemens Zeidler	BRect rect = TabRect(tab);
1041e07ebdebSClemens Zeidler
1042e07ebdebSClemens Zeidler	_DoLayout();
1043e07ebdebSClemens Zeidler
1044e07ebdebSClemens Zeidler	if (updateRegion == NULL)
1045e07ebdebSClemens Zeidler		return;
1046e07ebdebSClemens Zeidler
1047bb2e9b06SClemens Zeidler	rect = rect | TabRect(tab);
1048e07ebdebSClemens Zeidler
1049e07ebdebSClemens Zeidler	rect.bottom++;
1050e07ebdebSClemens Zeidler		// the border will look differently when the title is adjacent
1051e07ebdebSClemens Zeidler
1052e07ebdebSClemens Zeidler	updateRegion->Include(rect);
1053e07ebdebSClemens Zeidler}
1054e07ebdebSClemens Zeidler
1055e07ebdebSClemens Zeidler
105609301a49SClemens Zeidlervoid
105709301a49SClemens ZeidlerDefaultDecorator::_FontsChanged(DesktopSettings& settings,
105809301a49SClemens Zeidler	BRegion* updateRegion)
105909301a49SClemens Zeidler{
106009301a49SClemens Zeidler	// get previous extent
106109301a49SClemens Zeidler	if (updateRegion != NULL)
106209301a49SClemens Zeidler		updateRegion->Include(&GetFootprint());
106309301a49SClemens Zeidler
106409301a49SClemens Zeidler	_UpdateFont(settings);
106509301a49SClemens Zeidler	_InvalidateBitmaps();
106609301a49SClemens Zeidler	_DoLayout();
106709301a49SClemens Zeidler
1068962281e8SClemens Zeidler	_InvalidateFootprint();
106909301a49SClemens Zeidler	if (updateRegion != NULL)
107009301a49SClemens Zeidler		updateRegion->Include(&GetFootprint());
107109301a49SClemens Zeidler}
107209301a49SClemens Zeidler
107309301a49SClemens Zeidler
107409301a49SClemens Zeidlervoid
10751c141573SClemens ZeidlerDefaultDecorator::_SetLook(Decorator::Tab* tab, DesktopSettings& settings,
10761c141573SClemens Zeidler	window_look look, BRegion* updateRegion)
107709301a49SClemens Zeidler{
107809301a49SClemens Zeidler	// TODO: we could be much smarter about the update region
107909301a49SClemens Zeidler
108009301a49SClemens Zeidler	// get previous extent
108109301a49SClemens Zeidler	if (updateRegion != NULL)
108209301a49SClemens Zeidler		updateRegion->Include(&GetFootprint());
108309301a49SClemens Zeidler
10841c141573SClemens Zeidler	tab->look = look;
1085604ae84eSClemens Zeidler
108609301a49SClemens Zeidler	_UpdateFont(settings);
108709301a49SClemens Zeidler	_InvalidateBitmaps();
108809301a49SClemens Zeidler	_DoLayout();
108909301a49SClemens Zeidler
1090962281e8SClemens Zeidler	_InvalidateFootprint();
109109301a49SClemens Zeidler	if (updateRegion != NULL)
109209301a49SClemens Zeidler		updateRegion->Include(&GetFootprint());
109309301a49SClemens Zeidler}
109409301a49SClemens Zeidler
109509301a49SClemens Zeidler
109609301a49SClemens Zeidlervoid
10971c141573SClemens ZeidlerDefaultDecorator::_SetFlags(Decorator::Tab* tab, uint32 flags,
10981c141573SClemens Zeidler	BRegion* updateRegion)
109909301a49SClemens Zeidler{
110009301a49SClemens Zeidler	// TODO: we could be much smarter about the update region
110109301a49SClemens Zeidler
110209301a49SClemens Zeidler	// get previous extent
110309301a49SClemens Zeidler	if (updateRegion != NULL)
110409301a49SClemens Zeidler		updateRegion->Include(&GetFootprint());
110509301a49SClemens Zeidler
11061c141573SClemens Zeidler	tab->flags = flags;
110709301a49SClemens Zeidler	_DoLayout();
110809301a49SClemens Zeidler
1109962281e8SClemens Zeidler	_InvalidateFootprint();
111009301a49SClemens Zeidler	if (updateRegion != NULL)
111109301a49SClemens Zeidler		updateRegion->Include(&GetFootprint());
111209301a49SClemens Zeidler}
111309301a49SClemens Zeidler
111409301a49SClemens Zeidler
111559345e26SStephan Aßmusvoid
1116bb2e9b06SClemens ZeidlerDefaultDecorator::_SetFocus(Decorator::Tab* _tab)
1117ae01fc9bSDarkWyrm{
1118bb2e9b06SClemens Zeidler	DefaultDecorator::Tab* tab = static_cast<DefaultDecorator::Tab*>(_tab);
1119bb2e9b06SClemens Zeidler	tab->buttonFocus = IsFocus(tab)
11201c141573SClemens Zeidler		|| ((tab->look == B_FLOATING_WINDOW_LOOK
11211c141573SClemens Zeidler			|| tab->look == kLeftTitledWindowLook)
11221c141573SClemens Zeidler			&& (tab->flags & B_AVOID_FOCUS) != 0);
1123bb2e9b06SClemens Zeidler	if (CountTabs() > 1)
1124bb2e9b06SClemens Zeidler		_LayoutTabItems(tab, tab->tabRect);
1125ae01fc9bSDarkWyrm}
1126ae01fc9bSDarkWyrm
1127e13a79e0SMichael Lotz
112809301a49SClemens Zeidlervoid
112909301a49SClemens ZeidlerDefaultDecorator::_MoveBy(BPoint offset)
113009301a49SClemens Zeidler{
113109301a49SClemens Zeidler	STRACE(("DefaultDecorator: Move By (%.1f, %.1f)\n", offset.x, offset.y));
113209301a49SClemens Zeidler	// Move all internal rectangles the appropriate amount
1133bb2e9b06SClemens Zeidler	for (int32 i = 0; i < fTabList.CountItems(); i++) {
1134bb2e9b06SClemens Zeidler		Decorator::Tab* tab = fTabList.ItemAt(i);
1135bb2e9b06SClemens Zeidler
1136bb2e9b06SClemens Zeidler		tab->zoomRect.OffsetBy(offset);
1137bb2e9b06SClemens Zeidler		tab->closeRect.OffsetBy(offset);
1138bb2e9b06SClemens Zeidler		tab->tabRect.OffsetBy(offset);
1139bb2e9b06SClemens Zeidler	}
114009301a49SClemens Zeidler	fFrame.OffsetBy(offset);
1141bb2e9b06SClemens Zeidler	fTitleBarRect.OffsetBy(offset);
1142bb2e9b06SClemens Zeidler	fTabsRegion.OffsetBy(offset);
114309301a49SClemens Zeidler	fResizeRect.OffsetBy(offset);
114409301a49SClemens Zeidler	fBorderRect.OffsetBy(offset);
114509301a49SClemens Zeidler
114609301a49SClemens Zeidler	fLeftBorder.OffsetBy(offset);
114709301a49SClemens Zeidler	fRightBorder.OffsetBy(offset);
114809301a49SClemens Zeidler	fTopBorder.OffsetBy(offset);
114909301a49SClemens Zeidler	fBottomBorder.OffsetBy(offset);
115009301a49SClemens Zeidler}
115109301a49SClemens Zeidler
115209301a49SClemens Zeidler
115309301a49SClemens Zeidlervoid
115409301a49SClemens ZeidlerDefaultDecorator::_ResizeBy(BPoint offset, BRegion* dirty)
115509301a49SClemens Zeidler{
115609301a49SClemens Zeidler	STRACE(("DefaultDecorator: Resize By (%.1f, %.1f)\n", offset.x, offset.y));
115709301a49SClemens Zeidler	// Move all internal rectangles the appropriate amount
115809301a49SClemens Zeidler	fFrame.right += offset.x;
115909301a49SClemens Zeidler	fFrame.bottom += offset.y;
116009301a49SClemens Zeidler
116109301a49SClemens Zeidler	// Handle invalidation of resize rect
11621c141573SClemens Zeidler	if (dirty && !(fTopTab->flags & B_NOT_RESIZABLE)) {
116309301a49SClemens Zeidler		BRect realResizeRect;
11641c141573SClemens Zeidler		switch ((int)fTopTab->look) {
116509301a49SClemens Zeidler			case B_DOCUMENT_WINDOW_LOOK:
116609301a49SClemens Zeidler				realResizeRect = fResizeRect;
116709301a49SClemens Zeidler				// Resize rect at old location
116809301a49SClemens Zeidler				dirty->Include(realResizeRect);
116909301a49SClemens Zeidler				realResizeRect.OffsetBy(offset);
117009301a49SClemens Zeidler				// Resize rect at new location
117109301a49SClemens Zeidler				dirty->Include(realResizeRect);
117209301a49SClemens Zeidler				break;
117309301a49SClemens Zeidler			case B_TITLED_WINDOW_LOOK:
117409301a49SClemens Zeidler			case B_FLOATING_WINDOW_LOOK:
117509301a49SClemens Zeidler			case B_MODAL_WINDOW_LOOK:
117609301a49SClemens Zeidler			case kLeftTitledWindowLook:
117709301a49SClemens Zeidler				// The bottom border resize line
117809301a49SClemens Zeidler				realResizeRect.Set(fRightBorder.right - kBorderResizeLength, fBottomBorder.top,
117909301a49SClemens Zeidler					fRightBorder.right - kBorderResizeLength, fBottomBorder.bottom - 1);
118009301a49SClemens Zeidler				// Old location
118109301a49SClemens Zeidler				dirty->Include(realResizeRect);
118209301a49SClemens Zeidler				realResizeRect.OffsetBy(offset);
118309301a49SClemens Zeidler				// New location
118409301a49SClemens Zeidler				dirty->Include(realResizeRect);
118509301a49SClemens Zeidler
118609301a49SClemens Zeidler				// The right border resize line
118709301a49SClemens Zeidler				realResizeRect.Set(fRightBorder.left, fBottomBorder.bottom - kBorderResizeLength,
118809301a49SClemens Zeidler					fRightBorder.right - 1, fBottomBorder.bottom - kBorderResizeLength);
118909301a49SClemens Zeidler				// Old location
119009301a49SClemens Zeidler				dirty->Include(realResizeRect);
119109301a49SClemens Zeidler				realResizeRect.OffsetBy(offset);
119209301a49SClemens Zeidler				// New location
119309301a49SClemens Zeidler				dirty->Include(realResizeRect);
119409301a49SClemens Zeidler				break;
119509301a49SClemens Zeidler			default:
119609301a49SClemens Zeidler				break;
119709301a49SClemens Zeidler		}
119809301a49SClemens Zeidler	}
119909301a49SClemens Zeidler
120009301a49SClemens Zeidler	fResizeRect.OffsetBy(offset);
120109301a49SClemens Zeidler
120209301a49SClemens Zeidler	fBorderRect.right += offset.x;
120309301a49SClemens Zeidler	fBorderRect.bottom += offset.y;
120409301a49SClemens Zeidler
120509301a49SClemens Zeidler	fLeftBorder.bottom += offset.y;
120609301a49SClemens Zeidler	fTopBorder.right += offset.x;
120709301a49SClemens Zeidler
120809301a49SClemens Zeidler	fRightBorder.OffsetBy(offset.x, 0.0);
120909301a49SClemens Zeidler	fRightBorder.bottom	+= offset.y;
121009301a49SClemens Zeidler
121109301a49SClemens Zeidler	fBottomBorder.OffsetBy(0.0, offset.y);
121209301a49SClemens Zeidler	fBottomBorder.right	+= offset.x;
121309301a49SClemens Zeidler
121409301a49SClemens Zeidler	if (dirty) {
121509301a49SClemens Zeidler		if (offset.x > 0.0) {
121609301a49SClemens Zeidler			BRect t(fRightBorder.left - offset.x, fTopBorder.top,
121709301a49SClemens Zeidler				fRightBorder.right, fTopBorder.bottom);
121809301a49SClemens Zeidler			dirty->Include(t);
121909301a49SClemens Zeidler			t.Set(fRightBorder.left - offset.x, fBottomBorder.top,
122009301a49SClemens Zeidler				fRightBorder.right, fBottomBorder.bottom);
122109301a49SClemens Zeidler			dirty->Include(t);
122209301a49SClemens Zeidler			dirty->Include(fRightBorder);
122309301a49SClemens Zeidler		} else if (offset.x < 0.0) {
122409301a49SClemens Zeidler			dirty->Include(BRect(fRightBorder.left, fTopBorder.top,
122509301a49SClemens Zeidler				fRightBorder.right, fBottomBorder.bottom));
122609301a49SClemens Zeidler		}
122709301a49SClemens Zeidler		if (offset.y > 0.0) {
122809301a49SClemens Zeidler			BRect t(fLeftBorder.left, fLeftBorder.bottom - offset.y,
122909301a49SClemens Zeidler				fLeftBorder.right, fLeftBorder.bottom);
123009301a49SClemens Zeidler			dirty->Include(t);
123109301a49SClemens Zeidler			t.Set(fRightBorder.left, fRightBorder.bottom - offset.y,
123209301a49SClemens Zeidler				fRightBorder.right, fRightBorder.bottom);
123309301a49SClemens Zeidler			dirty->Include(t);
123409301a49SClemens Zeidler			dirty->Include(fBottomBorder);
123509301a49SClemens Zeidler		} else if (offset.y < 0.0) {
123609301a49SClemens Zeidler			dirty->Include(fBottomBorder);
123709301a49SClemens Zeidler		}
123809301a49SClemens Zeidler	}
123909301a49SClemens Zeidler
124009301a49SClemens Zeidler	// resize tab and layout tab items
1241bb2e9b06SClemens Zeidler	if (fTitleBarRect.IsValid()) {
1242bb2e9b06SClemens Zeidler		if (fTabList.CountItems() > 1) {
1243bb2e9b06SClemens Zeidler			_DoTabLayout();
12441c44bb21SClemens Zeidler			if (dirty != NULL)
12451c44bb21SClemens Zeidler				dirty->Include(fTitleBarRect);
1246bb2e9b06SClemens Zeidler			return;
1247bb2e9b06SClemens Zeidler		}
1248bb2e9b06SClemens Zeidler
1249bb2e9b06SClemens Zeidler		DefaultDecorator::Tab* tab = _TabAt(0);
1250bb2e9b06SClemens Zeidler		BRect& tabRect = tab->tabRect;
1251bb2e9b06SClemens Zeidler		BRect oldTabRect(tabRect);
125209301a49SClemens Zeidler
125309301a49SClemens Zeidler		float tabSize;
1254e089170aSClemens Zeidler		float tabOffset = _SingleTabOffsetAndSize(tabSize);
125509301a49SClemens Zeidler
1256bb2e9b06SClemens Zeidler		float delta = tabOffset - tab->tabOffset;
1257bb2e9b06SClemens Zeidler		tab->tabOffset = (uint32)tabOffset;
12581c141573SClemens Zeidler		if (fTopTab->look != kLeftTitledWindowLook)
1259bb2e9b06SClemens Zeidler			tabRect.OffsetBy(delta, 0.0);
126009301a49SClemens Zeidler		else
1261bb2e9b06SClemens Zeidler			tabRect.OffsetBy(0.0, delta);
126209301a49SClemens Zeidler
1263bb2e9b06SClemens Zeidler		if (tabSize < tab->minTabSize)
1264bb2e9b06SClemens Zeidler			tabSize = tab->minTabSize;
1265bb2e9b06SClemens Zeidler		if (tabSize > tab->maxTabSize)
1266bb2e9b06SClemens Zeidler			tabSize = tab->maxTabSize;
126709301a49SClemens Zeidler
12681c141573SClemens Zeidler		if (fTopTab->look != kLeftTitledWindowLook
12691c141573SClemens Zeidler			&& tabSize != tabRect.Width()) {
1270bb2e9b06SClemens Zeidler			tabRect.right = tabRect.left + tabSize;
12711c141573SClemens Zeidler		} else if (fTopTab->look == kLeftTitledWindowLook
1272bb2e9b06SClemens Zeidler			&& tabSize != tabRect.Height()) {
1273bb2e9b06SClemens Zeidler			tabRect.bottom = tabRect.top + tabSize;
127409301a49SClemens Zeidler		}
127509301a49SClemens Zeidler
1276bb2e9b06SClemens Zeidler		if (oldTabRect != tabRect) {
1277bb2e9b06SClemens Zeidler			_LayoutTabItems(tab, tabRect);
127809301a49SClemens Zeidler
127909301a49SClemens Zeidler			if (dirty) {
128009301a49SClemens Zeidler				// NOTE: the tab rect becoming smaller only would
128109301a49SClemens Zeidler				// handled be the Desktop anyways, so it is sufficient
128209301a49SClemens Zeidler				// to include it into the dirty region in it's
128309301a49SClemens Zeidler				// final state
1284bb2e9b06SClemens Zeidler				BRect redraw(tabRect);
128509301a49SClemens Zeidler				if (delta != 0.0) {
128609301a49SClemens Zeidler					redraw = redraw | oldTabRect;
12871c141573SClemens Zeidler					if (fTopTab->look != kLeftTitledWindowLook)
128809301a49SClemens Zeidler						redraw.bottom++;
128909301a49SClemens Zeidler					else
129009301a49SClemens Zeidler						redraw.right++;
129109301a49SClemens Zeidler				}
129209301a49SClemens Zeidler				dirty->Include(redraw);
129309301a49SClemens Zeidler			}
129409301a49SClemens Zeidler		}
1295bb2e9b06SClemens Zeidler		fTitleBarRect = tabRect;
1296bb2e9b06SClemens Zeidler		fTabsRegion = fTitleBarRect;
129709301a49SClemens Zeidler	}
129809301a49SClemens Zeidler}
129909301a49SClemens Zeidler
130009301a49SClemens Zeidler
130109301a49SClemens Zeidlerbool
1302bb2e9b06SClemens ZeidlerDefaultDecorator::_SetTabLocation(Decorator::Tab* _tab, float location,
1303bb2e9b06SClemens Zeidler	bool isShifting, BRegion* updateRegion)
130409301a49SClemens Zeidler{
130509301a49SClemens Zeidler	STRACE(("DefaultDecorator: Set Tab Location(%.1f)\n", location));
1306bb2e9b06SClemens Zeidler	if (CountTabs() > 1) {
1307bb2e9b06SClemens Zeidler		if (isShifting == false) {
1308bb2e9b06SClemens Zeidler			_DoTabLayout();
1309bb2e9b06SClemens Zeidler			if (updateRegion != NULL)
1310bb2e9b06SClemens Zeidler				updateRegion->Include(fTitleBarRect);
1311bb2e9b06SClemens Zeidler			fOldMovingTab = BRect(0, 0, -1, -1);
1312bb2e9b06SClemens Zeidler			return true;
1313bb2e9b06SClemens Zeidler		} else {
1314bb2e9b06SClemens Zeidler			if (fOldMovingTab.IsValid() == false)
1315bb2e9b06SClemens Zeidler				fOldMovingTab = _tab->tabRect;
1316bb2e9b06SClemens Zeidler		}
1317bb2e9b06SClemens Zeidler	}
1318bb2e9b06SClemens Zeidler
1319bb2e9b06SClemens Zeidler	DefaultDecorator::Tab* tab = static_cast<DefaultDecorator::Tab*>(_tab);
1320bb2e9b06SClemens Zeidler	BRect& tabRect = tab->tabRect;
1321bb2e9b06SClemens Zeidler	if (tabRect.IsValid() == false)
132209301a49SClemens Zeidler		return false;
132309301a49SClemens Zeidler
132409301a49SClemens Zeidler	if (location < 0)
132509301a49SClemens Zeidler		location = 0;
132609301a49SClemens Zeidler
132709301a49SClemens Zeidler	float maxLocation
1328bb2e9b06SClemens Zeidler		= fRightBorder.right - fLeftBorder.left - tabRect.Width();
1329bb2e9b06SClemens Zeidler	if (CountTabs() > 1)
1330bb2e9b06SClemens Zeidler		maxLocation = fTitleBarRect.right - fLeftBorder.left - tabRect.Width();
1331bb2e9b06SClemens Zeidler
133209301a49SClemens Zeidler	if (location > maxLocation)
133309301a49SClemens Zeidler		location = maxLocation;
133409301a49SClemens Zeidler
1335bb2e9b06SClemens Zeidler	float delta = floor(location - tab->tabOffset);
133609301a49SClemens Zeidler	if (delta == 0.0)
133709301a49SClemens Zeidler		return false;
133809301a49SClemens Zeidler
1339bb2e9b06SClemens Zeidler	// redraw old rect (1 pixel on the border must also be updated)
1340bb2e9b06SClemens Zeidler	BRect rect(tabRect);
1341bb2e9b06SClemens Zeidler	rect.bottom++;
1342bb2e9b06SClemens Zeidler	if (updateRegion != NULL)
1343bb2e9b06SClemens Zeidler		updateRegion->Include(rect);
1344bb2e9b06SClemens Zeidler
1345bb2e9b06SClemens Zeidler	tabRect.OffsetBy(delta, 0);
1346bb2e9b06SClemens Zeidler	tab->tabOffset = (int32)location;
1347bb2e9b06SClemens Zeidler	_LayoutTabItems(_tab, tabRect);
1348bb2e9b06SClemens Zeidler	tab->tabLocation = maxLocation > 0.0 ? tab->tabOffset / maxLocation : 0.0;
134909301a49SClemens Zeidler
1350bb2e9b06SClemens Zeidler	if (fTabList.CountItems() == 1)
1351bb2e9b06SClemens Zeidler		fTitleBarRect = tabRect;
135209301a49SClemens Zeidler
1353bb2e9b06SClemens Zeidler	_CalculateTabsRegion();
135409301a49SClemens Zeidler
135509301a49SClemens Zeidler	// redraw new rect as well
1356bb2e9b06SClemens Zeidler	rect = tabRect;
1357bb2e9b06SClemens Zeidler	rect.bottom++;
1358bb2e9b06SClemens Zeidler	if (updateRegion != NULL)
1359bb2e9b06SClemens Zeidler		updateRegion->Include(rect);
1360bb2e9b06SClemens Zeidler
136109301a49SClemens Zeidler	return true;
136209301a49SClemens Zeidler}
136309301a49SClemens Zeidler
136409301a49SClemens Zeidler
136509301a49SClemens Zeidlerbool
136609301a49SClemens ZeidlerDefaultDecorator::_SetSettings(const BMessage& settings, BRegion* updateRegion)
136709301a49SClemens Zeidler{
136809301a49SClemens Zeidler	float tabLocation;
1369bb2e9b06SClemens Zeidler	bool modified = false;
1370bb2e9b06SClemens Zeidler	for (int32 i = 0; i < fTabList.CountItems(); i++) {
1371bb2e9b06SClemens Zeidler		if (settings.FindFloat("tab location", i, &tabLocation) != B_OK)
1372bb2e9b06SClemens Zeidler			return false;
1373bb2e9b06SClemens Zeidler		modified |= SetTabLocation(i, tabLocation, updateRegion);
1374bb2e9b06SClemens Zeidler	}
1375bb2e9b06SClemens Zeidler	return modified;
1376bb2e9b06SClemens Zeidler}
1377bb2e9b06SClemens Zeidler
1378bb2e9b06SClemens Zeidler
1379bb2e9b06SClemens Zeidlerbool
13801c141573SClemens ZeidlerDefaultDecorator::_AddTab(DesktopSettings& settings, int32 index,
13811c141573SClemens Zeidler	BRegion* updateRegion)
1382bb2e9b06SClemens Zeidler{
13831c141573SClemens Zeidler	_UpdateFont(settings);
13841c141573SClemens Zeidler
1385bb2e9b06SClemens Zeidler	_DoLayout();
1386bb2e9b06SClemens Zeidler	if (updateRegion != NULL)
1387bb2e9b06SClemens Zeidler		updateRegion->Include(fTitleBarRect);
1388bb2e9b06SClemens Zeidler	return true;
1389bb2e9b06SClemens Zeidler}
1390bb2e9b06SClemens Zeidler
1391bb2e9b06SClemens Zeidler
1392bb2e9b06SClemens Zeidlerbool
139386b01082SClemens ZeidlerDefaultDecorator::_RemoveTab(int32 index, BRegion* updateRegion)
1394bb2e9b06SClemens Zeidler{
1395bb2e9b06SClemens Zeidler	BRect oldTitle = fTitleBarRect;
1396bb2e9b06SClemens Zeidler	_DoLayout();
1397bb2e9b06SClemens Zeidler	if (updateRegion != NULL) {
1398bb2e9b06SClemens Zeidler		updateRegion->Include(oldTitle);
1399bb2e9b06SClemens Zeidler		updateRegion->Include(fTitleBarRect);
1400bb2e9b06SClemens Zeidler	}
1401bb2e9b06SClemens Zeidler	return true;
1402bb2e9b06SClemens Zeidler}
1403bb2e9b06SClemens Zeidler
1404bb2e9b06SClemens Zeidler
1405bb2e9b06SClemens Zeidlerbool
1406bb2e9b06SClemens ZeidlerDefaultDecorator::_MoveTab(int32 from, int32 to, bool isMoving,
1407bb2e9b06SClemens Zeidler	BRegion* updateRegion)
1408bb2e9b06SClemens Zeidler{
1409bb2e9b06SClemens Zeidler	DefaultDecorator::Tab* toTab = _TabAt(to);
1410bb2e9b06SClemens Zeidler	if (toTab == NULL)
1411bb2e9b06SClemens Zeidler		return false;
1412bb2e9b06SClemens Zeidler
1413bb2e9b06SClemens Zeidler	if (from < to) {
1414bb2e9b06SClemens Zeidler		fOldMovingTab.OffsetBy(toTab->tabRect.Width(), 0);
1415bb2e9b06SClemens Zeidler		toTab->tabRect.OffsetBy(-fOldMovingTab.Width(), 0);
1416bb2e9b06SClemens Zeidler	} else {
1417bb2e9b06SClemens Zeidler		fOldMovingTab.OffsetBy(-toTab->tabRect.Width(), 0);
1418bb2e9b06SClemens Zeidler		toTab->tabRect.OffsetBy(fOldMovingTab.Width(), 0);
1419bb2e9b06SClemens Zeidler	}
1420bb2e9b06SClemens Zeidler
1421bb2e9b06SClemens Zeidler	toTab->tabOffset = uint32(toTab->tabRect.left - fLeftBorder.left);
1422bb2e9b06SClemens Zeidler	_LayoutTabItems(toTab, toTab->tabRect);
1423bb2e9b06SClemens Zeidler
1424bb2e9b06SClemens Zeidler	_CalculateTabsRegion();
142509301a49SClemens Zeidler
1426bb2e9b06SClemens Zeidler	if (updateRegion != NULL)
1427bb2e9b06SClemens Zeidler		updateRegion->Include(fTitleBarRect);
1428bb2e9b06SClemens Zeidler	return true;
142909301a49SClemens Zeidler}
143009301a49SClemens Zeidler
143109301a49SClemens Zeidler
143209301a49SClemens Zeidlervoid
143309301a49SClemens ZeidlerDefaultDecorator::_GetFootprint(BRegion *region)
143409301a49SClemens Zeidler{
143509301a49SClemens Zeidler	STRACE(("DefaultDecorator: Get Footprint\n"));
143609301a49SClemens Zeidler	// This function calculates the decorator's footprint in coordinates
143709301a49SClemens Zeidler	// relative to the view. This is most often used to set a Window
143809301a49SClemens Zeidler	// object's visible region.
143945b17fdeSJohn Scipione	if (region == NULL)
144009301a49SClemens Zeidler		return;
144109301a49SClemens Zeidler
144209301a49SClemens Zeidler	region->MakeEmpty();
144309301a49SClemens Zeidler
14441c141573SClemens Zeidler	if (fTopTab->look == B_NO_BORDER_WINDOW_LOOK)
144509301a49SClemens Zeidler		return;
144609301a49SClemens Zeidler
144709301a49SClemens Zeidler	region->Include(fTopBorder);
144809301a49SClemens Zeidler	region->Include(fLeftBorder);
144909301a49SClemens Zeidler	region->Include(fRightBorder);
145009301a49SClemens Zeidler	region->Include(fBottomBorder);
145109301a49SClemens Zeidler
14521c141573SClemens Zeidler	if (fTopTab->look == B_BORDERED_WINDOW_LOOK)
145309301a49SClemens Zeidler		return;
145409301a49SClemens Zeidler
1455bb2e9b06SClemens Zeidler	region->Include(&fTabsRegion);
145609301a49SClemens Zeidler
14571c141573SClemens Zeidler	if (fTopTab->look == B_DOCUMENT_WINDOW_LOOK) {
145809301a49SClemens Zeidler		// include the rectangular resize knob on the bottom right
145909301a49SClemens Zeidler		float knobSize = kResizeKnobSize - fBorderWidth;
146009301a49SClemens Zeidler		region->Include(BRect(fFrame.right - knobSize, fFrame.bottom - knobSize,
146109301a49SClemens Zeidler			fFrame.right, fFrame.bottom));
146209301a49SClemens Zeidler	}
146309301a49SClemens Zeidler}
146409301a49SClemens Zeidler
146509301a49SClemens Zeidler
14667ca71ab6SIngo Weinholdvoid
1467bb2e9b06SClemens ZeidlerDefaultDecorator::DrawButtons(Decorator::Tab* tab, const BRect& invalid)
14687ca71ab6SIngo Weinhold{
14697ca71ab6SIngo Weinhold	// Draw the buttons if we're supposed to
14701c141573SClemens Zeidler	if (!(tab->flags & B_NOT_CLOSABLE) && invalid.Intersects(tab->closeRect))
147186b01082SClemens Zeidler		_DrawClose(tab, false, tab->closeRect);
14721c141573SClemens Zeidler	if (!(tab->flags & B_NOT_ZOOMABLE) && invalid.Intersects(tab->zoomRect))
147386b01082SClemens Zeidler		_DrawZoom(tab, false, tab->zoomRect);
14747ca71ab6SIngo Weinhold}
14757ca71ab6SIngo Weinhold
14767ca71ab6SIngo Weinhold
1477e3ab8648SIngo Weinhold/*!	Returns the frame colors for the specified decorator component.
1478e3ab8648SIngo Weinhold
1479e3ab8648SIngo Weinhold	The meaning of the color array elements depends on the specified component.
1480e3ab8648SIngo Weinhold	For some components some array elements are unused.
1481e3ab8648SIngo Weinhold
14822b602c73SIngo Weinhold	\param component The component for which to return the frame colors.
14832b602c73SIngo Weinhold	\param highlight The highlight set for the component.
1484e3ab8648SIngo Weinhold	\param colors An array of colors to be initialized by the function.
1485e3ab8648SIngo Weinhold*/
1486e3ab8648SIngo Weinholdvoid
14872b602c73SIngo WeinholdDefaultDecorator::GetComponentColors(Component component, uint8 highlight,
1488bb2e9b06SClemens Zeidler	ComponentColors _colors, Decorator::Tab* _tab)
1489e3ab8648SIngo Weinhold{
1490bb2e9b06SClemens Zeidler	DefaultDecorator::Tab* tab = static_cast<DefaultDecorator::Tab*>(_tab);
1491e3ab8648SIngo Weinhold	switch (component) {
149209b19da8SIngo Weinhold		case COMPONENT_TAB:
1493bb2e9b06SClemens Zeidler			if (tab && tab->buttonFocus) {
149470a5df38SRyan Leavengood				_colors[COLOR_TAB_FRAME_LIGHT]
149570a5df38SRyan Leavengood					= tint_color(kFocusFrameColor, B_DARKEN_2_TINT);
149670a5df38SRyan Leavengood				_colors[COLOR_TAB_FRAME_DARK]
149770a5df38SRyan Leavengood					= tint_color(kFocusFrameColor, B_DARKEN_3_TINT);
1498e3ab8648SIngo Weinhold				_colors[COLOR_TAB] = kFocusTabColor;
1499e3ab8648SIngo Weinhold				_colors[COLOR_TAB_LIGHT] = kFocusTabColorLight;
1500e3ab8648SIngo Weinhold				_colors[COLOR_TAB_BEVEL] = kFocusTabColorBevel;
1501e3ab8648SIngo Weinhold				_colors[COLOR_TAB_SHADOW] = kFocusTabColorShadow;
1502e3ab8648SIngo Weinhold				_colors[COLOR_TAB_TEXT] = kFocusTextColor;
1503e3ab8648SIngo Weinhold			} else {
150470a5df38SRyan Leavengood				_colors[COLOR_TAB_FRAME_LIGHT]
150570a5df38SRyan Leavengood					= tint_color(kNonFocusFrameColor, B_DARKEN_2_TINT);
150670a5df38SRyan Leavengood				_colors[COLOR_TAB_FRAME_DARK]
150770a5df38SRyan Leavengood					= tint_color(kNonFocusFrameColor, B_DARKEN_3_TINT);
1508e3ab8648SIngo Weinhold				_colors[COLOR_TAB] = kNonFocusTabColor;
1509e3ab8648SIngo Weinhold				_colors[COLOR_TAB_LIGHT] = kNonFocusTabColorLight;
1510e3ab8648SIngo Weinhold				_colors[COLOR_TAB_BEVEL] = kNonFocusTabColorBevel;
1511e3ab8648SIngo Weinhold				_colors[COLOR_TAB_SHADOW] = kNonFocusTabColorShadow;
1512e3ab8648SIngo Weinhold				_colors[COLOR_TAB_TEXT] = kNonFocusTextColor;
1513e3ab8648SIngo Weinhold			}
1514e3ab8648SIngo Weinhold			break;
1515e3ab8648SIngo Weinhold
151606aa76e2SIngo Weinhold		case COMPONENT_CLOSE_BUTTON:
151706aa76e2SIngo Weinhold		case COMPONENT_ZOOM_BUTTON:
1518bb2e9b06SClemens Zeidler			if (tab && tab->buttonFocus) {
151906aa76e2SIngo Weinhold				_colors[COLOR_BUTTON] = kFocusTabColor;
152006aa76e2SIngo Weinhold				_colors[COLOR_BUTTON_LIGHT] = kFocusTabColorLight;
152106aa76e2SIngo Weinhold			} else {
152206aa76e2SIngo Weinhold				_colors[COLOR_BUTTON] = kNonFocusTabColor;
152306aa76e2SIngo Weinhold				_colors[COLOR_BUTTON_LIGHT] = kNonFocusTabColorLight;
152406aa76e2SIngo Weinhold			}
152506aa76e2SIngo Weinhold			break;
152606aa76e2SIngo Weinhold
152709b19da8SIngo Weinhold		case COMPONENT_LEFT_BORDER:
152809b19da8SIngo Weinhold		case COMPONENT_RIGHT_BORDER:
152909b19da8SIngo Weinhold		case COMPONENT_TOP_BORDER:
153009b19da8SIngo Weinhold		case COMPONENT_BOTTOM_BORDER:
153109b19da8SIngo Weinhold		case COMPONENT_RESIZE_CORNER:
1532e3ab8648SIngo Weinhold		default:
1533bb2e9b06SClemens Zeidler			if (tab && tab->buttonFocus) {
1534a18c2a6dSJohn Scipione				_colors[0] = tint_color(kFocusFrameColor, B_DARKEN_2_TINT);
1535a18c2a6dSJohn Scipione				_colors[1] = tint_color(kFocusFrameColor, B_LIGHTEN_2_TINT);
153630d17caaSJohn Scipione				_colors[2] = kFocusFrameColor;
1537a18c2a6dSJohn Scipione				_colors[3] = tint_color(kFocusFrameColor,
1538a18c2a6dSJohn Scipione					(B_DARKEN_1_TINT + B_NO_TINT) / 2);
1539a18c2a6dSJohn Scipione				_colors[4] = tint_color(kFocusFrameColor, B_DARKEN_2_TINT);
1540a18c2a6dSJohn Scipione				_colors[5] = tint_color(kFocusFrameColor, B_DARKEN_3_TINT);
1541e3ab8648SIngo Weinhold			} else {
1542a18c2a6dSJohn Scipione				_colors[0] = tint_color(kNonFocusFrameColor, B_DARKEN_2_TINT);
1543a18c2a6dSJohn Scipione				_colors[1] = tint_color(kNonFocusFrameColor, B_LIGHTEN_2_TINT);
154430d17caaSJohn Scipione				_colors[2] = kNonFocusFrameColor;
1545a18c2a6dSJohn Scipione				_colors[3] = tint_color(kNonFocusFrameColor,
1546a18c2a6dSJohn Scipione					(B_DARKEN_1_TINT + B_NO_TINT) / 2);
1547a18c2a6dSJohn Scipione				_colors[4] = tint_color(kNonFocusFrameColor, B_DARKEN_2_TINT);
1548a18c2a6dSJohn Scipione				_colors[5] = tint_color(kNonFocusFrameColor, B_DARKEN_3_TINT);
1549e3ab8648SIngo Weinhold			}
155092fe8be9SIngo Weinhold
155192fe8be9SIngo Weinhold			// for the resize-border highlight dye everything bluish.
155292fe8be9SIngo Weinhold			if (highlight == HIGHLIGHT_RESIZE_BORDER) {
155392fe8be9SIngo Weinhold				for (int32 i = 0; i < 6; i++) {
155492fe8be9SIngo Weinhold					_colors[i].red = std::max((int)_colors[i].red - 80, 0);
155592fe8be9SIngo Weinhold					_colors[i].green = std::max((int)_colors[i].green - 80, 0);
155692fe8be9SIngo Weinhold					_colors[i].blue = 255;
155792fe8be9SIngo Weinhold				}
155892fe8be9SIngo Weinhold			}
1559e3ab8648SIngo Weinhold			break;
1560e3ab8648SIngo Weinhold	}
1561e3ab8648SIngo Weinhold}
1562e3ab8648SIngo Weinhold
1563e3ab8648SIngo Weinhold
15640a3f410fSAxel Dörflervoid
15650a3f410fSAxel DörflerDefaultDecorator::_UpdateFont(DesktopSettings& settings)
15660a3f410fSAxel Dörfler{
15670a3f410fSAxel Dörfler	ServerFont font;
15681c141573SClemens Zeidler	if (fTopTab->look == B_FLOATING_WINDOW_LOOK
15691c141573SClemens Zeidler		|| fTopTab->look == kLeftTitledWindowLook) {
15700a3f410fSAxel Dörfler		settings.GetDefaultPlainFont(font);
15711c141573SClemens Zeidler		if (fTopTab->look == kLeftTitledWindowLook)
15720a3f410fSAxel Dörfler			font.SetRotation(90.0f);
15730a3f410fSAxel Dörfler	} else
15740a3f410fSAxel Dörfler		settings.GetDefaultBoldFont(font);
15750a3f410fSAxel Dörfler
15760a3f410fSAxel Dörfler	font.SetFlags(B_FORCE_ANTIALIASING);
15770a3f410fSAxel Dörfler	font.SetSpacing(B_STRING_SPACING);
15780a3f410fSAxel Dörfler	fDrawState.SetFont(font);
15790a3f410fSAxel Dörfler}
15800a3f410fSAxel Dörfler
15810a3f410fSAxel Dörfler
15826309b004SMichael Lotzvoid
158386b01082SClemens ZeidlerDefaultDecorator::_DrawButtonBitmap(ServerBitmap* bitmap, bool direct,
158486b01082SClemens Zeidler	BRect rect)
15856309b004SMichael Lotz{
15866309b004SMichael Lotz	if (bitmap == NULL)
15876309b004SMichael Lotz		return;
15886309b004SMichael Lotz
1589d0b2c3e1SMichael Lotz	bool copyToFrontEnabled = fDrawingEngine->CopyToFrontEnabled();
159086b01082SClemens Zeidler	fDrawingEngine->SetCopyToFrontEnabled(direct);
1591ce5d6472SStephan Aßmus	drawing_mode oldMode;
1592ce5d6472SStephan Aßmus	fDrawingEngine->SetDrawingMode(B_OP_OVER, oldMode);
1593d0b2c3e1SMichael Lotz	fDrawingEngine->DrawBitmap(bitmap, rect.OffsetToCopy(0, 0), rect);
1594ce5d6472SStephan Aßmus	fDrawingEngine->SetDrawingMode(oldMode);
1595d0b2c3e1SMichael Lotz	fDrawingEngine->SetCopyToFrontEnabled(copyToFrontEnabled);
15966309b004SMichael Lotz}
15976309b004SMichael Lotz
15986309b004SMichael Lotz
1599dacf06e6SAxel Dörfler/*!	\brief Draws a framed rectangle with a gradient.
160006aa76e2SIngo Weinhold	\param down The rectangle should be drawn recessed or not.
160106aa76e2SIngo Weinhold	\param colors A button color array with the colors to be used.
160214fb2b69SAxel Dörfler*/
160359345e26SStephan Aßmusvoid
1604b31df46fSAxel DörflerDefaultDecorator::_DrawBlendedRect(DrawingEngine* engine, BRect rect,
160506aa76e2SIngo Weinhold	bool down, const ComponentColors& colors)
1606ae01fc9bSDarkWyrm{
1607ce5d6472SStephan Aßmus	// figure out which colors to use
1608e13a79e0SMichael Lotz	rgb_color startColor, endColor;
160959345e26SStephan Aßmus	if (down) {
161006aa76e2SIngo Weinhold		startColor = tint_color(colors[COLOR_BUTTON], B_DARKEN_1_TINT);
161106aa76e2SIngo Weinhold		endColor = colors[COLOR_BUTTON_LIGHT];
161259345e26SStephan Aßmus	} else {
161306aa76e2SIngo Weinhold		startColor = tint_color(colors[COLOR_BUTTON], B_LIGHTEN_MAX_TINT);
161406aa76e2SIngo Weinhold		endColor = colors[COLOR_BUTTON];
1615ae01fc9bSDarkWyrm	}
1616e13a79e0SMichael Lotz
1617ce5d6472SStephan Aßmus	// fill
1618ce5d6472SStephan Aßmus	rect.InsetBy(1, 1);
1619ce5d6472SStephan Aßmus	BGradientLinear gradient;
1620ce5d6472SStephan Aßmus	gradient.SetStart(rect.LeftTop());
1621ce5d6472SStephan Aßmus	gradient.SetEnd(rect.RightBottom());
1622ce5d6472SStephan Aßmus	gradient.AddColor(startColor, 0);
1623ce5d6472SStephan Aßmus	gradient.AddColor(endColor, 255);
1624ce5d6472SStephan Aßmus
1625ce5d6472SStephan Aßmus	engine->FillRect(rect, gradient);
1626ce5d6472SStephan Aßmus
1627ce5d6472SStephan Aßmus	// outline
1628ce5d6472SStephan Aßmus	rect.InsetBy(-1, -1);
162906aa76e2SIngo Weinhold	engine->StrokeRect(rect, tint_color(colors[COLOR_BUTTON], B_DARKEN_2_TINT));
1630ae01fc9bSDarkWyrm}
1631ae01fc9bSDarkWyrm
1632b31df46fSAxel Dörfler
163359345e26SStephan Aßmusvoid
1634083ec975SAxel DörflerDefaultDecorator::_GetButtonSizeAndOffset(const BRect& tabRect, float* _offset,
1635f7e1df75SStephan Aßmus	float* _size, float* _inset) const
1636ae01fc9bSDarkWyrm{
16371c141573SClemens Zeidler	float tabSize = fTopTab->look == kLeftTitledWindowLook ?
1638f7e1df75SStephan Aßmus		tabRect.Width() : tabRect.Height();
1639f7e1df75SStephan Aßmus
16401c141573SClemens Zeidler	bool smallTab = fTopTab->look == B_FLOATING_WINDOW_LOOK
16411c141573SClemens Zeidler		|| fTopTab->look == kLeftTitledWindowLook;
1642f7e1df75SStephan Aßmus
164315a6a1bdSStephan Aßmus	*_offset = smallTab ? floorf(fDrawState.Font().Size() / 2.6)
164415a6a1bdSStephan Aßmus		: floorf(fDrawState.Font().Size() / 2.3);
1645f7e1df75SStephan Aßmus	*_inset = smallTab ? floorf(fDrawState.Font().Size() / 5.0)
1646f7e1df75SStephan Aßmus		: floorf(fDrawState.Font().Size() / 6.0);
1647083ec975SAxel Dörfler
164859345e26SStephan Aßmus	// "+ 2" so that the rects are centered within the solid area
164959345e26SStephan Aßmus	// (without the 2 pixels for the top border)
165015a6a1bdSStephan Aßmus	*_size = tabSize - 2 * *_offset + *_inset;
165159345e26SStephan Aßmus}
165247007fb0SAdi Oanca
1653b31df46fSAxel Dörfler
165459345e26SStephan Aßmusvoid
1655bb2e9b06SClemens ZeidlerDefaultDecorator::_LayoutTabItems(Decorator::Tab* _tab, const BRect& tabRect)
165659345e26SStephan Aßmus{
1657bb2e9b06SClemens Zeidler	DefaultDecorator::Tab* tab = static_cast<DefaultDecorator::Tab*>(_tab);
1658bb2e9b06SClemens Zeidler
165959345e26SStephan Aßmus	float offset;
166059345e26SStephan Aßmus	float size;
1661f7e1df75SStephan Aßmus	float inset;
1662f7e1df75SStephan Aßmus	_GetButtonSizeAndOffset(tabRect, &offset, &size, &inset);
166347007fb0SAdi Oanca
1664bb2e9b06SClemens Zeidler	// default textOffset
1665bb2e9b06SClemens Zeidler	tab->textOffset = _DefaultTextOffset();
1666bb2e9b06SClemens Zeidler
1667bb2e9b06SClemens Zeidler	BRect& closeRect = tab->closeRect;
1668bb2e9b06SClemens Zeidler	BRect& zoomRect = tab->zoomRect;
1669bb2e9b06SClemens Zeidler
167059345e26SStephan Aßmus	// calulate close rect based on the tab rectangle
16711c141573SClemens Zeidler	if (tab->look != kLeftTitledWindowLook) {
1672bb2e9b06SClemens Zeidler		closeRect.Set(tabRect.left + offset, tabRect.top + offset,
1673e60b1ff1SAxel Dörfler			tabRect.left + offset + size, tabRect.top + offset + size);
1674e60b1ff1SAxel Dörfler
1675bb2e9b06SClemens Zeidler		zoomRect.Set(tabRect.right - offset - size, tabRect.top + offset,
1676e60b1ff1SAxel Dörfler			tabRect.right - offset, tabRect.top + offset + size);
1677083ec975SAxel Dörfler
1678083ec975SAxel Dörfler		// hidden buttons have no width
16791c141573SClemens Zeidler		if ((tab->flags & B_NOT_CLOSABLE) != 0)
1680bb2e9b06SClemens Zeidler			closeRect.right = closeRect.left - offset;
16811c141573SClemens Zeidler		if ((tab->flags & B_NOT_ZOOMABLE) != 0)
1682bb2e9b06SClemens Zeidler			zoomRect.left = zoomRect.right + offset;
1683083ec975SAxel Dörfler	} else {
1684bb2e9b06SClemens Zeidler		closeRect.Set(tabRect.left + offset, tabRect.top + offset,
1685083ec975SAxel Dörfler			tabRect.left + offset + size, tabRect.top + offset + size);
1686083ec975SAxel Dörfler
1687bb2e9b06SClemens Zeidler		zoomRect.Set(tabRect.left + offset, tabRect.bottom - offset - size,
1688083ec975SAxel Dörfler			tabRect.left + size + offset, tabRect.bottom - offset);
1689083ec975SAxel Dörfler
1690083ec975SAxel Dörfler		// hidden buttons have no height
16911c141573SClemens Zeidler		if ((tab->flags & B_NOT_CLOSABLE) != 0)
1692bb2e9b06SClemens Zeidler			closeRect.bottom = closeRect.top - offset;
16931c141573SClemens Zeidler		if ((tab->flags & B_NOT_ZOOMABLE) != 0)
1694bb2e9b06SClemens Zeidler			zoomRect.top = zoomRect.bottom + offset;
1695e60b1ff1SAxel Dörfler	}
169659345e26SStephan Aßmus
169759345e26SStephan Aßmus	// calculate room for title
1698345d8c9fSAxel Dörfler	// TODO: the +2 is there because the title often appeared
1699e60b1ff1SAxel Dörfler	//	truncated for no apparent reason - OTOH the title does
1700e60b1ff1SAxel Dörfler	//	also not appear perfectly in the middle
17011c141573SClemens Zeidler	if (tab->look != kLeftTitledWindowLook)
1702bb2e9b06SClemens Zeidler		size = (zoomRect.left - closeRect.right) - tab->textOffset * 2 + inset;
1703083ec975SAxel Dörfler	else
1704bb2e9b06SClemens Zeidler		size = (zoomRect.top - closeRect.bottom) - tab->textOffset * 2 + inset;
1705083ec975SAxel Dörfler
1706bb2e9b06SClemens Zeidler	bool stackMode = fTabList.CountItems() > 1;
1707bb2e9b06SClemens Zeidler	if (stackMode && IsFocus(tab) == false) {
1708bb2e9b06SClemens Zeidler		zoomRect.Set(0, 0, 0, 0);
1709bb2e9b06SClemens Zeidler		size = (tab->tabRect.right - closeRect.right) - tab->textOffset * 2
1710bb2e9b06SClemens Zeidler			+ inset;
1711bb2e9b06SClemens Zeidler	}
1712bb2e9b06SClemens Zeidler	uint8 truncateMode = B_TRUNCATE_MIDDLE;
1713bb2e9b06SClemens Zeidler	if (stackMode) {
1714bb2e9b06SClemens Zeidler		if (tab->tabRect.Width() < 100)
1715bb2e9b06SClemens Zeidler			truncateMode = B_TRUNCATE_END;
1716bb2e9b06SClemens Zeidler		float titleWidth = fDrawState.Font().StringWidth(Title(tab),
1717bb2e9b06SClemens Zeidler			BString(Title(tab)).Length());
1718bb2e9b06SClemens Zeidler		if (size < titleWidth) {
1719bb2e9b06SClemens Zeidler			float oldTextOffset = tab->textOffset;
1720bb2e9b06SClemens Zeidler			tab->textOffset -= (titleWidth - size) / 2;
1721bb2e9b06SClemens Zeidler			const float kMinTextOffset = 5.;
1722bb2e9b06SClemens Zeidler			if (tab->textOffset < kMinTextOffset)
1723bb2e9b06SClemens Zeidler				tab->textOffset = kMinTextOffset;
1724bb2e9b06SClemens Zeidler			size += oldTextOffset * 2;
1725bb2e9b06SClemens Zeidler			size -= tab->textOffset * 2;
1726bb2e9b06SClemens Zeidler		}
1727bb2e9b06SClemens Zeidler	}
1728bb2e9b06SClemens Zeidler	tab->truncatedTitle = Title(tab);
1729bb2e9b06SClemens Zeidler	fDrawState.Font().TruncateString(&tab->truncatedTitle, truncateMode, size);
1730bb2e9b06SClemens Zeidler	tab->truncatedTitleLength = tab->truncatedTitle.Length();
1731ae01fc9bSDarkWyrm}
1732e13a79e0SMichael Lotz
1733e13a79e0SMichael Lotz
1734dacf06e6SAxel Dörflervoid
1735dacf06e6SAxel DörflerDefaultDecorator::_InvalidateBitmaps()
1736dacf06e6SAxel Dörfler{
1737bb2e9b06SClemens Zeidler	for (int32 i = 0; i < fTabList.CountItems(); i++) {
1738bb2e9b06SClemens Zeidler		DefaultDecorator::Tab* tab = _TabAt(i);
1739bb2e9b06SClemens Zeidler		for (int32 index = 0; index < 4; index++) {
1740bb2e9b06SClemens Zeidler			tab->closeBitmaps[index] = NULL;
1741bb2e9b06SClemens Zeidler			tab->zoomBitmaps[index] = NULL;
1742bb2e9b06SClemens Zeidler		}
1743dacf06e6SAxel Dörfler	}
1744dacf06e6SAxel Dörfler}
1745dacf06e6SAxel Dörfler
1746dacf06e6SAxel Dörfler
1747b31df46fSAxel DörflerServerBitmap*
1748bb2e9b06SClemens ZeidlerDefaultDecorator::_GetBitmapForButton(Decorator::Tab* tab, Component item,
1749bb2e9b06SClemens Zeidler	bool down, int32 width, int32 height)
1750e13a79e0SMichael Lotz{
1751e13a79e0SMichael Lotz	// TODO: the list of shared bitmaps is never freed
1752e13a79e0SMichael Lotz	struct decorator_bitmap {
175309b19da8SIngo Weinhold		Component			item;
1754e13a79e0SMichael Lotz		bool				down;
1755e13a79e0SMichael Lotz		int32				width;
1756e13a79e0SMichael Lotz		int32				height;
175706aa76e2SIngo Weinhold		rgb_color			baseColor;
175806aa76e2SIngo Weinhold		rgb_color			lightColor;
1759b31df46fSAxel Dörfler		UtilityBitmap*		bitmap;
1760b31df46fSAxel Dörfler		decorator_bitmap*	next;
1761e13a79e0SMichael Lotz	};
1762e13a79e0SMichael Lotz
1763e13a79e0SMichael Lotz	static BLocker sBitmapListLock("decorator lock", true);
1764b31df46fSAxel Dörfler	static decorator_bitmap* sBitmapList = NULL;
176506aa76e2SIngo Weinhold
176606aa76e2SIngo Weinhold	ComponentColors colors;
1767bb2e9b06SClemens Zeidler	_GetComponentColors(item, colors, tab);
176806aa76e2SIngo Weinhold
1769e13a79e0SMichael Lotz	BAutolock locker(sBitmapListLock);
1770e13a79e0SMichael Lotz
1771e13a79e0SMichael Lotz	// search our list for a matching bitmap
17720d1d2de5SAxel Dörfler	// TODO: use a hash map instead?
1773b31df46fSAxel Dörfler	decorator_bitmap* current = sBitmapList;
1774e13a79e0SMichael Lotz	while (current) {
1775e13a79e0SMichael Lotz		if (current->item == item && current->down == down
177606aa76e2SIngo Weinhold			&& current->width == width && current->height == height
177706aa76e2SIngo Weinhold			&& current->baseColor == colors[COLOR_BUTTON]
177806aa76e2SIngo Weinhold			&& current->lightColor == colors[COLOR_BUTTON_LIGHT]) {
1779e13a79e0SMichael Lotz			return current->bitmap;
1780e13a79e0SMichael Lotz		}
1781e13a79e0SMichael Lotz
1782e13a79e0SMichael Lotz		current = current->next;
1783e13a79e0SMichael Lotz	}
1784e13a79e0SMichael Lotz
1785b31df46fSAxel Dörfler	static BitmapDrawingEngine* sBitmapDrawingEngine = NULL;
1786e13a79e0SMichael Lotz
1787e13a79e0SMichael Lotz	// didn't find any bitmap, create a new one
1788e13a79e0SMichael Lotz	if (sBitmapDrawingEngine == NULL)
1789e13a79e0SMichael Lotz		sBitmapDrawingEngine = new(std::nothrow) BitmapDrawingEngine();
1790e13a79e0SMichael Lotz	if (sBitmapDrawingEngine == NULL
1791e13a79e0SMichael Lotz		|| sBitmapDrawingEngine->SetSize(width, height) != B_OK)
1792e13a79e0SMichael Lotz		return NULL;
1793e13a79e0SMichael Lotz
1794e13a79e0SMichael Lotz	BRect rect(0, 0, width - 1, height - 1);
1795e13a79e0SMichael Lotz
179606aa76e2SIngo Weinhold	STRACE(("DefaultDecorator creating bitmap for %s %s at size %ldx%ld\n",
179706aa76e2SIngo Weinhold		item == COMPONENT_CLOSE_BUTTON ? "close" : "zoom",
1798e13a79e0SMichael Lotz		down ? "down" : "up", width, height));
1799e13a79e0SMichael Lotz	switch (item) {
180009b19da8SIngo Weinhold		case COMPONENT_CLOSE_BUTTON:
180106aa76e2SIngo Weinhold			_DrawBlendedRect(sBitmapDrawingEngine, rect, down, colors);
1802e13a79e0SMichael Lotz			break;
1803e13a79e0SMichael Lotz
180409b19da8SIngo Weinhold		case COMPONENT_ZOOM_BUTTON:
1805e13a79e0SMichael Lotz		{
1806ce5d6472SStephan Aßmus			// init the background
1807ce5d6472SStephan Aßmus			sBitmapDrawingEngine->FillRect(rect, B_TRANSPARENT_COLOR);
1808ce5d6472SStephan Aßmus
1809e13a79e0SMichael Lotz			float inset = floorf(width / 4.0);
1810e13a79e0SMichael Lotz			BRect zoomRect(rect);
1811e13a79e0SMichael Lotz			zoomRect.left += inset;
1812e13a79e0SMichael Lotz			zoomRect.top += inset;
181306aa76e2SIngo Weinhold			_DrawBlendedRect(sBitmapDrawingEngine, zoomRect, down, colors);
1814e13a79e0SMichael Lotz
1815e13a79e0SMichael Lotz			inset = floorf(width / 2.1);
1816e13a79e0SMichael Lotz			zoomRect = rect;
1817e13a79e0SMichael Lotz			zoomRect.right -= inset;
1818e13a79e0SMichael Lotz			zoomRect.bottom -= inset;
181906aa76e2SIngo Weinhold			_DrawBlendedRect(sBitmapDrawingEngine, zoomRect, down, colors);
1820e13a79e0SMichael Lotz			break;
1821e13a79e0SMichael Lotz		}
18220fd53296SIngo Weinhold
18230fd53296SIngo Weinhold		default:
18240fd53296SIngo Weinhold			break;
1825e13a79e0SMichael Lotz	}
1826e13a79e0SMichael Lotz
1827b31df46fSAxel Dörfler	UtilityBitmap* bitmap = sBitmapDrawingEngine->ExportToBitmap(width, height,
1828e13a79e0SMichael Lotz		B_RGB32);
1829e13a79e0SMichael Lotz	if (bitmap == NULL)
1830e13a79e0SMichael Lotz		return NULL;
1831e13a79e0SMichael Lotz
1832e13a79e0SMichael Lotz	// bitmap ready, put it into the list
1833b31df46fSAxel Dörfler	decorator_bitmap* entry = new(std::nothrow) decorator_bitmap;
1834e13a79e0SMichael Lotz	if (entry == NULL) {
1835e13a79e0SMichael Lotz		delete bitmap;
1836e13a79e0SMichael Lotz		return NULL;
1837e13a79e0SMichael Lotz	}
1838e13a79e0SMichael Lotz
1839e13a79e0S