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