xref: /haiku/src/kits/tracker/DialogPane.cpp (revision 2ae568931fcac7deb9f1e6ff4e47213fbfe4029b)
1 /*
2 Open Tracker License
3 
4 Terms and Conditions
5 
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7 
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
14 
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
28 
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
32 All rights reserved.
33 */
34 
35 #include "Window.h"
36 #include "DialogPane.h"
37 #include "Thread.h"
38 #include "Utilities.h"
39 
40 void
41 ViewList::RemoveAll(BView *)
42 {
43 	EachListItemIgnoreResult(this, &BView::RemoveSelf);
44 }
45 
46 static void
47 AddSelf(BView *self, BView *to)
48 {
49 	to->AddChild(self);
50 }
51 
52 void
53 ViewList::AddAll(BView *toParent)
54 {
55 	EachListItem(this, &AddSelf, toParent);
56 }
57 
58 
59 DialogPane::DialogPane(BRect mode1Frame, BRect mode2Frame, int32 initialMode,
60 	const char *name, uint32 followFlags, uint32 flags)
61 	:	BView(FrameForMode(initialMode, mode1Frame, mode2Frame, mode2Frame),
62 			name, followFlags, flags),
63 		fMode1Frame(mode1Frame),
64 		fMode2Frame(mode2Frame),
65 		fMode3Frame(mode2Frame)
66 {
67 	SetMode(initialMode, true);
68 }
69 
70 
71 DialogPane::DialogPane(BRect mode1Frame, BRect mode2Frame, BRect mode3Frame,
72 	int32 initialMode, const char *name, uint32 followFlags, uint32 flags)
73 	:	BView(FrameForMode(initialMode, mode1Frame, mode2Frame, mode3Frame),
74 			name, followFlags, flags),
75 		fMode1Frame(mode1Frame),
76 		fMode2Frame(mode2Frame),
77 		fMode3Frame(mode3Frame)
78 {
79 	SetMode(initialMode, true);
80 }
81 
82 
83 DialogPane::~DialogPane()
84 {
85 	fMode3Items.RemoveAll(this);
86 	fMode2Items.RemoveAll(this);
87 }
88 
89 
90 void
91 DialogPane::SetMode(int32 mode, bool initialSetup)
92 {
93 	ASSERT(mode < 3 && mode >= 0);
94 
95 	if (!initialSetup && mode == fMode)
96 		return;
97 
98 	int32 oldMode = fMode;
99 	fMode = mode;
100 
101 	bool followBottom = (ResizingMode() & B_FOLLOW_BOTTOM) != 0;
102 	// if we are follow bottom, we will move ourselves, need to place us back
103 	float bottomOffset = 0;
104 	if (followBottom)
105 		bottomOffset = Window()->Bounds().bottom - Frame().bottom;
106 
107 	BRect newBounds(BoundsForMode(fMode));
108 	if (!initialSetup)
109 		ResizeParentWindow(fMode, oldMode);
110 
111 	ResizeTo(newBounds.Width(), newBounds.Height());
112 
113 	float delta = 0;
114 	if (followBottom)
115 		delta = (Window()->Bounds().bottom - Frame().bottom) - bottomOffset;
116 
117 	if (delta != 0) {
118 		MoveBy(0, delta);
119 		if (fLatch && (fLatch->ResizingMode() & B_FOLLOW_BOTTOM))
120 			fLatch->MoveBy(0, delta);
121 	}
122 
123 	switch (fMode) {
124 		case 0:
125 			{
126 				if (oldMode > 1)
127 					fMode3Items.RemoveAll(this);
128 				if (oldMode > 0)
129 					fMode2Items.RemoveAll(this);
130 
131 				BView *separator = FindView("separatorLine");
132 				if (separator) {
133 					BRect frame(separator->Frame());
134 					frame.InsetBy(-1, -1);
135 					RemoveChild(separator);
136 					Invalidate();
137 				}
138 
139 				AddChild(new SeparatorLine(BPoint(newBounds.left, newBounds.top
140 					+ newBounds.Height() / 2), newBounds.Width(), false,
141 					"separatorLine"));
142 			}
143 			break;
144 		case 1:
145 			{
146 				if (oldMode > 1)
147 					fMode3Items.RemoveAll(this);
148 				else
149 					fMode2Items.AddAll(this);
150 
151 				BView *separator = FindView("separatorLine");
152 				if (separator) {
153 					BRect frame(separator->Frame());
154 					frame.InsetBy(-1, -1);
155 					RemoveChild(separator);
156 					Invalidate();
157 				}
158 			}
159 			break;
160 		case 2:
161 			{
162 				fMode3Items.AddAll(this);
163 				if (oldMode < 1)
164 					fMode2Items.AddAll(this);
165 
166 				BView *separator = FindView("separatorLine");
167 				if (separator) {
168 					BRect frame(separator->Frame());
169 					frame.InsetBy(-1, -1);
170 					RemoveChild(separator);
171 					Invalidate();
172 				}
173 			}
174 			break;
175 	}
176 }
177 
178 void
179 DialogPane::AttachedToWindow()
180 {
181 	BView *parent = Parent();
182 	if (parent) {
183 		SetViewColor(parent->ViewColor());
184 		SetLowColor(parent->LowColor());
185 	}
186 }
187 
188 void
189 DialogPane::ResizeParentWindow(int32 from, int32 to)
190 {
191 	if (!Window())
192 		return;
193 
194 	BRect oldBounds = BoundsForMode(from);
195 	BRect newBounds = BoundsForMode(to);
196 
197 	BPoint by = oldBounds.RightBottom() - newBounds.RightBottom();
198 	if (by != BPoint(0, 0))
199 		Window()->ResizeBy(by.x, by.y);
200 }
201 
202 void
203 DialogPane::AddItem(BView *view, int32 toMode)
204 {
205 	if (toMode == 1)
206 		fMode2Items.AddItem(view);
207 	else if (toMode == 2)
208 		fMode3Items.AddItem(view);
209 	if (fMode >= toMode)
210 		AddChild(view);
211 }
212 
213 BRect
214 DialogPane::FrameForMode(int32 mode)
215 {
216 	switch (mode) {
217 		case 0:
218 			return fMode1Frame;
219 		case 1:
220 			return fMode2Frame;
221 		case 2:
222 			return fMode3Frame;
223 	}
224 	return fMode1Frame;
225 }
226 
227 BRect
228 DialogPane::BoundsForMode(int32 mode)
229 {
230 	BRect result;
231 	switch (mode) {
232 		case 0:
233 			result = fMode1Frame;
234 			break;
235 		case 1:
236 			result = fMode2Frame;
237 			break;
238 		case 2:
239 			result = fMode3Frame;
240 			break;
241 	}
242 	result.OffsetTo(0, 0);
243 	return result;
244 }
245 
246 BRect
247 DialogPane::FrameForMode(int32 mode, BRect mode1Frame, BRect mode2Frame,
248 	BRect mode3Frame)
249 {
250 	switch (mode) {
251 		case 0:
252 			return mode1Frame;
253 		case 1:
254 			return mode2Frame;
255 		case 2:
256 			return mode3Frame;
257 	}
258 	return mode1Frame;
259 }
260 
261 const uint32 kValueChanged = 'swch';
262 
263 void
264 DialogPane::SetSwitch(BControl *control)
265 {
266 	fLatch = control;
267 	control->SetMessage(new BMessage(kValueChanged));
268 	control->SetTarget(this);
269 }
270 
271 void
272 DialogPane::MessageReceived(BMessage *message)
273 {
274 	if (message->what == kValueChanged) {
275 		int32 value;
276 		if (message->FindInt32("be:value", &value) == B_OK)
277 			SetMode(value);
278 	} else
279 		_inherited::MessageReceived(message);
280 }
281 
282 PaneSwitch::PaneSwitch(BRect frame, const char *name, bool leftAligned,
283 	uint32 resizeMask, uint32 flags)
284 	:	BControl(frame, name, "", 0, resizeMask, flags),
285 		fLeftAligned(leftAligned),
286 		fPressing(false)
287 {
288 }
289 
290 void
291 PaneSwitch::DoneTracking(BPoint point)
292 {
293 	BRect bounds(Bounds());
294 	bounds.InsetBy(-3, -3);
295 
296 	fPressing = false;
297 	Invalidate();
298 	if (bounds.Contains(point)) {
299 		SetValue(!Value());
300 		Invoke();
301 	}
302 }
303 
304 void
305 PaneSwitch::Track(BPoint point, uint32)
306 {
307 	BRect bounds(Bounds());
308 	bounds.InsetBy(-3, -3);
309 
310 	bool newPressing = bounds.Contains(point);
311 	if (newPressing != fPressing) {
312 		fPressing = newPressing;
313 		Invalidate();
314 	}
315 }
316 
317 
318 void
319 PaneSwitch::MouseDown(BPoint)
320 {
321 	if (!IsEnabled())
322 		return;
323 
324 	fPressing = true;
325 	MouseDownThread<PaneSwitch>::TrackMouse(this, &PaneSwitch::DoneTracking,
326 		&PaneSwitch::Track);
327 	Invalidate();
328 }
329 
330 
331 const rgb_color kNormalColor = {150, 150, 150, 255};
332 const rgb_color kHighlightColor = {100, 100, 0, 255};
333 
334 void
335 PaneSwitch::Draw(BRect)
336 {
337 	if (fPressing)
338 		DrawInState(kPressed);
339 	else if (Value())
340 		DrawInState(kExpanded);
341 	else
342 		DrawInState(kCollapsed);
343 
344 
345 	rgb_color markColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
346 
347 	bool focused = IsFocus() && Window()->IsActive();
348 	BRect bounds(Bounds());
349 	BeginLineArray(2);
350 	AddLine(BPoint(bounds.left + 2, bounds.bottom - 1),
351 		BPoint(bounds.right - 2, bounds.bottom - 1), focused ? markColor : ViewColor());
352 	AddLine(BPoint(bounds.left + 2, bounds.bottom),
353 		BPoint(bounds.right - 2, bounds.bottom), focused ? kWhite : ViewColor());
354 	EndLineArray();
355 }
356 
357 void
358 PaneSwitch::DrawInState(PaneSwitch::State state)
359 {
360 	BRect rect(0, 0, 10, 10);
361 
362 	rgb_color outlineColor = {0, 0, 0, 255};
363 	rgb_color middleColor = state == kPressed ? kHighlightColor : kNormalColor;
364 
365 
366 	SetDrawingMode(B_OP_COPY);
367 
368 	switch (state) {
369 		case kCollapsed:
370 			BeginLineArray(6);
371 
372 			if (fLeftAligned) {
373 				AddLine(BPoint(rect.left + 3, rect.top + 1),
374 					BPoint(rect.left + 3, rect.bottom - 1), outlineColor);
375 				AddLine(BPoint(rect.left + 3, rect.top + 1),
376 					BPoint(rect.left + 7, rect.top + 5), outlineColor);
377 				AddLine(BPoint(rect.left + 7, rect.top + 5),
378 					BPoint(rect.left + 3, rect.bottom - 1), outlineColor);
379 
380 				AddLine(BPoint(rect.left + 4, rect.top + 3),
381 					BPoint(rect.left + 4, rect.bottom - 3), middleColor);
382 				AddLine(BPoint(rect.left + 5, rect.top + 4),
383 					BPoint(rect.left + 5, rect.bottom - 4), middleColor);
384 				AddLine(BPoint(rect.left + 5, rect.top + 5),
385 					BPoint(rect.left + 6, rect.top + 5), middleColor);
386 			} else {
387 				AddLine(BPoint(rect.right - 3, rect.top + 1),
388 					BPoint(rect.right - 3, rect.bottom - 1), outlineColor);
389 				AddLine(BPoint(rect.right - 3, rect.top + 1),
390 					BPoint(rect.right - 7, rect.top + 5), outlineColor);
391 				AddLine(BPoint(rect.right - 7, rect.top + 5),
392 					BPoint(rect.right - 3, rect.bottom - 1), outlineColor);
393 
394 				AddLine(BPoint(rect.right - 4, rect.top + 3),
395 					BPoint(rect.right - 4, rect.bottom - 3), middleColor);
396 				AddLine(BPoint(rect.right - 5, rect.top + 4),
397 					BPoint(rect.right - 5, rect.bottom - 4), middleColor);
398 				AddLine(BPoint(rect.right - 5, rect.top + 5),
399 					BPoint(rect.right - 6, rect.top + 5), middleColor);
400 			}
401 			EndLineArray();
402 			break;
403 
404 		case kPressed:
405 			BeginLineArray(7);
406 			if (fLeftAligned) {
407 				AddLine(BPoint(rect.left + 1, rect.top + 7),
408 					BPoint(rect.left + 7, rect.top + 7), outlineColor);
409 				AddLine(BPoint(rect.left + 7, rect.top + 1),
410 					BPoint(rect.left + 7, rect.top + 7), outlineColor);
411 				AddLine(BPoint(rect.left + 1, rect.top + 7),
412 					BPoint(rect.left + 7, rect.top + 1), outlineColor);
413 
414 				AddLine(BPoint(rect.left + 3, rect.top + 6),
415 					BPoint(rect.left + 6, rect.top + 6), middleColor);
416 				AddLine(BPoint(rect.left + 4, rect.top + 5),
417 					BPoint(rect.left + 6, rect.top + 5), middleColor);
418 				AddLine(BPoint(rect.left + 5, rect.top + 4),
419 					BPoint(rect.left + 6, rect.top + 4), middleColor);
420 				AddLine(BPoint(rect.left + 6, rect.top + 3),
421 					BPoint(rect.left + 6, rect.top + 4), middleColor);
422 			} else {
423 				AddLine(BPoint(rect.right - 1, rect.top + 7),
424 					BPoint(rect.right - 7, rect.top + 7), outlineColor);
425 				AddLine(BPoint(rect.right - 7, rect.top + 1),
426 					BPoint(rect.right - 7, rect.top + 7), outlineColor);
427 				AddLine(BPoint(rect.right - 1, rect.top + 7),
428 					BPoint(rect.right - 7, rect.top + 1), outlineColor);
429 
430 				AddLine(BPoint(rect.right - 3, rect.top + 6),
431 					BPoint(rect.right - 6, rect.top + 6), middleColor);
432 				AddLine(BPoint(rect.right - 4, rect.top + 5),
433 					BPoint(rect.right - 6, rect.top + 5), middleColor);
434 				AddLine(BPoint(rect.right - 5, rect.top + 4),
435 					BPoint(rect.right - 6, rect.top + 4), middleColor);
436 				AddLine(BPoint(rect.right - 6, rect.top + 3),
437 					BPoint(rect.right - 6, rect.top + 4), middleColor);
438 			}
439 			EndLineArray();
440 			break;
441 
442 		case kExpanded:
443 			BeginLineArray(6);
444 			AddLine(BPoint(rect.left + 1, rect.top + 3),
445 				BPoint(rect.right - 1, rect.top + 3), outlineColor);
446 			AddLine(BPoint(rect.left + 1, rect.top + 3),
447 				BPoint(rect.left + 5, rect.top + 7), outlineColor);
448 			AddLine(BPoint(rect.left + 5, rect.top + 7),
449 				BPoint(rect.right - 1, rect.top + 3), outlineColor);
450 
451 			AddLine(BPoint(rect.left + 3, rect.top + 4),
452 				BPoint(rect.right - 3, rect.top + 4), middleColor);
453 			AddLine(BPoint(rect.left + 4, rect.top + 5),
454 				BPoint(rect.right - 4, rect.top + 5), middleColor);
455 			AddLine(BPoint(rect.left + 5, rect.top + 5),
456 				BPoint(rect.left + 5, rect.top + 6), middleColor);
457 			EndLineArray();
458 			break;
459 	}
460 }
461 
462