SectionEdit.cpp revision 323ba9b7
1fd7c0c2eSStephan Aßmus/*
2323ba9b7SRyan Leavengood * Copyright 2004-2011, Haiku, Inc. All Rights Reserved.
3fd7c0c2eSStephan Aßmus * Distributed under the terms of the MIT License.
4fd7c0c2eSStephan Aßmus *
5fd7c0c2eSStephan Aßmus * Authors:
600826781SKarsten Heimrich *		Mike Berg <mike@berg-net.us>
7fd7c0c2eSStephan Aßmus *		Julun <host.haiku@gmx.de>
8323ba9b7SRyan Leavengood *		Hamish Morrison <hamish@lavabit.com>
9fd7c0c2eSStephan Aßmus */
1026c008b7SPhil Greenway
1190433c43SOliver Tappe
1226c008b7SPhil Greenway#include "SectionEdit.h"
1326c008b7SPhil Greenway
14fd7c0c2eSStephan Aßmus#include <Bitmap.h>
1502b73236SAxel Dörfler#include <ControlLook.h>
16323ba9b7SRyan Leavengood#include <LayoutUtils.h>
17fd7c0c2eSStephan Aßmus#include <List.h>
18fd7c0c2eSStephan Aßmus#include <Window.h>
1926c008b7SPhil Greenway
2002b73236SAxel Dörfler#include "TimeMessages.h"
2102b73236SAxel Dörfler
2226c008b7SPhil Greenway
23fd7c0c2eSStephan Aßmusconst uint32 kArrowAreaWidth = 16;
2426c008b7SPhil Greenway
2526c008b7SPhil Greenway
26323ba9b7SRyan LeavengoodTSectionEdit::TSectionEdit(const char* name, uint32 sections)
2702b73236SAxel Dörfler	:
28323ba9b7SRyan Leavengood	BControl(name, NULL, NULL, B_WILL_DRAW | B_NAVIGABLE),
2902b73236SAxel Dörfler	fFocus(-1),
30420e9637SOliver Tappe	fSectionCount(sections),
31420e9637SOliver Tappe	fHoldValue(0)
3226c008b7SPhil Greenway{
3326c008b7SPhil Greenway}
3426c008b7SPhil Greenway
3526c008b7SPhil Greenway
3626c008b7SPhil GreenwayTSectionEdit::~TSectionEdit()
3726c008b7SPhil Greenway{
3826c008b7SPhil Greenway}
3926c008b7SPhil Greenway
4026c008b7SPhil Greenway
4126c008b7SPhil Greenwayvoid
4226c008b7SPhil GreenwayTSectionEdit::AttachedToWindow()
4326c008b7SPhil Greenway{
4402b73236SAxel Dörfler	if (Parent())
4526c008b7SPhil Greenway		SetViewColor(Parent()->ViewColor());
4626c008b7SPhil Greenway}
4726c008b7SPhil Greenway
4826c008b7SPhil Greenway
4926c008b7SPhil Greenwayvoid
5000826781SKarsten HeimrichTSectionEdit::Draw(BRect updateRect)
5126c008b7SPhil Greenway{
5202b73236SAxel Dörfler	DrawBorder(updateRect);
5302b73236SAxel Dörfler
5400826781SKarsten Heimrich	for (uint32 idx = 0; idx < fSectionCount; idx++) {
55323ba9b7SRyan Leavengood		DrawSection(idx, FrameForSection(idx),
56323ba9b7SRyan Leavengood			((uint32)fFocus == idx) && IsFocus());
5790433c43SOliver Tappe		if (idx < fSectionCount - 1)
58323ba9b7SRyan Leavengood			DrawSeparator(idx, FrameForSeparator(idx));
5926c008b7SPhil Greenway	}
6026c008b7SPhil Greenway}
6126c008b7SPhil Greenway
6226c008b7SPhil Greenway
6326c008b7SPhil Greenwayvoid
6426c008b7SPhil GreenwayTSectionEdit::MouseDown(BPoint where)
6526c008b7SPhil Greenway{
6626c008b7SPhil Greenway	MakeFocus(true);
6702b73236SAxel Dörfler
68fd7c0c2eSStephan Aßmus	if (fUpRect.Contains(where))
6926c008b7SPhil Greenway		DoUpPress();
70fd7c0c2eSStephan Aßmus	else if (fDownRect.Contains(where))
7126c008b7SPhil Greenway		DoDownPress();
72323ba9b7SRyan Leavengood	else if (fSectionCount > 0) {
73fd7c0c2eSStephan Aßmus		for (uint32 idx = 0; idx < fSectionCount; idx++) {
74323ba9b7SRyan Leavengood			if (FrameForSection(idx).Contains(where)) {
7526c008b7SPhil Greenway				SectionFocus(idx);
7626c008b7SPhil Greenway				return;
7726c008b7SPhil Greenway			}
7802b73236SAxel Dörfler		}
7926c008b7SPhil Greenway	}
8026c008b7SPhil Greenway}
8126c008b7SPhil Greenway
8226c008b7SPhil Greenway
83323ba9b7SRyan LeavengoodBSize
84323ba9b7SRyan LeavengoodTSectionEdit::MaxSize()
85323ba9b7SRyan Leavengood{
86323ba9b7SRyan Leavengood	return BLayoutUtils::ComposeSize(ExplicitMaxSize(),
87323ba9b7SRyan Leavengood		BSize(B_SIZE_UNLIMITED, PreferredHeight()));
88323ba9b7SRyan Leavengood}
89323ba9b7SRyan Leavengood
90323ba9b7SRyan Leavengood
91323ba9b7SRyan LeavengoodBSize
92323ba9b7SRyan LeavengoodTSectionEdit::MinSize()
93323ba9b7SRyan Leavengood{
94323ba9b7SRyan Leavengood	BSize minSize;
95323ba9b7SRyan Leavengood	minSize.height = PreferredHeight();
96323ba9b7SRyan Leavengood	minSize.width = (SeparatorWidth() + MinSectionWidth())
97323ba9b7SRyan Leavengood		* fSectionCount;
98323ba9b7SRyan Leavengood	return BLayoutUtils::ComposeSize(ExplicitMinSize(),
99323ba9b7SRyan Leavengood		minSize);
100323ba9b7SRyan Leavengood}
101323ba9b7SRyan Leavengood
102323ba9b7SRyan Leavengood
103323ba9b7SRyan LeavengoodBSize
104323ba9b7SRyan LeavengoodTSectionEdit::PreferredSize()
105323ba9b7SRyan Leavengood{
106323ba9b7SRyan Leavengood	return BLayoutUtils::ComposeSize(ExplicitPreferredSize(),
107323ba9b7SRyan Leavengood		MinSize());
108323ba9b7SRyan Leavengood}
109323ba9b7SRyan Leavengood
110323ba9b7SRyan Leavengood
111323ba9b7SRyan LeavengoodBRect
112323ba9b7SRyan LeavengoodTSectionEdit::FrameForSection(uint32 index)
113323ba9b7SRyan Leavengood{
114323ba9b7SRyan Leavengood	BRect area = SectionArea();
115323ba9b7SRyan Leavengood	float sepWidth = SeparatorWidth();
116323ba9b7SRyan Leavengood
117323ba9b7SRyan Leavengood	float width = (area.Width() -
118323ba9b7SRyan Leavengood		sepWidth * (fSectionCount - 1))
119323ba9b7SRyan Leavengood		/ fSectionCount;
120323ba9b7SRyan Leavengood	area.left += index * (width + sepWidth);
121323ba9b7SRyan Leavengood	area.right = area.left + width;
122323ba9b7SRyan Leavengood
123323ba9b7SRyan Leavengood	return area;
124323ba9b7SRyan Leavengood}
125323ba9b7SRyan Leavengood
126323ba9b7SRyan Leavengood
127323ba9b7SRyan LeavengoodBRect
128323ba9b7SRyan LeavengoodTSectionEdit::FrameForSeparator(uint32 index)
129323ba9b7SRyan Leavengood{
130323ba9b7SRyan Leavengood	BRect area = SectionArea();
131323ba9b7SRyan Leavengood	float sepWidth = SeparatorWidth();
132323ba9b7SRyan Leavengood
133323ba9b7SRyan Leavengood	float width = (area.Width() -
134323ba9b7SRyan Leavengood		sepWidth * (fSectionCount - 1))
135323ba9b7SRyan Leavengood		/ fSectionCount;
136323ba9b7SRyan Leavengood	area.left += (index + 1) * width + index * sepWidth;
137323ba9b7SRyan Leavengood	area.right = area.left + sepWidth;
138323ba9b7SRyan Leavengood
139323ba9b7SRyan Leavengood	return area;
140323ba9b7SRyan Leavengood}
141323ba9b7SRyan Leavengood
142323ba9b7SRyan Leavengood
14300826781SKarsten Heimrichvoid
14400826781SKarsten HeimrichTSectionEdit::MakeFocus(bool focused)
14500826781SKarsten Heimrich{
14600826781SKarsten Heimrich	if (focused == IsFocus())
14700826781SKarsten Heimrich		return;
14800826781SKarsten Heimrich
14900826781SKarsten Heimrich	BControl::MakeFocus(focused);
15002b73236SAxel Dörfler
15100826781SKarsten Heimrich	if (fFocus == -1)
15200826781SKarsten Heimrich		SectionFocus(0);
15300826781SKarsten Heimrich	else
15400826781SKarsten Heimrich		SectionFocus(fFocus);
15500826781SKarsten Heimrich}
15600826781SKarsten Heimrich
15700826781SKarsten Heimrich
15826c008b7SPhil Greenwayvoid
1596d6408d6SOliver TappeTSectionEdit::KeyDown(const char* bytes, int32 numbytes)
16026c008b7SPhil Greenway{
161fd7c0c2eSStephan Aßmus	if (fFocus == -1)
16226c008b7SPhil Greenway		SectionFocus(0);
16302b73236SAxel Dörfler
16426c008b7SPhil Greenway	switch (bytes[0]) {
16526c008b7SPhil Greenway		case B_LEFT_ARROW:
166fd7c0c2eSStephan Aßmus			fFocus -= 1;
167fd7c0c2eSStephan Aßmus			if (fFocus < 0)
16890433c43SOliver Tappe				fFocus = fSectionCount - 1;
169fd7c0c2eSStephan Aßmus			SectionFocus(fFocus);
17002b73236SAxel Dörfler			break;
17102b73236SAxel Dörfler
17226c008b7SPhil Greenway		case B_RIGHT_ARROW:
173fd7c0c2eSStephan Aßmus			fFocus += 1;
174fd7c0c2eSStephan Aßmus			if ((uint32)fFocus >= fSectionCount)
175fd7c0c2eSStephan Aßmus				fFocus = 0;
176fd7c0c2eSStephan Aßmus			SectionFocus(fFocus);
17702b73236SAxel Dörfler			break;
17802b73236SAxel Dörfler
17926c008b7SPhil Greenway		case B_UP_ARROW:
18026c008b7SPhil Greenway			DoUpPress();
18102b73236SAxel Dörfler			break;
18202b73236SAxel Dörfler
18326c008b7SPhil Greenway		case B_DOWN_ARROW:
18426c008b7SPhil Greenway			DoDownPress();
18502b73236SAxel Dörfler			break;
18602b73236SAxel Dörfler
18726c008b7SPhil Greenway		default:
18826c008b7SPhil Greenway			BControl::KeyDown(bytes, numbytes);
18902b73236SAxel Dörfler			break;
19026c008b7SPhil Greenway	}
19126c008b7SPhil Greenway	Draw(Bounds());
19226c008b7SPhil Greenway}
19326c008b7SPhil Greenway
19426c008b7SPhil Greenway
19526c008b7SPhil Greenwayvoid
19626c008b7SPhil GreenwayTSectionEdit::DispatchMessage()
19726c008b7SPhil Greenway{
19800826781SKarsten Heimrich	BMessage message(H_USER_CHANGE);
19900826781SKarsten Heimrich	BuildDispatch(&message);
20000826781SKarsten Heimrich	Window()->PostMessage(&message);
20126c008b7SPhil Greenway}
20226c008b7SPhil Greenway
20326c008b7SPhil Greenway
20426c008b7SPhil Greenwayuint32
20526c008b7SPhil GreenwayTSectionEdit::CountSections() const
20626c008b7SPhil Greenway{
207323ba9b7SRyan Leavengood	return fSectionCount;
20826c008b7SPhil Greenway}
20926c008b7SPhil Greenway
21026c008b7SPhil Greenway
21126c008b7SPhil Greenwayint32
21226c008b7SPhil GreenwayTSectionEdit::FocusIndex() const
21326c008b7SPhil Greenway{
214fd7c0c2eSStephan Aßmus	return fFocus;
21526c008b7SPhil Greenway}
21626c008b7SPhil Greenway
21726c008b7SPhil Greenway
218323ba9b7SRyan LeavengoodBRect
219323ba9b7SRyan LeavengoodTSectionEdit::SectionArea() const
22026c008b7SPhil Greenway{
221323ba9b7SRyan Leavengood	BRect sectionArea = Bounds().InsetByCopy(2, 2);
222323ba9b7SRyan Leavengood	sectionArea.right -= kArrowAreaWidth;
223323ba9b7SRyan Leavengood	return sectionArea;
22426c008b7SPhil Greenway}
22526c008b7SPhil Greenway
22626c008b7SPhil Greenway
22726c008b7SPhil Greenwayvoid
22802b73236SAxel DörflerTSectionEdit::DrawBorder(const BRect& updateRect)
22926c008b7SPhil Greenway{
23002b73236SAxel Dörfler	BRect bounds(Bounds());
231420e9637SOliver Tappe	bool showFocus = (IsFocus() && Window() && Window()->IsActive());
232fd7c0c2eSStephan Aßmus
23302b73236SAxel Dörfler	be_control_look->DrawBorder(this, bounds, updateRect, ViewColor(),
234420e9637SOliver Tappe		B_FANCY_BORDER, showFocus ? BControlLook::B_FOCUSED : 0);
23526c008b7SPhil Greenway
23602b73236SAxel Dörfler	// draw up/down control
23726c008b7SPhil Greenway
23802b73236SAxel Dörfler	bounds.left = bounds.right - kArrowAreaWidth;
23902b73236SAxel Dörfler	bounds.right = Bounds().right - 2;
24002b73236SAxel Dörfler	fUpRect.Set(bounds.left + 3, bounds.top + 2, bounds.right,
24102b73236SAxel Dörfler		bounds.bottom / 2.0);
24202b73236SAxel Dörfler	fDownRect = fUpRect.OffsetByCopy(0, fUpRect.Height() + 2);
24302b73236SAxel Dörfler
244323ba9b7SRyan Leavengood	BPoint middle(floorf(fUpRect.left + fUpRect.Width() / 2),
245323ba9b7SRyan Leavengood		fUpRect.top + 1);
24602b73236SAxel Dörfler	BPoint left(fUpRect.left + 3, fUpRect.bottom - 1);
24702b73236SAxel Dörfler	BPoint right(left.x + 2 * (middle.x - left.x), fUpRect.bottom - 1);
24802b73236SAxel Dörfler
24902b73236SAxel Dörfler	SetPenSize(2);
250323ba9b7SRyan Leavengood	SetLowColor(ViewColor());
25102b73236SAxel Dörfler
25202b73236SAxel Dörfler	if (updateRect.Intersects(fUpRect)) {
25302b73236SAxel Dörfler		FillRect(fUpRect, B_SOLID_LOW);
25402b73236SAxel Dörfler		BeginLineArray(2);
25502b73236SAxel Dörfler			AddLine(left, middle, HighColor());
25602b73236SAxel Dörfler			AddLine(middle, right, HighColor());
25702b73236SAxel Dörfler		EndLineArray();
25802b73236SAxel Dörfler	}
25902b73236SAxel Dörfler	if (updateRect.Intersects(fDownRect)) {
26002b73236SAxel Dörfler		middle.y = fDownRect.bottom - 1;
26102b73236SAxel Dörfler		left.y = right.y = fDownRect.top + 1;
26202b73236SAxel Dörfler
26302b73236SAxel Dörfler		FillRect(fDownRect, B_SOLID_LOW);
26402b73236SAxel Dörfler		BeginLineArray(2);
26502b73236SAxel Dörfler			AddLine(left, middle, HighColor());
26602b73236SAxel Dörfler			AddLine(middle, right, HighColor());
26702b73236SAxel Dörfler		EndLineArray();
26826c008b7SPhil Greenway	}
26926c008b7SPhil Greenway
27002b73236SAxel Dörfler	SetPenSize(1);
27126c008b7SPhil Greenway}
272