xref: /haiku/src/kits/interface/StatusBar.cpp (revision 7120e97489acbf17d86d3f33e3b2e68974fd4b23)
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 <malloc.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 	// TODO: Should we 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 		SetViewColor(Parent ()->ViewColor());
205 }
206 //------------------------------------------------------------------------------
207 void BStatusBar::MessageReceived(BMessage *message)
208 {
209 	switch(message->what)
210 	{
211 		case B_UPDATE_STATUS_BAR:
212 		{
213 			float delta;
214 			const char *text = NULL, *trailing_text = NULL;
215 
216 			message->FindFloat("delta", &delta);
217 			message->FindString("text", &text);
218 			message->FindString("trailing text", &trailing_text);
219 
220 			Update(delta, text, trailing_text);
221 
222 			break;
223 		}
224 		case B_RESET_STATUS_BAR:
225 		{
226 			const char *label = NULL, *trailing_label = NULL;
227 
228 			message->FindString("label", &label);
229 			message->FindString("trailing label", &trailing_label);
230 
231 			Reset(label, trailing_label);
232 
233 			break;
234 		}
235 		default:
236 			BView::MessageReceived ( message );
237 	}
238 }
239 //------------------------------------------------------------------------------
240 void BStatusBar::Draw(BRect updateRect)
241 {
242 	float width = Frame().Width();
243 	font_height fh;
244 	GetFontHeight(&fh);
245 
246 	SetHighColor(0, 0, 0);
247 	MovePenTo(2.0f, (float)ceil(fh.ascent) + 1.0f);
248 
249 	if (fLabel)
250 		DrawString(fLabel);
251 	if (fText)
252 		DrawString(fText);
253 
254 	if (fTrailingText)
255 	{
256 		if (fTrailingLabel)
257 		{
258 			MovePenTo(width - StringWidth(fTrailingText) -
259 			StringWidth(fTrailingLabel) - 2.0f,
260 			(float)ceil(fh.ascent) + 1.0f);
261 			DrawString(fTrailingText);
262 			DrawString(fTrailingLabel);
263 		}
264 		else
265 		{
266 			MovePenTo(width - StringWidth(fTrailingText) - 2.0f,
267 			(float)ceil(fh.ascent) + 1.0f);
268 			DrawString(fTrailingText);
269 		}
270 
271 	}
272 	else if (fTrailingLabel)
273 	{
274 		MovePenTo(width - StringWidth(fTrailingLabel) - 2.0f,
275 			(float)ceil(fh.ascent) + 1.0f);
276 		DrawString(fTrailingLabel);
277 	}
278 
279 	BRect rect(0.0f, (float)ceil(fh.ascent) + 4.0f, width,
280 		(float)ceil(fh.ascent) + 4.0f + fBarHeight);
281 
282 	// First bevel
283 	SetHighColor(tint_color(ui_color ( B_PANEL_BACKGROUND_COLOR ), B_DARKEN_1_TINT));
284 	StrokeLine(BPoint(rect.left, rect.bottom), BPoint(rect.left, rect.top));
285 	StrokeLine(BPoint(rect.right, rect.top));
286 
287 	SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_2_TINT));
288 	StrokeLine(BPoint(rect.left + 1.0f, rect.bottom), BPoint(rect.right, rect.bottom));
289 	StrokeLine(BPoint(rect.right, rect.top + 1.0f));
290 
291 	rect.InsetBy(1.0f, 1.0f);
292 
293 	// Second bevel
294 	SetHighColor(tint_color(ui_color ( B_PANEL_BACKGROUND_COLOR ), B_DARKEN_4_TINT));
295 	StrokeLine(BPoint(rect.left, rect.bottom), BPoint(rect.left, rect.top));
296 	StrokeLine(BPoint(rect.right, rect.top));
297 
298 	SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
299 	StrokeLine(BPoint(rect.left + 1.0f, rect.bottom), BPoint(rect.right, rect.bottom));
300 	StrokeLine(BPoint(rect.right, rect.top + 1.0f));
301 
302 	rect.InsetBy(1.0f, 1.0f);
303 
304 	// Filling
305 	SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_MAX_TINT));
306 	FillRect(rect);
307 
308 	if (fCurrent != 0.0f)
309 	{
310 		rect.right = rect.left + (float)ceil(fCurrent * (width - 4) / fMax),
311 
312 		// Bevel
313 		SetHighColor(tint_color(fBarColor, B_LIGHTEN_2_TINT));
314 		StrokeLine(BPoint(rect.left, rect.bottom), BPoint(rect.left, rect.top));
315 		StrokeLine(BPoint(rect.right, rect.top));
316 
317 		SetHighColor(tint_color(fBarColor, B_DARKEN_2_TINT));
318 		StrokeLine(BPoint(rect.left, rect.bottom), BPoint(rect.right, rect.bottom));
319 		StrokeLine(BPoint(rect.right, rect.top));
320 
321 		rect.InsetBy(1.0f, 1.0f);
322 
323 		// Filling
324 		SetHighColor(fBarColor);
325 		FillRect(rect);
326 	}
327 }
328 //------------------------------------------------------------------------------
329 void BStatusBar::SetBarColor(rgb_color color)
330 {
331 	memcpy(&fBarColor, &color, sizeof(rgb_color));
332 
333 	Invalidate();
334 }
335 //------------------------------------------------------------------------------
336 void BStatusBar::SetBarHeight(float height)
337 {
338 	BRect frame = Frame();
339 
340 	fBarHeight = height;
341 	fCustomBarHeight = true;
342 	ResizeTo(frame.Width(), fBarHeight + 16);
343 }
344 //------------------------------------------------------------------------------
345 void BStatusBar::SetText ( const char *string )
346 {
347 	if (fText)
348 		free(fText);
349 
350 	fText = strdup(string);
351 
352 	Invalidate();
353 }
354 //------------------------------------------------------------------------------
355 void BStatusBar::SetTrailingText(const char *string)
356 {
357 	if (fTrailingText)
358 		free(fTrailingText);
359 
360 	fTrailingText = strdup(string);
361 
362 	Invalidate();
363 }
364 //------------------------------------------------------------------------------
365 void BStatusBar::SetMaxValue(float max)
366 {
367 	fMax = max;
368 
369 	Invalidate();
370 }
371 //------------------------------------------------------------------------------
372 void BStatusBar::Update(float delta, const char *text, const char *trailingText)
373 {
374 	fCurrent += delta;
375 
376 	if (fCurrent > fMax)
377 		fCurrent = fMax;
378 
379 	if (fText)
380 		free(fText);
381 
382 	fText = strdup(text);
383 
384 	if (fTrailingText)
385 		free(fTrailingText);
386 
387 	fTrailingText = strdup(trailingText);
388 
389 	Invalidate();
390 }
391 //------------------------------------------------------------------------------
392 void BStatusBar::Reset(const char *label, const char *trailingLabel)
393 {
394 	if (fLabel)
395 		free(fLabel);
396 
397 	fLabel = strdup(label);
398 
399 	if (fTrailingLabel)
400 		free(fTrailingLabel);
401 
402 	fTrailingLabel = strdup(trailingLabel);
403 
404 	fCurrent = 0.0f;
405 
406 	Invalidate();
407 }
408 float BStatusBar::CurrentValue() const
409 {
410 	return fCurrent;
411 }
412 //------------------------------------------------------------------------------
413 float BStatusBar::MaxValue() const
414 {
415 	return fMax;
416 }
417 //------------------------------------------------------------------------------
418 rgb_color BStatusBar::BarColor() const
419 {
420 	return fBarColor;
421 }
422 //------------------------------------------------------------------------------
423 float BStatusBar::BarHeight() const
424 {
425 	if (!fCustomBarHeight && fBarHeight == -1.0f)
426 	{
427 		font_height fh;
428 		GetFontHeight(&fh);
429 		((BStatusBar*)this)->fBarHeight = fh.ascent + fh.descent + 6.0f;
430 	}
431 
432 	return fBarHeight;
433 }
434 //------------------------------------------------------------------------------
435 const char *BStatusBar::Text() const
436 {
437 	return fText;
438 }
439 //------------------------------------------------------------------------------
440 const char *BStatusBar::TrailingText() const
441 {
442 	return fTrailingText;
443 }
444 //------------------------------------------------------------------------------
445 const char *BStatusBar::Label() const
446 {
447 	return fLabel;
448 }
449 //------------------------------------------------------------------------------
450 const char *BStatusBar::TrailingLabel() const
451 {
452 	return fTrailingLabel;
453 }
454 //------------------------------------------------------------------------------
455 void BStatusBar::MouseDown(BPoint point)
456 {
457 	BView::MouseDown(point);
458 }
459 //------------------------------------------------------------------------------
460 void BStatusBar::MouseUp(BPoint point)
461 {
462 	BView::MouseUp(point);
463 }
464 //------------------------------------------------------------------------------
465 void BStatusBar::WindowActivated(bool state)
466 {
467 	BView::WindowActivated(state);
468 }
469 //------------------------------------------------------------------------------
470 void BStatusBar::MouseMoved(BPoint point, uint32 transit,
471 							const BMessage *message)
472 {
473 	BView::MouseMoved(point, transit, message);
474 }
475 //------------------------------------------------------------------------------
476 void BStatusBar::DetachedFromWindow()
477 {
478 	BView::DetachedFromWindow();
479 }
480 //------------------------------------------------------------------------------
481 void BStatusBar::FrameMoved(BPoint new_position)
482 {
483 	BView::FrameMoved(new_position);
484 }
485 //------------------------------------------------------------------------------
486 void BStatusBar::FrameResized(float new_width, float new_height)
487 {
488 	BView::FrameResized(new_width, new_height);
489 }
490 //------------------------------------------------------------------------------
491 BHandler *BStatusBar::ResolveSpecifier(BMessage *message, int32 index,
492 									   BMessage *specifier,
493 									   int32 what, const char *property)
494 {
495 	return BView::ResolveSpecifier(message, index, specifier, what, property);
496 }
497 //------------------------------------------------------------------------------
498 void BStatusBar::ResizeToPreferred()
499 {
500 	BView::ResizeToPreferred();
501 }
502 //------------------------------------------------------------------------------
503 void BStatusBar::GetPreferredSize(float *width, float *height)
504 {
505 	font_height fh;
506 	GetFontHeight(&fh);
507 
508 	*width = (fLabel ? (float)ceil(StringWidth(fLabel)) : 0.0f) +
509 		(fTrailingLabel ? (float)ceil(StringWidth(fTrailingLabel)) : 0.0f) +
510 		7.0f;
511 	*height = fh.ascent + fh.descent + 5.0f + BarHeight();
512 }
513 //------------------------------------------------------------------------------
514 void BStatusBar::MakeFocus(bool state)
515 {
516 	BView::MakeFocus(state);
517 }
518 //------------------------------------------------------------------------------
519 void BStatusBar::AllAttached()
520 {
521 	BView::AllAttached();
522 }
523 //------------------------------------------------------------------------------
524 void BStatusBar::AllDetached()
525 {
526 	BView::AllDetached();
527 }
528 //------------------------------------------------------------------------------
529 status_t BStatusBar::GetSupportedSuites(BMessage *data)
530 {
531 	return BView::GetSupportedSuites(data);
532 }
533 //------------------------------------------------------------------------------
534 status_t BStatusBar::Perform(perform_code d, void *arg)
535 {
536 	return B_ERROR;
537 }
538 //------------------------------------------------------------------------------
539 void BStatusBar::_ReservedStatusBar1() {}
540 void BStatusBar::_ReservedStatusBar2() {}
541 void BStatusBar::_ReservedStatusBar3() {}
542 void BStatusBar::_ReservedStatusBar4() {}
543 
544 //------------------------------------------------------------------------------
545 BStatusBar &BStatusBar::operator=(const BStatusBar &)
546 {
547 	return *this;
548 }
549 //------------------------------------------------------------------------------
550 void BStatusBar::InitObject(const char *l, const char *aux_l)
551 {
552 	// TODO:
553 }
554 //------------------------------------------------------------------------------
555 void BStatusBar::SetTextData(char **pp, const char *str)
556 {
557 	// TODO:
558 }
559 //------------------------------------------------------------------------------
560 void BStatusBar::FillBar(BRect r)
561 {
562 	// TODO:
563 }
564 //------------------------------------------------------------------------------
565 void BStatusBar::Resize()
566 {
567 	// TODO:
568 }
569 //------------------------------------------------------------------------------
570 void BStatusBar::_Draw(BRect updateRect, bool bar_only)
571 {
572 	// TODO:
573 }
574 //------------------------------------------------------------------------------
575 
576 /*
577  * $Log $
578  *
579  * $Id  $
580  *
581  */
582