xref: /haiku/src/kits/tracker/DialogPane.cpp (revision 8baeb63aa2722f9ea5ada1821e5cfe903d02aa16)
102be5353SAxel Dörfler /*
202be5353SAxel Dörfler Open Tracker License
302be5353SAxel Dörfler 
402be5353SAxel Dörfler Terms and Conditions
502be5353SAxel Dörfler 
602be5353SAxel Dörfler Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
702be5353SAxel Dörfler 
802be5353SAxel Dörfler Permission is hereby granted, free of charge, to any person obtaining a copy of
902be5353SAxel Dörfler this software and associated documentation files (the "Software"), to deal in
1002be5353SAxel Dörfler the Software without restriction, including without limitation the rights to
1102be5353SAxel Dörfler use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
1202be5353SAxel Dörfler of the Software, and to permit persons to whom the Software is furnished to do
1302be5353SAxel Dörfler so, subject to the following conditions:
1402be5353SAxel Dörfler 
1502be5353SAxel Dörfler The above copyright notice and this permission notice applies to all licensees
1602be5353SAxel Dörfler and shall be included in all copies or substantial portions of the Software.
1702be5353SAxel Dörfler 
1802be5353SAxel Dörfler THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1902be5353SAxel Dörfler IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
2002be5353SAxel Dörfler FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2102be5353SAxel Dörfler BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2202be5353SAxel Dörfler AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
2302be5353SAxel Dörfler WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2402be5353SAxel Dörfler 
2502be5353SAxel Dörfler Except as contained in this notice, the name of Be Incorporated shall not be
2602be5353SAxel Dörfler used in advertising or otherwise to promote the sale, use or other dealings in
2702be5353SAxel Dörfler this Software without prior written authorization from Be Incorporated.
2802be5353SAxel Dörfler 
2902be5353SAxel Dörfler Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
3002be5353SAxel Dörfler of Be Incorporated in the United States and other countries. Other brand product
3102be5353SAxel Dörfler names are registered trademarks or trademarks of their respective holders.
3202be5353SAxel Dörfler All rights reserved.
3302be5353SAxel Dörfler */
3402be5353SAxel Dörfler 
3502be5353SAxel Dörfler #include "DialogPane.h"
363e3d7acbSStephan Aßmus 
373e3d7acbSStephan Aßmus #include <LayoutUtils.h>
383e3d7acbSStephan Aßmus 
3902be5353SAxel Dörfler #include "Thread.h"
4002be5353SAxel Dörfler #include "Utilities.h"
413e3d7acbSStephan Aßmus #include "Window.h"
4202be5353SAxel Dörfler 
4381202ff5SAxel Dörfler 
4481202ff5SAxel Dörfler const uint32 kValueChanged = 'swch';
4581202ff5SAxel Dörfler 
4681202ff5SAxel Dörfler const rgb_color kNormalColor = {150, 150, 150, 255};
4781202ff5SAxel Dörfler const rgb_color kHighlightColor = {100, 100, 0, 255};
4881202ff5SAxel Dörfler 
4902be5353SAxel Dörfler 
5002be5353SAxel Dörfler static void
5102be5353SAxel Dörfler AddSelf(BView *self, BView *to)
5202be5353SAxel Dörfler {
5302be5353SAxel Dörfler 	to->AddChild(self);
5402be5353SAxel Dörfler }
5502be5353SAxel Dörfler 
5681202ff5SAxel Dörfler 
5781202ff5SAxel Dörfler void
5881202ff5SAxel Dörfler ViewList::RemoveAll(BView *)
5981202ff5SAxel Dörfler {
6081202ff5SAxel Dörfler 	EachListItemIgnoreResult(this, &BView::RemoveSelf);
6181202ff5SAxel Dörfler }
6281202ff5SAxel Dörfler 
6381202ff5SAxel Dörfler 
6402be5353SAxel Dörfler void
6502be5353SAxel Dörfler ViewList::AddAll(BView *toParent)
6602be5353SAxel Dörfler {
6702be5353SAxel Dörfler 	EachListItem(this, &AddSelf, toParent);
6802be5353SAxel Dörfler }
6902be5353SAxel Dörfler 
7002be5353SAxel Dörfler 
7181202ff5SAxel Dörfler //	#pragma mark -
7281202ff5SAxel Dörfler 
7381202ff5SAxel Dörfler 
7402be5353SAxel Dörfler DialogPane::DialogPane(BRect mode1Frame, BRect mode2Frame, int32 initialMode,
7502be5353SAxel Dörfler 	const char *name, uint32 followFlags, uint32 flags)
7602be5353SAxel Dörfler 	: BView(FrameForMode(initialMode, mode1Frame, mode2Frame, mode2Frame),
7702be5353SAxel Dörfler 		name, followFlags, flags),
7881202ff5SAxel Dörfler 	fMode(initialMode),
7902be5353SAxel Dörfler 	fMode1Frame(mode1Frame),
8002be5353SAxel Dörfler 	fMode2Frame(mode2Frame),
8102be5353SAxel Dörfler 	fMode3Frame(mode2Frame)
8202be5353SAxel Dörfler {
834f459891SAxel Dörfler 	SetMode(fMode, true);
8402be5353SAxel Dörfler }
8502be5353SAxel Dörfler 
8602be5353SAxel Dörfler 
8702be5353SAxel Dörfler DialogPane::DialogPane(BRect mode1Frame, BRect mode2Frame, BRect mode3Frame,
8802be5353SAxel Dörfler 	int32 initialMode, const char *name, uint32 followFlags, uint32 flags)
8902be5353SAxel Dörfler 	: BView(FrameForMode(initialMode, mode1Frame, mode2Frame, mode3Frame),
9002be5353SAxel Dörfler 		name, followFlags, flags),
9181202ff5SAxel Dörfler 	fMode(initialMode),
9202be5353SAxel Dörfler 	fMode1Frame(mode1Frame),
9302be5353SAxel Dörfler 	fMode2Frame(mode2Frame),
9402be5353SAxel Dörfler 	fMode3Frame(mode3Frame)
9502be5353SAxel Dörfler {
964f459891SAxel Dörfler 	SetMode(fMode, true);
9702be5353SAxel Dörfler }
9802be5353SAxel Dörfler 
9902be5353SAxel Dörfler 
10002be5353SAxel Dörfler DialogPane::~DialogPane()
10102be5353SAxel Dörfler {
10202be5353SAxel Dörfler 	fMode3Items.RemoveAll(this);
10302be5353SAxel Dörfler 	fMode2Items.RemoveAll(this);
10402be5353SAxel Dörfler }
10502be5353SAxel Dörfler 
10602be5353SAxel Dörfler 
10702be5353SAxel Dörfler void
10802be5353SAxel Dörfler DialogPane::SetMode(int32 mode, bool initialSetup)
10902be5353SAxel Dörfler {
11002be5353SAxel Dörfler 	ASSERT(mode < 3 && mode >= 0);
11102be5353SAxel Dörfler 
11202be5353SAxel Dörfler 	if (!initialSetup && mode == fMode)
11302be5353SAxel Dörfler 		return;
11402be5353SAxel Dörfler 
11502be5353SAxel Dörfler 	int32 oldMode = fMode;
11602be5353SAxel Dörfler 	fMode = mode;
11702be5353SAxel Dörfler 
11802be5353SAxel Dörfler 	bool followBottom = (ResizingMode() & B_FOLLOW_BOTTOM) != 0;
11902be5353SAxel Dörfler 	// if we are follow bottom, we will move ourselves, need to place us back
12002be5353SAxel Dörfler 	float bottomOffset = 0;
12181202ff5SAxel Dörfler 	if (followBottom && Window() != NULL)
12202be5353SAxel Dörfler 		bottomOffset = Window()->Bounds().bottom - Frame().bottom;
12302be5353SAxel Dörfler 
12402be5353SAxel Dörfler 	BRect newBounds(BoundsForMode(fMode));
12502be5353SAxel Dörfler 	if (!initialSetup)
12602be5353SAxel Dörfler 		ResizeParentWindow(fMode, oldMode);
12702be5353SAxel Dörfler 
12802be5353SAxel Dörfler 	ResizeTo(newBounds.Width(), newBounds.Height());
12902be5353SAxel Dörfler 
13002be5353SAxel Dörfler 	float delta = 0;
13181202ff5SAxel Dörfler 	if (followBottom && Window() != NULL)
13202be5353SAxel Dörfler 		delta = (Window()->Bounds().bottom - Frame().bottom) - bottomOffset;
13302be5353SAxel Dörfler 
13402be5353SAxel Dörfler 	if (delta != 0) {
13502be5353SAxel Dörfler 		MoveBy(0, delta);
13602be5353SAxel Dörfler 		if (fLatch && (fLatch->ResizingMode() & B_FOLLOW_BOTTOM))
13702be5353SAxel Dörfler 			fLatch->MoveBy(0, delta);
13802be5353SAxel Dörfler 	}
13902be5353SAxel Dörfler 
14002be5353SAxel Dörfler 	switch (fMode) {
14102be5353SAxel Dörfler 		case 0:
14202be5353SAxel Dörfler 		{
14302be5353SAxel Dörfler 			if (oldMode > 1)
14402be5353SAxel Dörfler 				fMode3Items.RemoveAll(this);
14502be5353SAxel Dörfler 			if (oldMode > 0)
14602be5353SAxel Dörfler 				fMode2Items.RemoveAll(this);
14702be5353SAxel Dörfler 
14802be5353SAxel Dörfler 			BView *separator = FindView("separatorLine");
14902be5353SAxel Dörfler 			if (separator) {
15002be5353SAxel Dörfler 				BRect frame(separator->Frame());
15102be5353SAxel Dörfler 				frame.InsetBy(-1, -1);
15202be5353SAxel Dörfler 				RemoveChild(separator);
15302be5353SAxel Dörfler 				Invalidate();
15402be5353SAxel Dörfler 			}
15502be5353SAxel Dörfler 
15602be5353SAxel Dörfler 			AddChild(new SeparatorLine(BPoint(newBounds.left, newBounds.top
15702be5353SAxel Dörfler 				+ newBounds.Height() / 2), newBounds.Width(), false,
15802be5353SAxel Dörfler 				"separatorLine"));
15902be5353SAxel Dörfler 			break;
16081202ff5SAxel Dörfler 		}
16102be5353SAxel Dörfler 		case 1:
16202be5353SAxel Dörfler 		{
16302be5353SAxel Dörfler 			if (oldMode > 1)
16402be5353SAxel Dörfler 				fMode3Items.RemoveAll(this);
16502be5353SAxel Dörfler 			else
16602be5353SAxel Dörfler 				fMode2Items.AddAll(this);
16702be5353SAxel Dörfler 
16802be5353SAxel Dörfler 			BView *separator = FindView("separatorLine");
16902be5353SAxel Dörfler 			if (separator) {
17002be5353SAxel Dörfler 				BRect frame(separator->Frame());
17102be5353SAxel Dörfler 				frame.InsetBy(-1, -1);
17202be5353SAxel Dörfler 				RemoveChild(separator);
17302be5353SAxel Dörfler 				Invalidate();
17402be5353SAxel Dörfler 			}
17502be5353SAxel Dörfler 			break;
17681202ff5SAxel Dörfler 		}
17702be5353SAxel Dörfler 		case 2:
17802be5353SAxel Dörfler 		{
17902be5353SAxel Dörfler 			fMode3Items.AddAll(this);
18002be5353SAxel Dörfler 			if (oldMode < 1)
18102be5353SAxel Dörfler 				fMode2Items.AddAll(this);
18202be5353SAxel Dörfler 
18302be5353SAxel Dörfler 			BView *separator = FindView("separatorLine");
18402be5353SAxel Dörfler 			if (separator) {
18502be5353SAxel Dörfler 				BRect frame(separator->Frame());
18602be5353SAxel Dörfler 				frame.InsetBy(-1, -1);
18702be5353SAxel Dörfler 				RemoveChild(separator);
18802be5353SAxel Dörfler 				Invalidate();
18902be5353SAxel Dörfler 			}
19002be5353SAxel Dörfler 			break;
19102be5353SAxel Dörfler 		}
19202be5353SAxel Dörfler 	}
19381202ff5SAxel Dörfler }
19481202ff5SAxel Dörfler 
19502be5353SAxel Dörfler 
19602be5353SAxel Dörfler void
19702be5353SAxel Dörfler DialogPane::AttachedToWindow()
19802be5353SAxel Dörfler {
19902be5353SAxel Dörfler 	BView *parent = Parent();
20002be5353SAxel Dörfler 	if (parent) {
20102be5353SAxel Dörfler 		SetViewColor(parent->ViewColor());
20202be5353SAxel Dörfler 		SetLowColor(parent->LowColor());
20302be5353SAxel Dörfler 	}
20402be5353SAxel Dörfler }
20502be5353SAxel Dörfler 
20681202ff5SAxel Dörfler 
20702be5353SAxel Dörfler void
20802be5353SAxel Dörfler DialogPane::ResizeParentWindow(int32 from, int32 to)
20902be5353SAxel Dörfler {
21002be5353SAxel Dörfler 	if (!Window())
21102be5353SAxel Dörfler 		return;
21202be5353SAxel Dörfler 
21302be5353SAxel Dörfler 	BRect oldBounds = BoundsForMode(from);
21402be5353SAxel Dörfler 	BRect newBounds = BoundsForMode(to);
21502be5353SAxel Dörfler 
21602be5353SAxel Dörfler 	BPoint by = oldBounds.RightBottom() - newBounds.RightBottom();
21702be5353SAxel Dörfler 	if (by != BPoint(0, 0))
21802be5353SAxel Dörfler 		Window()->ResizeBy(by.x, by.y);
21902be5353SAxel Dörfler }
22002be5353SAxel Dörfler 
22181202ff5SAxel Dörfler 
22202be5353SAxel Dörfler void
22302be5353SAxel Dörfler DialogPane::AddItem(BView *view, int32 toMode)
22402be5353SAxel Dörfler {
22502be5353SAxel Dörfler 	if (toMode == 1)
22602be5353SAxel Dörfler 		fMode2Items.AddItem(view);
22702be5353SAxel Dörfler 	else if (toMode == 2)
22802be5353SAxel Dörfler 		fMode3Items.AddItem(view);
22902be5353SAxel Dörfler 	if (fMode >= toMode)
23002be5353SAxel Dörfler 		AddChild(view);
23102be5353SAxel Dörfler }
23202be5353SAxel Dörfler 
23381202ff5SAxel Dörfler 
23402be5353SAxel Dörfler BRect
23502be5353SAxel Dörfler DialogPane::FrameForMode(int32 mode)
23602be5353SAxel Dörfler {
23702be5353SAxel Dörfler 	switch (mode) {
23802be5353SAxel Dörfler 		case 0:
23902be5353SAxel Dörfler 			return fMode1Frame;
24002be5353SAxel Dörfler 		case 1:
24102be5353SAxel Dörfler 			return fMode2Frame;
24202be5353SAxel Dörfler 		case 2:
24302be5353SAxel Dörfler 			return fMode3Frame;
24402be5353SAxel Dörfler 	}
24502be5353SAxel Dörfler 	return fMode1Frame;
24602be5353SAxel Dörfler }
24702be5353SAxel Dörfler 
24881202ff5SAxel Dörfler 
24902be5353SAxel Dörfler BRect
25002be5353SAxel Dörfler DialogPane::BoundsForMode(int32 mode)
25102be5353SAxel Dörfler {
25202be5353SAxel Dörfler 	BRect result;
25302be5353SAxel Dörfler 	switch (mode) {
25402be5353SAxel Dörfler 		case 0:
25502be5353SAxel Dörfler 			result = fMode1Frame;
25602be5353SAxel Dörfler 			break;
25702be5353SAxel Dörfler 		case 1:
25802be5353SAxel Dörfler 			result = fMode2Frame;
25902be5353SAxel Dörfler 			break;
26002be5353SAxel Dörfler 		case 2:
26102be5353SAxel Dörfler 			result = fMode3Frame;
26202be5353SAxel Dörfler 			break;
26302be5353SAxel Dörfler 	}
26402be5353SAxel Dörfler 	result.OffsetTo(0, 0);
26502be5353SAxel Dörfler 	return result;
26602be5353SAxel Dörfler }
26702be5353SAxel Dörfler 
26881202ff5SAxel Dörfler 
26902be5353SAxel Dörfler BRect
27002be5353SAxel Dörfler DialogPane::FrameForMode(int32 mode, BRect mode1Frame, BRect mode2Frame,
27102be5353SAxel Dörfler 	BRect mode3Frame)
27202be5353SAxel Dörfler {
27302be5353SAxel Dörfler 	switch (mode) {
27402be5353SAxel Dörfler 		case 0:
27502be5353SAxel Dörfler 			return mode1Frame;
27602be5353SAxel Dörfler 		case 1:
27702be5353SAxel Dörfler 			return mode2Frame;
27802be5353SAxel Dörfler 		case 2:
27902be5353SAxel Dörfler 			return mode3Frame;
28002be5353SAxel Dörfler 	}
28102be5353SAxel Dörfler 	return mode1Frame;
28202be5353SAxel Dörfler }
28302be5353SAxel Dörfler 
28402be5353SAxel Dörfler 
28502be5353SAxel Dörfler void
28602be5353SAxel Dörfler DialogPane::SetSwitch(BControl *control)
28702be5353SAxel Dörfler {
28802be5353SAxel Dörfler 	fLatch = control;
28902be5353SAxel Dörfler 	control->SetMessage(new BMessage(kValueChanged));
29002be5353SAxel Dörfler 	control->SetTarget(this);
29102be5353SAxel Dörfler }
29202be5353SAxel Dörfler 
29381202ff5SAxel Dörfler 
29402be5353SAxel Dörfler void
29502be5353SAxel Dörfler DialogPane::MessageReceived(BMessage *message)
29602be5353SAxel Dörfler {
29702be5353SAxel Dörfler 	if (message->what == kValueChanged) {
29802be5353SAxel Dörfler 		int32 value;
29902be5353SAxel Dörfler 		if (message->FindInt32("be:value", &value) == B_OK)
30002be5353SAxel Dörfler 			SetMode(value);
30102be5353SAxel Dörfler 	} else
30202be5353SAxel Dörfler 		_inherited::MessageReceived(message);
30302be5353SAxel Dörfler }
30402be5353SAxel Dörfler 
30581202ff5SAxel Dörfler 
3063e3d7acbSStephan Aßmus //	#pragma mark - PaneSwitch
30781202ff5SAxel Dörfler 
30881202ff5SAxel Dörfler 
30902be5353SAxel Dörfler PaneSwitch::PaneSwitch(BRect frame, const char *name, bool leftAligned,
31002be5353SAxel Dörfler 		uint32 resizeMask, uint32 flags)
3113e3d7acbSStephan Aßmus 	:
3123e3d7acbSStephan Aßmus 	BControl(frame, name, "", 0, resizeMask, flags),
31302be5353SAxel Dörfler 	fLeftAligned(leftAligned),
3143e3d7acbSStephan Aßmus 	fPressing(false),
3153e3d7acbSStephan Aßmus 	fLabelOn(NULL),
3163e3d7acbSStephan Aßmus 	fLabelOff(NULL)
31702be5353SAxel Dörfler {
31802be5353SAxel Dörfler }
31902be5353SAxel Dörfler 
32081202ff5SAxel Dörfler 
3213e3d7acbSStephan Aßmus PaneSwitch::PaneSwitch(const char *name, bool leftAligned, uint32 flags)
3223e3d7acbSStephan Aßmus 	:
3233e3d7acbSStephan Aßmus 	BControl(name, "", 0, flags),
3243e3d7acbSStephan Aßmus 	fLeftAligned(leftAligned),
3253e3d7acbSStephan Aßmus 	fPressing(false),
3263e3d7acbSStephan Aßmus 	fLabelOn(NULL),
3273e3d7acbSStephan Aßmus 	fLabelOff(NULL)
3283e3d7acbSStephan Aßmus {
3293e3d7acbSStephan Aßmus }
3303e3d7acbSStephan Aßmus 
3313e3d7acbSStephan Aßmus 
3323e3d7acbSStephan Aßmus PaneSwitch::~PaneSwitch()
3333e3d7acbSStephan Aßmus {
334*8baeb63aSStephan Aßmus 	free(fLabelOn);
335*8baeb63aSStephan Aßmus 	free(fLabelOff);
3363e3d7acbSStephan Aßmus }
3373e3d7acbSStephan Aßmus 
3383e3d7acbSStephan Aßmus 
3393e3d7acbSStephan Aßmus void
3403e3d7acbSStephan Aßmus PaneSwitch::Draw(BRect)
3413e3d7acbSStephan Aßmus {
3423e3d7acbSStephan Aßmus 	BRect bounds(Bounds());
3433e3d7acbSStephan Aßmus 
3443e3d7acbSStephan Aßmus 	// Draw the label, if any
3453e3d7acbSStephan Aßmus 	const char* label = fLabelOff;
3463e3d7acbSStephan Aßmus 	if (fLabelOn != NULL && Value() == B_CONTROL_ON)
3473e3d7acbSStephan Aßmus 		label = fLabelOn;
3483e3d7acbSStephan Aßmus 
3493e3d7acbSStephan Aßmus 	if (label != NULL) {
3503e3d7acbSStephan Aßmus 		BPoint point;
3513e3d7acbSStephan Aßmus 		float labelDist = sLatchSize + ceilf(sLatchSize / 2.0);
3523e3d7acbSStephan Aßmus 		if (fLeftAligned)
3533e3d7acbSStephan Aßmus 			point.x = labelDist;
3543e3d7acbSStephan Aßmus 		else
3553e3d7acbSStephan Aßmus 			point.x = bounds.right - labelDist - StringWidth(label);
3563e3d7acbSStephan Aßmus 
3573e3d7acbSStephan Aßmus 		font_height fontHeight;
3583e3d7acbSStephan Aßmus 		GetFontHeight(&fontHeight);
3593e3d7acbSStephan Aßmus 		point.y = (bounds.top + bounds.bottom
3603e3d7acbSStephan Aßmus 			- ceilf(fontHeight.ascent) - ceilf(fontHeight.descent)) / 2
3613e3d7acbSStephan Aßmus 			+ ceilf(fontHeight.ascent);
3623e3d7acbSStephan Aßmus 
3633e3d7acbSStephan Aßmus 		DrawString(label, point);
3643e3d7acbSStephan Aßmus 	}
3653e3d7acbSStephan Aßmus 
3663e3d7acbSStephan Aßmus 	// draw the latch
3673e3d7acbSStephan Aßmus 	if (fPressing)
3683e3d7acbSStephan Aßmus 		DrawInState(kPressed);
3693e3d7acbSStephan Aßmus 	else if (Value())
3703e3d7acbSStephan Aßmus 		DrawInState(kExpanded);
3713e3d7acbSStephan Aßmus 	else
3723e3d7acbSStephan Aßmus 		DrawInState(kCollapsed);
3733e3d7acbSStephan Aßmus 
3743e3d7acbSStephan Aßmus 	// ...and the focus indication
3753e3d7acbSStephan Aßmus 	if (!IsFocus() || !Window()->IsActive())
3763e3d7acbSStephan Aßmus 		return;
3773e3d7acbSStephan Aßmus 
3783e3d7acbSStephan Aßmus 	rgb_color markColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
3793e3d7acbSStephan Aßmus 
3803e3d7acbSStephan Aßmus 	BeginLineArray(2);
3813e3d7acbSStephan Aßmus 	AddLine(BPoint(bounds.left + 2, bounds.bottom - 1),
3823e3d7acbSStephan Aßmus 		BPoint(bounds.right - 2, bounds.bottom - 1), markColor);
3833e3d7acbSStephan Aßmus 	AddLine(BPoint(bounds.left + 2, bounds.bottom),
3843e3d7acbSStephan Aßmus 		BPoint(bounds.right - 2, bounds.bottom), kWhite);
3853e3d7acbSStephan Aßmus 	EndLineArray();
3863e3d7acbSStephan Aßmus }
3873e3d7acbSStephan Aßmus 
3883e3d7acbSStephan Aßmus 
3893e3d7acbSStephan Aßmus void
3903e3d7acbSStephan Aßmus PaneSwitch::MouseDown(BPoint)
3913e3d7acbSStephan Aßmus {
3923e3d7acbSStephan Aßmus 	if (!IsEnabled())
3933e3d7acbSStephan Aßmus 		return;
3943e3d7acbSStephan Aßmus 
3953e3d7acbSStephan Aßmus 	fPressing = true;
3963e3d7acbSStephan Aßmus 	MouseDownThread<PaneSwitch>::TrackMouse(this, &PaneSwitch::DoneTracking,
3973e3d7acbSStephan Aßmus 		&PaneSwitch::Track);
3983e3d7acbSStephan Aßmus 	Invalidate();
3993e3d7acbSStephan Aßmus }
4003e3d7acbSStephan Aßmus 
4013e3d7acbSStephan Aßmus 
4023e3d7acbSStephan Aßmus void
4033e3d7acbSStephan Aßmus PaneSwitch::GetPreferredSize(float* _width, float* _height)
4043e3d7acbSStephan Aßmus {
4053e3d7acbSStephan Aßmus 	BSize size = MinSize();
4063e3d7acbSStephan Aßmus 	if (_width)
4073e3d7acbSStephan Aßmus 		*_width = size.width;
4083e3d7acbSStephan Aßmus 	if (_height)
4093e3d7acbSStephan Aßmus 		*_height = size.height;
4103e3d7acbSStephan Aßmus }
4113e3d7acbSStephan Aßmus 
4123e3d7acbSStephan Aßmus 
4133e3d7acbSStephan Aßmus BSize
4143e3d7acbSStephan Aßmus PaneSwitch::MinSize()
4153e3d7acbSStephan Aßmus {
4163e3d7acbSStephan Aßmus 	BSize size;
4173e3d7acbSStephan Aßmus 	float onLabelWidth = StringWidth(fLabelOn);
4183e3d7acbSStephan Aßmus 	float offLabelWidth = StringWidth(fLabelOff);
4193e3d7acbSStephan Aßmus 	float labelWidth = max_c(onLabelWidth, offLabelWidth);
4203e3d7acbSStephan Aßmus 	size.width = sLatchSize;
4213e3d7acbSStephan Aßmus 	if (labelWidth > 0.0)
4223e3d7acbSStephan Aßmus 		size.width += ceilf(sLatchSize / 2.0) + labelWidth;
4233e3d7acbSStephan Aßmus 	font_height fontHeight;
4243e3d7acbSStephan Aßmus 	GetFontHeight(&fontHeight);
4253e3d7acbSStephan Aßmus 	size.height = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
4263e3d7acbSStephan Aßmus 	size.height = max_c(size.height, sLatchSize);
4273e3d7acbSStephan Aßmus 	return BLayoutUtils::ComposeSize(ExplicitMinSize(), size);
4283e3d7acbSStephan Aßmus }
4293e3d7acbSStephan Aßmus 
4303e3d7acbSStephan Aßmus 
4313e3d7acbSStephan Aßmus BSize
4323e3d7acbSStephan Aßmus PaneSwitch::MaxSize()
4333e3d7acbSStephan Aßmus {
4343e3d7acbSStephan Aßmus 	return BLayoutUtils::ComposeSize(ExplicitMaxSize(), MinSize());
4353e3d7acbSStephan Aßmus }
4363e3d7acbSStephan Aßmus 
4373e3d7acbSStephan Aßmus 
4383e3d7acbSStephan Aßmus BSize
4393e3d7acbSStephan Aßmus PaneSwitch::PreferredSize()
4403e3d7acbSStephan Aßmus {
4413e3d7acbSStephan Aßmus 	return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), MinSize());
4423e3d7acbSStephan Aßmus }
4433e3d7acbSStephan Aßmus 
4443e3d7acbSStephan Aßmus 
4453e3d7acbSStephan Aßmus void
4463e3d7acbSStephan Aßmus PaneSwitch::SetLabels(const char* labelOn, const char* labelOff)
4473e3d7acbSStephan Aßmus {
4483e3d7acbSStephan Aßmus 	free(fLabelOn);
4493e3d7acbSStephan Aßmus 	free(fLabelOff);
4503e3d7acbSStephan Aßmus 
4513e3d7acbSStephan Aßmus 	if (labelOn != NULL)
4523e3d7acbSStephan Aßmus 		fLabelOn = strdup(labelOn);
4533e3d7acbSStephan Aßmus 	else
4543e3d7acbSStephan Aßmus 		fLabelOn = NULL;
4553e3d7acbSStephan Aßmus 
4563e3d7acbSStephan Aßmus 	if (labelOff != NULL)
4573e3d7acbSStephan Aßmus 		fLabelOff = strdup(labelOff);
4583e3d7acbSStephan Aßmus 	else
4593e3d7acbSStephan Aßmus 		fLabelOff = NULL;
4603e3d7acbSStephan Aßmus 
4613e3d7acbSStephan Aßmus 	Invalidate();
4623e3d7acbSStephan Aßmus 	InvalidateLayout();
4633e3d7acbSStephan Aßmus }
4643e3d7acbSStephan Aßmus 
4653e3d7acbSStephan Aßmus 
46602be5353SAxel Dörfler void
46702be5353SAxel Dörfler PaneSwitch::DoneTracking(BPoint point)
46802be5353SAxel Dörfler {
46902be5353SAxel Dörfler 	BRect bounds(Bounds());
47002be5353SAxel Dörfler 	bounds.InsetBy(-3, -3);
47102be5353SAxel Dörfler 
47202be5353SAxel Dörfler 	fPressing = false;
47302be5353SAxel Dörfler 	Invalidate();
47402be5353SAxel Dörfler 	if (bounds.Contains(point)) {
47502be5353SAxel Dörfler 		SetValue(!Value());
47602be5353SAxel Dörfler 		Invoke();
47702be5353SAxel Dörfler 	}
47802be5353SAxel Dörfler }
47902be5353SAxel Dörfler 
48081202ff5SAxel Dörfler 
48102be5353SAxel Dörfler void
48202be5353SAxel Dörfler PaneSwitch::Track(BPoint point, uint32)
48302be5353SAxel Dörfler {
48402be5353SAxel Dörfler 	BRect bounds(Bounds());
48502be5353SAxel Dörfler 	bounds.InsetBy(-3, -3);
48602be5353SAxel Dörfler 
48702be5353SAxel Dörfler 	bool newPressing = bounds.Contains(point);
48802be5353SAxel Dörfler 	if (newPressing != fPressing) {
48902be5353SAxel Dörfler 		fPressing = newPressing;
49002be5353SAxel Dörfler 		Invalidate();
49102be5353SAxel Dörfler 	}
49202be5353SAxel Dörfler }
49302be5353SAxel Dörfler 
49402be5353SAxel Dörfler 
49502be5353SAxel Dörfler void
49602be5353SAxel Dörfler PaneSwitch::DrawInState(PaneSwitch::State state)
49702be5353SAxel Dörfler {
49802be5353SAxel Dörfler 	BRect rect(0, 0, 10, 10);
49902be5353SAxel Dörfler 
50002be5353SAxel Dörfler 	rgb_color outlineColor = {0, 0, 0, 255};
50102be5353SAxel Dörfler 	rgb_color middleColor = state == kPressed ? kHighlightColor : kNormalColor;
50202be5353SAxel Dörfler 
50302be5353SAxel Dörfler 	SetDrawingMode(B_OP_COPY);
50402be5353SAxel Dörfler 
50502be5353SAxel Dörfler 	switch (state) {
50602be5353SAxel Dörfler 		case kCollapsed:
50702be5353SAxel Dörfler 			BeginLineArray(6);
50802be5353SAxel Dörfler 
50902be5353SAxel Dörfler 			if (fLeftAligned) {
51002be5353SAxel Dörfler 				AddLine(BPoint(rect.left + 3, rect.top + 1),
51102be5353SAxel Dörfler 					BPoint(rect.left + 3, rect.bottom - 1), outlineColor);
51202be5353SAxel Dörfler 				AddLine(BPoint(rect.left + 3, rect.top + 1),
51302be5353SAxel Dörfler 					BPoint(rect.left + 7, rect.top + 5), outlineColor);
51402be5353SAxel Dörfler 				AddLine(BPoint(rect.left + 7, rect.top + 5),
51502be5353SAxel Dörfler 					BPoint(rect.left + 3, rect.bottom - 1), outlineColor);
51602be5353SAxel Dörfler 
51702be5353SAxel Dörfler 				AddLine(BPoint(rect.left + 4, rect.top + 3),
51802be5353SAxel Dörfler 					BPoint(rect.left + 4, rect.bottom - 3), middleColor);
51902be5353SAxel Dörfler 				AddLine(BPoint(rect.left + 5, rect.top + 4),
52002be5353SAxel Dörfler 					BPoint(rect.left + 5, rect.bottom - 4), middleColor);
52102be5353SAxel Dörfler 				AddLine(BPoint(rect.left + 5, rect.top + 5),
52202be5353SAxel Dörfler 					BPoint(rect.left + 6, rect.top + 5), middleColor);
52302be5353SAxel Dörfler 			} else {
52402be5353SAxel Dörfler 				AddLine(BPoint(rect.right - 3, rect.top + 1),
52502be5353SAxel Dörfler 					BPoint(rect.right - 3, rect.bottom - 1), outlineColor);
52602be5353SAxel Dörfler 				AddLine(BPoint(rect.right - 3, rect.top + 1),
52702be5353SAxel Dörfler 					BPoint(rect.right - 7, rect.top + 5), outlineColor);
52802be5353SAxel Dörfler 				AddLine(BPoint(rect.right - 7, rect.top + 5),
52902be5353SAxel Dörfler 					BPoint(rect.right - 3, rect.bottom - 1), outlineColor);
53002be5353SAxel Dörfler 
53102be5353SAxel Dörfler 				AddLine(BPoint(rect.right - 4, rect.top + 3),
53202be5353SAxel Dörfler 					BPoint(rect.right - 4, rect.bottom - 3), middleColor);
53302be5353SAxel Dörfler 				AddLine(BPoint(rect.right - 5, rect.top + 4),
53402be5353SAxel Dörfler 					BPoint(rect.right - 5, rect.bottom - 4), middleColor);
53502be5353SAxel Dörfler 				AddLine(BPoint(rect.right - 5, rect.top + 5),
53602be5353SAxel Dörfler 					BPoint(rect.right - 6, rect.top + 5), middleColor);
53702be5353SAxel Dörfler 			}
53802be5353SAxel Dörfler 			EndLineArray();
53902be5353SAxel Dörfler 			break;
54002be5353SAxel Dörfler 
54102be5353SAxel Dörfler 		case kPressed:
54202be5353SAxel Dörfler 			BeginLineArray(7);
54302be5353SAxel Dörfler 			if (fLeftAligned) {
54402be5353SAxel Dörfler 				AddLine(BPoint(rect.left + 1, rect.top + 7),
54502be5353SAxel Dörfler 					BPoint(rect.left + 7, rect.top + 7), outlineColor);
54602be5353SAxel Dörfler 				AddLine(BPoint(rect.left + 7, rect.top + 1),
54702be5353SAxel Dörfler 					BPoint(rect.left + 7, rect.top + 7), outlineColor);
54802be5353SAxel Dörfler 				AddLine(BPoint(rect.left + 1, rect.top + 7),
54902be5353SAxel Dörfler 					BPoint(rect.left + 7, rect.top + 1), outlineColor);
55002be5353SAxel Dörfler 
55102be5353SAxel Dörfler 				AddLine(BPoint(rect.left + 3, rect.top + 6),
55202be5353SAxel Dörfler 					BPoint(rect.left + 6, rect.top + 6), middleColor);
55302be5353SAxel Dörfler 				AddLine(BPoint(rect.left + 4, rect.top + 5),
55402be5353SAxel Dörfler 					BPoint(rect.left + 6, rect.top + 5), middleColor);
55502be5353SAxel Dörfler 				AddLine(BPoint(rect.left + 5, rect.top + 4),
55602be5353SAxel Dörfler 					BPoint(rect.left + 6, rect.top + 4), middleColor);
55702be5353SAxel Dörfler 				AddLine(BPoint(rect.left + 6, rect.top + 3),
55802be5353SAxel Dörfler 					BPoint(rect.left + 6, rect.top + 4), middleColor);
55902be5353SAxel Dörfler 			} else {
56002be5353SAxel Dörfler 				AddLine(BPoint(rect.right - 1, rect.top + 7),
56102be5353SAxel Dörfler 					BPoint(rect.right - 7, rect.top + 7), outlineColor);
56202be5353SAxel Dörfler 				AddLine(BPoint(rect.right - 7, rect.top + 1),
56302be5353SAxel Dörfler 					BPoint(rect.right - 7, rect.top + 7), outlineColor);
56402be5353SAxel Dörfler 				AddLine(BPoint(rect.right - 1, rect.top + 7),
56502be5353SAxel Dörfler 					BPoint(rect.right - 7, rect.top + 1), outlineColor);
56602be5353SAxel Dörfler 
56702be5353SAxel Dörfler 				AddLine(BPoint(rect.right - 3, rect.top + 6),
56802be5353SAxel Dörfler 					BPoint(rect.right - 6, rect.top + 6), middleColor);
56902be5353SAxel Dörfler 				AddLine(BPoint(rect.right - 4, rect.top + 5),
57002be5353SAxel Dörfler 					BPoint(rect.right - 6, rect.top + 5), middleColor);
57102be5353SAxel Dörfler 				AddLine(BPoint(rect.right - 5, rect.top + 4),
57202be5353SAxel Dörfler 					BPoint(rect.right - 6, rect.top + 4), middleColor);
57302be5353SAxel Dörfler 				AddLine(BPoint(rect.right - 6, rect.top + 3),
57402be5353SAxel Dörfler 					BPoint(rect.right - 6, rect.top + 4), middleColor);
57502be5353SAxel Dörfler 			}
57602be5353SAxel Dörfler 			EndLineArray();
57702be5353SAxel Dörfler 			break;
57802be5353SAxel Dörfler 
57902be5353SAxel Dörfler 		case kExpanded:
58002be5353SAxel Dörfler 			BeginLineArray(6);
58102be5353SAxel Dörfler 			AddLine(BPoint(rect.left + 1, rect.top + 3),
58202be5353SAxel Dörfler 				BPoint(rect.right - 1, rect.top + 3), outlineColor);
58302be5353SAxel Dörfler 			AddLine(BPoint(rect.left + 1, rect.top + 3),
58402be5353SAxel Dörfler 				BPoint(rect.left + 5, rect.top + 7), outlineColor);
58502be5353SAxel Dörfler 			AddLine(BPoint(rect.left + 5, rect.top + 7),
58602be5353SAxel Dörfler 				BPoint(rect.right - 1, rect.top + 3), outlineColor);
58702be5353SAxel Dörfler 
58802be5353SAxel Dörfler 			AddLine(BPoint(rect.left + 3, rect.top + 4),
58902be5353SAxel Dörfler 				BPoint(rect.right - 3, rect.top + 4), middleColor);
59002be5353SAxel Dörfler 			AddLine(BPoint(rect.left + 4, rect.top + 5),
59102be5353SAxel Dörfler 				BPoint(rect.right - 4, rect.top + 5), middleColor);
59202be5353SAxel Dörfler 			AddLine(BPoint(rect.left + 5, rect.top + 5),
59302be5353SAxel Dörfler 				BPoint(rect.left + 5, rect.top + 6), middleColor);
59402be5353SAxel Dörfler 			EndLineArray();
59502be5353SAxel Dörfler 			break;
59602be5353SAxel Dörfler 	}
59702be5353SAxel Dörfler }
59802be5353SAxel Dörfler 
599