1/*
2Open Tracker License
3
4Terms and Conditions
5
6Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining a copy of
9this software and associated documentation files (the "Software"), to deal in
10the Software without restriction, including without limitation the rights to
11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12of the Software, and to permit persons to whom the Software is furnished to do
13so, subject to the following conditions:
14
15The above copyright notice and this permission notice applies to all licensees
16and shall be included in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25Except as contained in this notice, the name of Be Incorporated shall not be
26used in advertising or otherwise to promote the sale, use or other dealings in
27this Software without prior written authorization from Be Incorporated.
28
29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30of Be Incorporated in the United States and other countries. Other brand product
31names are registered trademarks or trademarks of their respective holders.
32All rights reserved.
33*/
34
35
36#include "DialogPane.h"
37
38#include <ControlLook.h>
39#include <LayoutUtils.h>
40
41#include "Utilities.h"
42#include "Window.h"
43
44
45const rgb_color kNormalColor = {150, 150, 150, 255};
46const rgb_color kHighlightColor = {100, 100, 0, 255};
47
48
49//	#pragma mark - PaneSwitch
50
51
52PaneSwitch::PaneSwitch(BRect frame, const char* name, bool leftAligned,
53		uint32 resizeMask, uint32 flags)
54	:
55	BControl(frame, name, "", 0, resizeMask, flags),
56	fLeftAligned(leftAligned),
57	fPressing(false),
58	fLabelOn(NULL),
59	fLabelOff(NULL)
60{
61}
62
63
64PaneSwitch::PaneSwitch(const char* name, bool leftAligned, uint32 flags)
65	:
66	BControl(name, "", 0, flags),
67	fLeftAligned(leftAligned),
68	fPressing(false),
69	fLabelOn(NULL),
70	fLabelOff(NULL)
71{
72}
73
74
75PaneSwitch::~PaneSwitch()
76{
77	free(fLabelOn);
78	free(fLabelOff);
79}
80
81
82void
83PaneSwitch::Draw(BRect)
84{
85	BRect bounds(Bounds());
86
87	// Draw the label, if any
88	const char* label = fLabelOff;
89	if (fLabelOn != NULL && Value() == B_CONTROL_ON)
90		label = fLabelOn;
91
92	if (label != NULL) {
93		BPoint point;
94		float latchSize = be_plain_font->Size();
95		float labelDist = latchSize + ceilf(latchSize / 2.0);
96		if (fLeftAligned)
97			point.x = labelDist;
98		else
99			point.x = bounds.right - labelDist - StringWidth(label);
100
101		SetHighUIColor(B_PANEL_TEXT_COLOR);
102		font_height fontHeight;
103		GetFontHeight(&fontHeight);
104		point.y = (bounds.top + bounds.bottom
105			- ceilf(fontHeight.ascent) - ceilf(fontHeight.descent)) / 2
106			+ ceilf(fontHeight.ascent);
107
108		DrawString(label, point);
109	}
110
111	// draw the latch
112	if (fPressing)
113		DrawInState(kPressed);
114	else if (Value())
115		DrawInState(kExpanded);
116	else
117		DrawInState(kCollapsed);
118
119	// ...and the focus indication
120	if (!IsFocus() || !Window()->IsActive())
121		return;
122
123	rgb_color markColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
124
125	BeginLineArray(2);
126	AddLine(BPoint(bounds.left + 2, bounds.bottom - 1),
127		BPoint(bounds.right - 2, bounds.bottom - 1), markColor);
128	AddLine(BPoint(bounds.left + 2, bounds.bottom),
129		BPoint(bounds.right - 2, bounds.bottom), kWhite);
130	EndLineArray();
131}
132
133
134void
135PaneSwitch::MouseDown(BPoint)
136{
137	if (!IsEnabled())
138		return;
139
140	fPressing = true;
141	SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
142	Invalidate();
143}
144
145
146void
147PaneSwitch::MouseMoved(BPoint point, uint32 code, const BMessage* message)
148{
149	int32 buttons;
150	BMessage* currentMessage = Window()->CurrentMessage();
151	if (currentMessage == NULL
152		|| currentMessage->FindInt32("buttons", &buttons) != B_OK) {
153		buttons = 0;
154	}
155
156	if (buttons != 0) {
157		BRect bounds(Bounds());
158		bounds.InsetBy(-3, -3);
159
160		bool newPressing = bounds.Contains(point);
161		if (newPressing != fPressing) {
162			fPressing = newPressing;
163			Invalidate();
164		}
165	}
166
167	BControl::MouseMoved(point, code, message);
168}
169
170
171void
172PaneSwitch::MouseUp(BPoint point)
173{
174	BRect bounds(Bounds());
175	bounds.InsetBy(-3, -3);
176
177	fPressing = false;
178	Invalidate();
179	if (bounds.Contains(point)) {
180		SetValue(!Value());
181		Invoke();
182	}
183
184	BControl::MouseUp(point);
185}
186
187
188void
189PaneSwitch::GetPreferredSize(float* _width, float* _height)
190{
191	BSize size = MinSize();
192	if (_width != NULL)
193		*_width = size.width;
194
195	if (_height != NULL)
196		*_height = size.height;
197}
198
199
200BSize
201PaneSwitch::MinSize()
202{
203	BSize size;
204	float onLabelWidth = StringWidth(fLabelOn);
205	float offLabelWidth = StringWidth(fLabelOff);
206	float labelWidth = max_c(onLabelWidth, offLabelWidth);
207	float latchSize = be_plain_font->Size();
208	size.width = latchSize;
209	if (labelWidth > 0.0)
210		size.width += ceilf(latchSize / 2.0) + labelWidth;
211
212	font_height fontHeight;
213	GetFontHeight(&fontHeight);
214	size.height = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
215	size.height = max_c(size.height, latchSize);
216
217	return BLayoutUtils::ComposeSize(ExplicitMinSize(), size);
218}
219
220
221BSize
222PaneSwitch::MaxSize()
223{
224	return BLayoutUtils::ComposeSize(ExplicitMaxSize(), MinSize());
225}
226
227
228BSize
229PaneSwitch::PreferredSize()
230{
231	return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), MinSize());
232}
233
234
235void
236PaneSwitch::SetLabels(const char* labelOn, const char* labelOff)
237{
238	free(fLabelOn);
239	free(fLabelOff);
240
241	if (labelOn != NULL)
242		fLabelOn = strdup(labelOn);
243	else
244		fLabelOn = NULL;
245
246	if (labelOff != NULL)
247		fLabelOff = strdup(labelOff);
248	else
249		fLabelOff = NULL;
250
251	Invalidate();
252	InvalidateLayout();
253}
254
255
256void
257PaneSwitch::DrawInState(PaneSwitch::State state)
258{
259	BRect rect(0, 0, be_plain_font->Size(), be_plain_font->Size());
260	rect.OffsetBy(1, 1);
261
262	rgb_color arrowColor = state == kPressed ? kHighlightColor : kNormalColor;
263	int32 arrowDirection = BControlLook::B_RIGHT_ARROW;
264	float tint = IsEnabled() && Window()->IsActive() ? B_DARKEN_3_TINT
265		: B_DARKEN_1_TINT;
266
267	switch (state) {
268		case kCollapsed:
269			arrowDirection = BControlLook::B_RIGHT_ARROW;
270			break;
271
272		case kPressed:
273			arrowDirection = BControlLook::B_RIGHT_DOWN_ARROW;
274			break;
275
276		case kExpanded:
277			arrowDirection = BControlLook::B_DOWN_ARROW;
278			break;
279	}
280
281	SetDrawingMode(B_OP_COPY);
282	be_control_look->DrawArrowShape(this, rect, rect, arrowColor,
283		arrowDirection, 0, tint);
284}
285