xref: /haiku/src/kits/interface/StatusBar.cpp (revision 0e50eab75e25d0d82090e22dbff766dfaa6f5e86)
1 /*
2  * Copyright 2001-2006, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Marc Flerackers (mflerackers@androme.be)
7  */
8 
9 /*! BStatusBar displays a "percentage-of-completion" gauge. */
10 
11 #include <Debug.h>
12 #include <Message.h>
13 #include <StatusBar.h>
14 
15 #include <stdlib.h>
16 #include <string.h>
17 
18 
19 BStatusBar::BStatusBar(BRect frame, const char *name, const char *label,
20 					   const char *trailingLabel)
21 	:	BView(frame, name, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW),
22 		fLabel(NULL),
23 		fTrailingLabel(NULL),
24 		fText(NULL),
25 		fTrailingText(NULL),
26 		fMax(100.0f),
27 		fCurrent(0.0f),
28 		fBarHeight(-1.0f),
29 		fTrailingWidth(-1.0f),
30 		fEraseText(-1.0f),
31 		fEraseTrailingText(-1.0f),
32 		fCustomBarHeight(false)
33 
34 {
35 	// TODO: Move initializer list and other stuff to InitObject
36 	InitObject(label, trailingLabel);
37 
38 	fBarColor.set_to(50, 150, 255, 255);
39 }
40 
41 
42 BStatusBar::BStatusBar(BMessage *archive)
43 	:	BView(archive),
44 		fLabel(NULL),
45 		fTrailingLabel(NULL),
46 		fText(NULL),
47 		fTrailingText(NULL),
48 		fMax(100.0f),
49 		fCurrent(0.0f),
50 		fBarHeight(-1.0f),
51 		fTrailingWidth(-1.0f),
52 		fEraseText(-1.0f),
53 		fEraseTrailingText(-1.0f),
54 		fCustomBarHeight(false)
55 {
56 	const char *label = NULL;
57 	const char *trailingLabel = NULL;
58 	archive->FindString("_label", &label);
59 	archive->FindString("_tlabel", &trailingLabel);
60 
61 	InitObject(label, trailingLabel);
62 
63 	if (archive->FindFloat("_high", &fBarHeight) != B_OK)
64 		fBarHeight = -1.0f;
65 
66 	if (archive->FindInt32("_bcolor", (int32 *)&fBarColor) < B_OK)
67 		fBarColor.set_to(50, 150, 255, 255);
68 
69 	if (archive->FindFloat("_val", &fCurrent) < B_OK)
70 		fCurrent = 0.0f;
71 
72 	if (archive->FindFloat("_max", &fMax) < B_OK)
73 		fMax = 100.0f;
74 
75 	const char *string;
76 
77 	if (archive->FindString("_text", &string) < B_OK)
78 		fText = NULL;
79 	else
80 		fText = strdup(string);
81 
82 	if (archive->FindString("_ttext", &string) < B_OK)
83 		fTrailingText = NULL;
84 	else
85 		fTrailingText = strdup(string);
86 
87 }
88 
89 
90 BStatusBar::~BStatusBar()
91 {
92 	free(fLabel);
93 	free(fTrailingLabel);
94 	free(fText);
95 	free(fTrailingText);
96 }
97 
98 
99 BArchivable *
100 BStatusBar::Instantiate(BMessage *archive)
101 {
102 	if (validate_instantiation(archive, "BStatusBar"))
103 		return new BStatusBar(archive);
104 
105 	return NULL;
106 }
107 
108 
109 status_t
110 BStatusBar::Archive(BMessage *archive, bool deep) const
111 {
112 	status_t err = BView::Archive(archive, deep);
113 
114 	if (err < B_OK)
115 		return err;
116 
117 	if (fBarHeight != 16.0f)
118 		err = archive->AddFloat("_high", fBarHeight);
119 
120 	if (err < B_OK)
121 		return err;
122 
123 	// DW: I'm pretty sure we don't need to compare the color with (50, 150, 255) ?
124 	err = archive->AddInt32("_bcolor", (const uint32 &)fBarColor);
125 
126 	if (err < B_OK)
127 		return err;
128 
129 	if (fCurrent != 0.0f)
130 		err = archive->AddFloat("_val", fCurrent);
131 
132 	if (err < B_OK)
133 		return err;
134 
135 	if (fMax != 100.0f )
136 		err = archive->AddFloat("_max", fMax);
137 
138 	if (err < B_OK)
139 		return err;
140 
141 	if (fText )
142 		err = archive->AddString("_text", fText);
143 
144 	if (err < B_OK)
145 		return err;
146 
147 	if (fTrailingText)
148 		err = archive->AddString("_ttext", fTrailingText);
149 
150 	if (err < B_OK)
151 		return err;
152 
153 	if (fLabel)
154 		err = archive->AddString("_label", fLabel);
155 
156 	if (err < B_OK)
157 		return err;
158 
159 	if (fTrailingLabel)
160 		err = archive->AddString ("_tlabel", fTrailingLabel);
161 
162 	return err;
163 }
164 
165 
166 void
167 BStatusBar::AttachedToWindow()
168 {
169 	float width, height;
170 	GetPreferredSize(&width, &height);
171 	ResizeTo(Frame().Width(), height);
172 
173 	if (Parent()) {
174 		SetViewColor(Parent()->ViewColor());
175 		SetLowColor(Parent()->ViewColor());
176 	}
177 }
178 
179 
180 void
181 BStatusBar::MessageReceived(BMessage *message)
182 {
183 	switch(message->what) {
184 		case B_UPDATE_STATUS_BAR:
185 		{
186 			float delta;
187 			const char *text = NULL, *trailing_text = NULL;
188 
189 			message->FindFloat("delta", &delta);
190 			message->FindString("text", &text);
191 			message->FindString("trailing_text", &trailing_text);
192 
193 			Update(delta, text, trailing_text);
194 
195 			break;
196 		}
197 
198 		case B_RESET_STATUS_BAR:
199 		{
200 			const char *label = NULL, *trailing_label = NULL;
201 
202 			message->FindString("label", &label);
203 			message->FindString("trailing_label", &trailing_label);
204 
205 			Reset(label, trailing_label);
206 
207 			break;
208 		}
209 
210 		default:
211 			BView::MessageReceived(message);
212 			break;
213 	}
214 }
215 
216 
217 void
218 BStatusBar::Draw(BRect updateRect)
219 {
220 	float width = Frame().Width();
221 	font_height fh;
222 	GetFontHeight(&fh);
223 
224 	SetHighColor(0, 0, 0);
225 	MovePenTo(2.0f, (float)ceil(fh.ascent) + 1.0f);
226 
227 	if (fLabel)
228 		DrawString(fLabel);
229 	if (fText)
230 		DrawString(fText);
231 
232 	if (fTrailingText) {
233 		if (fTrailingLabel) {
234 			MovePenTo(width - StringWidth(fTrailingText) -
235 			StringWidth(fTrailingLabel) - 2.0f,
236 			(float)ceil(fh.ascent) + 1.0f);
237 			DrawString(fTrailingText);
238 			DrawString(fTrailingLabel);
239 		} else {
240 			MovePenTo(width - StringWidth(fTrailingText) - 2.0f,
241 			(float)ceil(fh.ascent) + 1.0f);
242 			DrawString(fTrailingText);
243 		}
244 
245 	} else if (fTrailingLabel) {
246 		MovePenTo(width - StringWidth(fTrailingLabel) - 2.0f,
247 			(float)ceil(fh.ascent) + 1.0f);
248 		DrawString(fTrailingLabel);
249 	}
250 
251 	BRect rect(0.0f, (float)ceil(fh.ascent) + 4.0f, width,
252 		(float)ceil(fh.ascent) + 4.0f + fBarHeight);
253 
254 	// First bevel
255 	SetHighColor(tint_color(ui_color ( B_PANEL_BACKGROUND_COLOR ), B_DARKEN_1_TINT));
256 	StrokeLine(BPoint(rect.left, rect.bottom), BPoint(rect.left, rect.top));
257 	StrokeLine(BPoint(rect.right, rect.top));
258 
259 	SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_2_TINT));
260 	StrokeLine(BPoint(rect.left + 1.0f, rect.bottom), BPoint(rect.right, rect.bottom));
261 	StrokeLine(BPoint(rect.right, rect.top + 1.0f));
262 
263 	rect.InsetBy(1.0f, 1.0f);
264 
265 	// Second bevel
266 	SetHighColor(tint_color(ui_color ( B_PANEL_BACKGROUND_COLOR ), B_DARKEN_4_TINT));
267 	StrokeLine(BPoint(rect.left, rect.bottom), BPoint(rect.left, rect.top));
268 	StrokeLine(BPoint(rect.right, rect.top));
269 
270 	SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
271 	StrokeLine(BPoint(rect.left + 1.0f, rect.bottom), BPoint(rect.right, rect.bottom));
272 	StrokeLine(BPoint(rect.right, rect.top + 1.0f));
273 
274 	rect.InsetBy(1.0f, 1.0f);
275 
276 	// Filling
277 	SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_MAX_TINT));
278 	FillRect(rect);
279 
280 	if (fCurrent != 0.0f) {
281 		rect.right = rect.left + (float)ceil(fCurrent * (width - 4) / fMax),
282 
283 		// Bevel
284 		SetHighColor(tint_color(fBarColor, B_LIGHTEN_2_TINT));
285 		StrokeLine(BPoint(rect.left, rect.bottom), BPoint(rect.left, rect.top));
286 		StrokeLine(BPoint(rect.right, rect.top));
287 
288 		SetHighColor(tint_color(fBarColor, B_DARKEN_2_TINT));
289 		StrokeLine(BPoint(rect.left, rect.bottom), BPoint(rect.right, rect.bottom));
290 		StrokeLine(BPoint(rect.right, rect.top));
291 
292 		rect.InsetBy(1.0f, 1.0f);
293 
294 		// Filling
295 		SetHighColor(fBarColor);
296 		FillRect(rect);
297 	}
298 }
299 
300 
301 void
302 BStatusBar::SetBarColor(rgb_color color)
303 {
304 	fBarColor = color;
305 
306 	Invalidate();
307 }
308 
309 
310 void
311 BStatusBar::SetBarHeight(float height)
312 {
313 	BRect frame = Frame();
314 
315 	fBarHeight = height;
316 	fCustomBarHeight = true;
317 	ResizeTo(frame.Width(), fBarHeight + 16);
318 }
319 
320 
321 void
322 BStatusBar::SetText(const char *string)
323 {
324 	SetTextData(&fText, string);
325 
326 	Invalidate();
327 }
328 
329 
330 void
331 BStatusBar::SetTrailingText(const char *string)
332 {
333 	SetTextData(&fTrailingText, string);
334 
335 	Invalidate();
336 }
337 
338 
339 void
340 BStatusBar::SetMaxValue(float max)
341 {
342 	fMax = max;
343 
344 	Invalidate();
345 }
346 
347 
348 void
349 BStatusBar::Update(float delta, const char *text, const char *trailingText)
350 {
351 	fCurrent += delta;
352 
353 	if (fCurrent > fMax)
354 		fCurrent = fMax;
355 
356 	// Passing NULL for the text or trailingText argument retains the previous
357 	// text or trailing text string.
358 	if (text)
359 		SetTextData(&fText, text);
360 
361 	if (trailingText)
362 		SetTextData(&fTrailingText, trailingText);
363 
364 	Invalidate();
365 }
366 
367 
368 void
369 BStatusBar::Reset(const char *label, const char *trailingLabel)
370 {
371 	// Reset replaces the label and trailing label with copies of the
372 	// strings passed as arguments. If either argument is NULL, the
373 	// label or trailing label will be deleted and erased.
374 	SetTextData(&fLabel, label);
375 	SetTextData(&fTrailingLabel, trailingLabel);
376 
377 	// Reset deletes and erases any text or trailing text
378 	SetTextData(&fText, NULL);
379 	SetTextData(&fTrailingText, NULL);
380 
381 	fCurrent = 0.0f;
382 	fMax = 100.0f;
383 
384 	Invalidate();
385 }
386 
387 
388 float
389 BStatusBar::CurrentValue() const
390 {
391 	return fCurrent;
392 }
393 
394 
395 float
396 BStatusBar::MaxValue() const
397 {
398 	return fMax;
399 }
400 
401 
402 rgb_color
403 BStatusBar::BarColor() const
404 {
405 	return fBarColor;
406 }
407 
408 
409 float
410 BStatusBar::BarHeight() const
411 {
412 	if (!fCustomBarHeight && fBarHeight == -1.0f) {
413 		font_height fh;
414 		GetFontHeight(&fh);
415 		const_cast<BStatusBar *>(this)->fBarHeight = fh.ascent + fh.descent + 6.0f;
416 	}
417 
418 	return fBarHeight;
419 }
420 
421 
422 const char *
423 BStatusBar::Text() const
424 {
425 	return fText;
426 }
427 
428 
429 const char *
430 BStatusBar::TrailingText() const
431 {
432 	return fTrailingText;
433 }
434 
435 
436 const char *
437 BStatusBar::Label() const
438 {
439 	return fLabel;
440 }
441 
442 
443 const char *
444 BStatusBar::TrailingLabel() const
445 {
446 	return fTrailingLabel;
447 }
448 
449 
450 void
451 BStatusBar::MouseDown(BPoint point)
452 {
453 	BView::MouseDown(point);
454 }
455 
456 
457 void
458 BStatusBar::MouseUp(BPoint point)
459 {
460 	BView::MouseUp(point);
461 }
462 
463 
464 void
465 BStatusBar::WindowActivated(bool state)
466 {
467 	BView::WindowActivated(state);
468 }
469 
470 
471 void
472 BStatusBar::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
473 {
474 	BView::MouseMoved(point, transit, message);
475 }
476 
477 
478 void
479 BStatusBar::DetachedFromWindow()
480 {
481 	BView::DetachedFromWindow();
482 }
483 
484 
485 void
486 BStatusBar::FrameMoved(BPoint newPosition)
487 {
488 	BView::FrameMoved(newPosition);
489 }
490 
491 
492 void
493 BStatusBar::FrameResized(float newWidth, float newHeight)
494 {
495 	BView::FrameResized(newWidth, newHeight);
496 }
497 
498 
499 BHandler *
500 BStatusBar::ResolveSpecifier(BMessage *message, int32 index,
501 									   BMessage *specifier,
502 									   int32 what, const char *property)
503 {
504 	return BView::ResolveSpecifier(message, index, specifier, what, property);
505 }
506 
507 
508 void
509 BStatusBar::ResizeToPreferred()
510 {
511 	BView::ResizeToPreferred();
512 }
513 
514 
515 void
516 BStatusBar::GetPreferredSize(float* _width, float* _height)
517 {
518 	if (_width) {
519 		*_width = (fLabel ? (float)ceil(StringWidth(fLabel)) : 0.0f)
520 			+ (fTrailingLabel ? (float)ceil(StringWidth(fTrailingLabel)) : 0.0f)
521 			+ 7.0f;
522 	}
523 
524 	if (_height) {
525 		font_height fontHeight;
526 		GetFontHeight(&fontHeight);
527 
528 		*_height = ceil(fontHeight.ascent + fontHeight.descent) + 5.0f + BarHeight();
529 	}
530 }
531 
532 
533 void
534 BStatusBar::MakeFocus(bool state)
535 {
536 	BView::MakeFocus(state);
537 }
538 
539 
540 void
541 BStatusBar::AllAttached()
542 {
543 	BView::AllAttached();
544 }
545 
546 
547 void
548 BStatusBar::AllDetached()
549 {
550 	BView::AllDetached();
551 }
552 
553 
554 status_t
555 BStatusBar::GetSupportedSuites(BMessage *data)
556 {
557 	return BView::GetSupportedSuites(data);
558 }
559 
560 
561 status_t
562 BStatusBar::Perform(perform_code d, void *arg)
563 {
564 	return BView::Perform(d, arg);
565 }
566 
567 
568 void BStatusBar::_ReservedStatusBar1() {}
569 void BStatusBar::_ReservedStatusBar2() {}
570 void BStatusBar::_ReservedStatusBar3() {}
571 void BStatusBar::_ReservedStatusBar4() {}
572 
573 
574 BStatusBar &
575 BStatusBar::operator=(const BStatusBar &)
576 {
577 	return *this;
578 }
579 
580 
581 void
582 BStatusBar::InitObject(const char *label, const char *trailingLabel)
583 {
584 	SetTextData(&fLabel, label);
585 	SetTextData(&fTrailingLabel, trailingLabel);
586 }
587 
588 
589 void
590 BStatusBar::SetTextData(char **dest, const char *source)
591 {
592 	ASSERT(dest != NULL);
593 
594 	if (*dest != NULL) {
595 		free(*dest);
596 		*dest = NULL;
597 	}
598 
599 	if (source != NULL && source[0] != '\0')
600 		*dest = strdup(source);
601 }
602 
603 
604 void
605 BStatusBar::FillBar(BRect rect)
606 {
607 	// TODO:
608 }
609 
610 
611 void
612 BStatusBar::Resize()
613 {
614 	// TODO:
615 }
616 
617 
618 void
619 BStatusBar::_Draw(BRect updateRect, bool barOnly)
620 {
621 	// TODO:
622 }
623