xref: /haiku/src/kits/tracker/DialogPane.cpp (revision 1acbe440b8dd798953bec31d18ee589aa3f71b73)
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 
41 const uint32 kValueChanged = 'swch';
42 
43 const rgb_color kNormalColor = {150, 150, 150, 255};
44 const rgb_color kHighlightColor = {100, 100, 0, 255};
45 
46 
47 static void
48 AddSelf(BView *self, BView *to)
49 {
50 	to->AddChild(self);
51 }
52 
53 
54 void
55 ViewList::RemoveAll(BView *)
56 {
57 	EachListItemIgnoreResult(this, &BView::RemoveSelf);
58 }
59 
60 
61 void
62 ViewList::AddAll(BView *toParent)
63 {
64 	EachListItem(this, &AddSelf, toParent);
65 }
66 
67 
68 //	#pragma mark -
69 
70 
71 DialogPane::DialogPane(BRect mode1Frame, BRect mode2Frame, int32 initialMode,
72 	const char *name, uint32 followFlags, uint32 flags)
73 	: BView(FrameForMode(initialMode, mode1Frame, mode2Frame, mode2Frame),
74 		name, followFlags, flags),
75 	fMode(initialMode),
76 	fMode1Frame(mode1Frame),
77 	fMode2Frame(mode2Frame),
78 	fMode3Frame(mode2Frame)
79 {
80 	SetMode(fMode, true);
81 }
82 
83 
84 DialogPane::DialogPane(BRect mode1Frame, BRect mode2Frame, BRect mode3Frame,
85 	int32 initialMode, const char *name, uint32 followFlags, uint32 flags)
86 	: BView(FrameForMode(initialMode, mode1Frame, mode2Frame, mode3Frame),
87 		name, followFlags, flags),
88 	fMode(initialMode),
89 	fMode1Frame(mode1Frame),
90 	fMode2Frame(mode2Frame),
91 	fMode3Frame(mode3Frame)
92 {
93 	SetMode(fMode, true);
94 }
95 
96 
97 DialogPane::~DialogPane()
98 {
99 	fMode3Items.RemoveAll(this);
100 	fMode2Items.RemoveAll(this);
101 }
102 
103 
104 void
105 DialogPane::SetMode(int32 mode, bool initialSetup)
106 {
107 	ASSERT(mode < 3 && mode >= 0);
108 
109 	if (!initialSetup && mode == fMode)
110 		return;
111 
112 	int32 oldMode = fMode;
113 	fMode = mode;
114 
115 	bool followBottom = (ResizingMode() & B_FOLLOW_BOTTOM) != 0;
116 	// if we are follow bottom, we will move ourselves, need to place us back
117 	float bottomOffset = 0;
118 	if (followBottom && Window() != NULL)
119 		bottomOffset = Window()->Bounds().bottom - Frame().bottom;
120 
121 	BRect newBounds(BoundsForMode(fMode));
122 	if (!initialSetup)
123 		ResizeParentWindow(fMode, oldMode);
124 
125 	ResizeTo(newBounds.Width(), newBounds.Height());
126 
127 	float delta = 0;
128 	if (followBottom && Window() != NULL)
129 		delta = (Window()->Bounds().bottom - Frame().bottom) - bottomOffset;
130 
131 	if (delta != 0) {
132 		MoveBy(0, delta);
133 		if (fLatch && (fLatch->ResizingMode() & B_FOLLOW_BOTTOM))
134 			fLatch->MoveBy(0, delta);
135 	}
136 
137 	switch (fMode) {
138 		case 0:
139 		{
140 			if (oldMode > 1)
141 				fMode3Items.RemoveAll(this);
142 			if (oldMode > 0)
143 				fMode2Items.RemoveAll(this);
144 
145 			BView *separator = FindView("separatorLine");
146 			if (separator) {
147 				BRect frame(separator->Frame());
148 				frame.InsetBy(-1, -1);
149 				RemoveChild(separator);
150 				Invalidate();
151 			}
152 
153 			AddChild(new SeparatorLine(BPoint(newBounds.left, newBounds.top
154 				+ newBounds.Height() / 2), newBounds.Width(), false,
155 				"separatorLine"));
156 			break;
157 		}
158 		case 1:
159 		{
160 			if (oldMode > 1)
161 				fMode3Items.RemoveAll(this);
162 			else
163 				fMode2Items.AddAll(this);
164 
165 			BView *separator = FindView("separatorLine");
166 			if (separator) {
167 				BRect frame(separator->Frame());
168 				frame.InsetBy(-1, -1);
169 				RemoveChild(separator);
170 				Invalidate();
171 			}
172 			break;
173 		}
174 		case 2:
175 		{
176 			fMode3Items.AddAll(this);
177 			if (oldMode < 1)
178 				fMode2Items.AddAll(this);
179 
180 			BView *separator = FindView("separatorLine");
181 			if (separator) {
182 				BRect frame(separator->Frame());
183 				frame.InsetBy(-1, -1);
184 				RemoveChild(separator);
185 				Invalidate();
186 			}
187 			break;
188 		}
189 	}
190 }
191 
192 
193 void
194 DialogPane::AttachedToWindow()
195 {
196 	BView *parent = Parent();
197 	if (parent) {
198 		SetViewColor(parent->ViewColor());
199 		SetLowColor(parent->LowColor());
200 	}
201 }
202 
203 
204 void
205 DialogPane::ResizeParentWindow(int32 from, int32 to)
206 {
207 	if (!Window())
208 		return;
209 
210 	BRect oldBounds = BoundsForMode(from);
211 	BRect newBounds = BoundsForMode(to);
212 
213 	BPoint by = oldBounds.RightBottom() - newBounds.RightBottom();
214 	if (by != BPoint(0, 0))
215 		Window()->ResizeBy(by.x, by.y);
216 }
217 
218 
219 void
220 DialogPane::AddItem(BView *view, int32 toMode)
221 {
222 	if (toMode == 1)
223 		fMode2Items.AddItem(view);
224 	else if (toMode == 2)
225 		fMode3Items.AddItem(view);
226 	if (fMode >= toMode)
227 		AddChild(view);
228 }
229 
230 
231 BRect
232 DialogPane::FrameForMode(int32 mode)
233 {
234 	switch (mode) {
235 		case 0:
236 			return fMode1Frame;
237 		case 1:
238 			return fMode2Frame;
239 		case 2:
240 			return fMode3Frame;
241 	}
242 	return fMode1Frame;
243 }
244 
245 
246 BRect
247 DialogPane::BoundsForMode(int32 mode)
248 {
249 	BRect result;
250 	switch (mode) {
251 		case 0:
252 			result = fMode1Frame;
253 			break;
254 		case 1:
255 			result = fMode2Frame;
256 			break;
257 		case 2:
258 			result = fMode3Frame;
259 			break;
260 	}
261 	result.OffsetTo(0, 0);
262 	return result;
263 }
264 
265 
266 BRect
267 DialogPane::FrameForMode(int32 mode, BRect mode1Frame, BRect mode2Frame,
268 	BRect mode3Frame)
269 {
270 	switch (mode) {
271 		case 0:
272 			return mode1Frame;
273 		case 1:
274 			return mode2Frame;
275 		case 2:
276 			return mode3Frame;
277 	}
278 	return mode1Frame;
279 }
280 
281 
282 void
283 DialogPane::SetSwitch(BControl *control)
284 {
285 	fLatch = control;
286 	control->SetMessage(new BMessage(kValueChanged));
287 	control->SetTarget(this);
288 }
289 
290 
291 void
292 DialogPane::MessageReceived(BMessage *message)
293 {
294 	if (message->what == kValueChanged) {
295 		int32 value;
296 		if (message->FindInt32("be:value", &value) == B_OK)
297 			SetMode(value);
298 	} else
299 		_inherited::MessageReceived(message);
300 }
301 
302 
303 //	#pragma mark -
304 
305 
306 PaneSwitch::PaneSwitch(BRect frame, const char *name, bool leftAligned,
307 	uint32 resizeMask, uint32 flags)
308 	:	BControl(frame, name, "", 0, resizeMask, flags),
309 		fLeftAligned(leftAligned),
310 		fPressing(false)
311 {
312 }
313 
314 
315 void
316 PaneSwitch::DoneTracking(BPoint point)
317 {
318 	BRect bounds(Bounds());
319 	bounds.InsetBy(-3, -3);
320 
321 	fPressing = false;
322 	Invalidate();
323 	if (bounds.Contains(point)) {
324 		SetValue(!Value());
325 		Invoke();
326 	}
327 }
328 
329 
330 void
331 PaneSwitch::Track(BPoint point, uint32)
332 {
333 	BRect bounds(Bounds());
334 	bounds.InsetBy(-3, -3);
335 
336 	bool newPressing = bounds.Contains(point);
337 	if (newPressing != fPressing) {
338 		fPressing = newPressing;
339 		Invalidate();
340 	}
341 }
342 
343 
344 void
345 PaneSwitch::MouseDown(BPoint)
346 {
347 	if (!IsEnabled())
348 		return;
349 
350 	fPressing = true;
351 	MouseDownThread<PaneSwitch>::TrackMouse(this, &PaneSwitch::DoneTracking,
352 		&PaneSwitch::Track);
353 	Invalidate();
354 }
355 
356 
357 void
358 PaneSwitch::Draw(BRect)
359 {
360 	if (fPressing)
361 		DrawInState(kPressed);
362 	else if (Value())
363 		DrawInState(kExpanded);
364 	else
365 		DrawInState(kCollapsed);
366 
367 	rgb_color markColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
368 
369 	bool focused = IsFocus() && Window()->IsActive();
370 	BRect bounds(Bounds());
371 	BeginLineArray(2);
372 	AddLine(BPoint(bounds.left + 2, bounds.bottom - 1),
373 		BPoint(bounds.right - 2, bounds.bottom - 1), focused ? markColor : ViewColor());
374 	AddLine(BPoint(bounds.left + 2, bounds.bottom),
375 		BPoint(bounds.right - 2, bounds.bottom), focused ? kWhite : ViewColor());
376 	EndLineArray();
377 }
378 
379 
380 void
381 PaneSwitch::DrawInState(PaneSwitch::State state)
382 {
383 	BRect rect(0, 0, 10, 10);
384 
385 	rgb_color outlineColor = {0, 0, 0, 255};
386 	rgb_color middleColor = state == kPressed ? kHighlightColor : kNormalColor;
387 
388 	SetDrawingMode(B_OP_COPY);
389 
390 	switch (state) {
391 		case kCollapsed:
392 			BeginLineArray(6);
393 
394 			if (fLeftAligned) {
395 				AddLine(BPoint(rect.left + 3, rect.top + 1),
396 					BPoint(rect.left + 3, rect.bottom - 1), outlineColor);
397 				AddLine(BPoint(rect.left + 3, rect.top + 1),
398 					BPoint(rect.left + 7, rect.top + 5), outlineColor);
399 				AddLine(BPoint(rect.left + 7, rect.top + 5),
400 					BPoint(rect.left + 3, rect.bottom - 1), outlineColor);
401 
402 				AddLine(BPoint(rect.left + 4, rect.top + 3),
403 					BPoint(rect.left + 4, rect.bottom - 3), middleColor);
404 				AddLine(BPoint(rect.left + 5, rect.top + 4),
405 					BPoint(rect.left + 5, rect.bottom - 4), middleColor);
406 				AddLine(BPoint(rect.left + 5, rect.top + 5),
407 					BPoint(rect.left + 6, rect.top + 5), middleColor);
408 			} else {
409 				AddLine(BPoint(rect.right - 3, rect.top + 1),
410 					BPoint(rect.right - 3, rect.bottom - 1), outlineColor);
411 				AddLine(BPoint(rect.right - 3, rect.top + 1),
412 					BPoint(rect.right - 7, rect.top + 5), outlineColor);
413 				AddLine(BPoint(rect.right - 7, rect.top + 5),
414 					BPoint(rect.right - 3, rect.bottom - 1), outlineColor);
415 
416 				AddLine(BPoint(rect.right - 4, rect.top + 3),
417 					BPoint(rect.right - 4, rect.bottom - 3), middleColor);
418 				AddLine(BPoint(rect.right - 5, rect.top + 4),
419 					BPoint(rect.right - 5, rect.bottom - 4), middleColor);
420 				AddLine(BPoint(rect.right - 5, rect.top + 5),
421 					BPoint(rect.right - 6, rect.top + 5), middleColor);
422 			}
423 			EndLineArray();
424 			break;
425 
426 		case kPressed:
427 			BeginLineArray(7);
428 			if (fLeftAligned) {
429 				AddLine(BPoint(rect.left + 1, rect.top + 7),
430 					BPoint(rect.left + 7, rect.top + 7), outlineColor);
431 				AddLine(BPoint(rect.left + 7, rect.top + 1),
432 					BPoint(rect.left + 7, rect.top + 7), outlineColor);
433 				AddLine(BPoint(rect.left + 1, rect.top + 7),
434 					BPoint(rect.left + 7, rect.top + 1), outlineColor);
435 
436 				AddLine(BPoint(rect.left + 3, rect.top + 6),
437 					BPoint(rect.left + 6, rect.top + 6), middleColor);
438 				AddLine(BPoint(rect.left + 4, rect.top + 5),
439 					BPoint(rect.left + 6, rect.top + 5), middleColor);
440 				AddLine(BPoint(rect.left + 5, rect.top + 4),
441 					BPoint(rect.left + 6, rect.top + 4), middleColor);
442 				AddLine(BPoint(rect.left + 6, rect.top + 3),
443 					BPoint(rect.left + 6, rect.top + 4), middleColor);
444 			} else {
445 				AddLine(BPoint(rect.right - 1, rect.top + 7),
446 					BPoint(rect.right - 7, rect.top + 7), outlineColor);
447 				AddLine(BPoint(rect.right - 7, rect.top + 1),
448 					BPoint(rect.right - 7, rect.top + 7), outlineColor);
449 				AddLine(BPoint(rect.right - 1, rect.top + 7),
450 					BPoint(rect.right - 7, rect.top + 1), outlineColor);
451 
452 				AddLine(BPoint(rect.right - 3, rect.top + 6),
453 					BPoint(rect.right - 6, rect.top + 6), middleColor);
454 				AddLine(BPoint(rect.right - 4, rect.top + 5),
455 					BPoint(rect.right - 6, rect.top + 5), middleColor);
456 				AddLine(BPoint(rect.right - 5, rect.top + 4),
457 					BPoint(rect.right - 6, rect.top + 4), middleColor);
458 				AddLine(BPoint(rect.right - 6, rect.top + 3),
459 					BPoint(rect.right - 6, rect.top + 4), middleColor);
460 			}
461 			EndLineArray();
462 			break;
463 
464 		case kExpanded:
465 			BeginLineArray(6);
466 			AddLine(BPoint(rect.left + 1, rect.top + 3),
467 				BPoint(rect.right - 1, rect.top + 3), outlineColor);
468 			AddLine(BPoint(rect.left + 1, rect.top + 3),
469 				BPoint(rect.left + 5, rect.top + 7), outlineColor);
470 			AddLine(BPoint(rect.left + 5, rect.top + 7),
471 				BPoint(rect.right - 1, rect.top + 3), outlineColor);
472 
473 			AddLine(BPoint(rect.left + 3, rect.top + 4),
474 				BPoint(rect.right - 3, rect.top + 4), middleColor);
475 			AddLine(BPoint(rect.left + 4, rect.top + 5),
476 				BPoint(rect.right - 4, rect.top + 5), middleColor);
477 			AddLine(BPoint(rect.left + 5, rect.top + 5),
478 				BPoint(rect.left + 5, rect.top + 6), middleColor);
479 			EndLineArray();
480 			break;
481 	}
482 }
483 
484