tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / interface / ColumnTypes.cpp
blob8e61228e2ec6ef755eab6d97cb4200b57830c51a
1 /*******************************************************************************
3 / File: ColumnTypes.h
5 / Description: Experimental classes that implement particular column/field
6 / data types for use in BColumnListView.
8 / Copyright 2000+, Be Incorporated, All Rights Reserved
10 *******************************************************************************/
12 #include "ColumnTypes.h"
14 #include <View.h>
16 #include <parsedate.h>
17 #include <stdio.h>
20 #define kTEXT_MARGIN 8
23 const int64 kKB_SIZE = 1024;
24 const int64 kMB_SIZE = 1048576;
25 const int64 kGB_SIZE = 1073741824;
26 const int64 kTB_SIZE = kGB_SIZE * kKB_SIZE;
28 const char* kSIZE_FORMATS[] = {
29 "%.2f %s",
30 "%.1f %s",
31 "%.f %s",
32 "%.f%s",
37 BTitledColumn::BTitledColumn(const char* title, float width, float minWidth,
38 float maxWidth, alignment align)
40 BColumn(width, minWidth, maxWidth, align),
41 fTitle(title)
43 font_height fh;
45 be_plain_font->GetHeight(&fh);
46 fFontHeight = fh.descent + fh.leading;
50 void
51 BTitledColumn::DrawTitle(BRect rect, BView* parent)
53 float width = rect.Width() - (2 * kTEXT_MARGIN);
54 BString out_string(fTitle);
56 parent->TruncateString(&out_string, B_TRUNCATE_END, width + 2);
57 DrawString(out_string.String(), parent, rect);
61 void
62 BTitledColumn::GetColumnName(BString* into) const
64 *into = fTitle;
68 void
69 BTitledColumn::DrawString(const char* string, BView* parent, BRect rect)
71 float width = rect.Width() - (2 * kTEXT_MARGIN);
72 float y;
73 BFont font;
74 font_height finfo;
76 parent->GetFont(&font);
77 font.GetHeight(&finfo);
78 y = rect.top + finfo.ascent
79 + (rect.Height() - ceilf(finfo.ascent + finfo.descent)) / 2.0f;
81 switch (Alignment()) {
82 default:
83 case B_ALIGN_LEFT:
84 parent->MovePenTo(rect.left + kTEXT_MARGIN, y);
85 break;
87 case B_ALIGN_CENTER:
88 parent->MovePenTo(rect.left + kTEXT_MARGIN
89 + ((width - font.StringWidth(string)) / 2), y);
90 break;
92 case B_ALIGN_RIGHT:
93 parent->MovePenTo(rect.right - kTEXT_MARGIN
94 - font.StringWidth(string), y);
95 break;
98 parent->DrawString(string);
102 void
103 BTitledColumn::SetTitle(const char* title)
105 fTitle.SetTo(title);
109 void
110 BTitledColumn::Title(BString* forTitle) const
112 if (forTitle)
113 forTitle->SetTo(fTitle.String());
117 float
118 BTitledColumn::FontHeight() const
120 return fFontHeight;
124 float
125 BTitledColumn::GetPreferredWidth(BField *_field, BView* parent) const
127 return parent->StringWidth(fTitle.String()) + 2 * kTEXT_MARGIN;
131 // #pragma mark - BStringField
134 BStringField::BStringField(const char* string)
136 fWidth(0),
137 fString(string),
138 fClippedString(string)
143 void
144 BStringField::SetString(const char* val)
146 fString = val;
147 fClippedString = "";
148 fWidth = 0;
152 const char*
153 BStringField::String() const
155 return fString.String();
159 void
160 BStringField::SetWidth(float width)
162 fWidth = width;
166 float
167 BStringField::Width()
169 return fWidth;
173 void
174 BStringField::SetClippedString(const char* val)
176 fClippedString = val;
180 bool
181 BStringField::HasClippedString() const
183 return !fClippedString.IsEmpty();
187 const char*
188 BStringField::ClippedString()
190 return fClippedString.String();
194 // #pragma mark - BStringColumn
197 BStringColumn::BStringColumn(const char* title, float width, float minWidth,
198 float maxWidth, uint32 truncate, alignment align)
200 BTitledColumn(title, width, minWidth, maxWidth, align),
201 fTruncate(truncate)
206 void
207 BStringColumn::DrawField(BField* _field, BRect rect, BView* parent)
209 float width = rect.Width() - (2 * kTEXT_MARGIN);
210 BStringField* field = static_cast<BStringField*>(_field);
211 float fieldWidth = field->Width();
212 bool updateNeeded = width != fieldWidth;
214 if (updateNeeded) {
215 BString out_string(field->String());
216 float preferredWidth = parent->StringWidth(out_string.String());
217 if (width < preferredWidth) {
218 parent->TruncateString(&out_string, fTruncate, width + 2);
219 field->SetClippedString(out_string.String());
220 } else
221 field->SetClippedString("");
222 field->SetWidth(width);
225 DrawString(field->HasClippedString()
226 ? field->ClippedString()
227 : field->String(), parent, rect);
231 float
232 BStringColumn::GetPreferredWidth(BField *_field, BView* parent) const
234 BStringField* field = static_cast<BStringField*>(_field);
235 return parent->StringWidth(field->String()) + 2 * kTEXT_MARGIN;
240 BStringColumn::CompareFields(BField* field1, BField* field2)
242 return ICompare(((BStringField*)field1)->String(),
243 (((BStringField*)field2)->String()));
247 bool
248 BStringColumn::AcceptsField(const BField *field) const
250 return static_cast<bool>(dynamic_cast<const BStringField*>(field));
254 // #pragma mark - BDateField
257 BDateField::BDateField(time_t* time)
259 fTime(*localtime(time)),
260 fUnixTime(*time),
261 fSeconds(0),
262 fClippedString(""),
263 fWidth(0)
265 fSeconds = mktime(&fTime);
269 void
270 BDateField::SetWidth(float width)
272 fWidth = width;
276 float
277 BDateField::Width()
279 return fWidth;
283 void
284 BDateField::SetClippedString(const char* string)
286 fClippedString = string;
290 const char*
291 BDateField::ClippedString()
293 return fClippedString.String();
297 time_t
298 BDateField::Seconds()
300 return fSeconds;
304 time_t
305 BDateField::UnixTime()
307 return fUnixTime;
311 // #pragma mark - BDateColumn
314 BDateColumn::BDateColumn(const char* title, float width, float minWidth,
315 float maxWidth, alignment align)
317 BTitledColumn(title, width, minWidth, maxWidth, align),
318 fTitle(title)
323 const char *kTIME_FORMATS[] = {
324 "%A, %B %d %Y, %I:%M:%S %p", // Monday, July 09 1997, 05:08:15 PM
325 "%a, %b %d %Y, %I:%M:%S %p", // Mon, Jul 09 1997, 05:08:15 PM
326 "%a, %b %d %Y, %I:%M %p", // Mon, Jul 09 1997, 05:08 PM
327 "%b %d %Y, %I:%M %p", // Jul 09 1997, 05:08 PM
328 "%m/%d/%y, %I:%M %p", // 07/09/97, 05:08 PM
329 "%m/%d/%y", // 07/09/97
330 NULL
334 void
335 BDateColumn::DrawField(BField* _field, BRect rect, BView* parent)
337 float width = rect.Width() - (2 * kTEXT_MARGIN);
338 BDateField* field = (BDateField*)_field;
340 if (field->Width() != rect.Width()) {
341 char dateString[256];
342 time_t currentTime = field->UnixTime();
343 tm time_data;
344 BFont font;
346 parent->GetFont(&font);
347 localtime_r(&currentTime, &time_data);
349 for (int32 index = 0; ; index++) {
350 if (!kTIME_FORMATS[index])
351 break;
353 strftime(dateString, 256, kTIME_FORMATS[index], &time_data);
354 if (font.StringWidth(dateString) <= width)
355 break;
358 if (font.StringWidth(dateString) > width) {
359 BString out_string(dateString);
361 parent->TruncateString(&out_string, B_TRUNCATE_MIDDLE, width + 2);
362 strcpy(dateString, out_string.String());
364 field->SetClippedString(dateString);
365 field->SetWidth(width);
368 DrawString(field->ClippedString(), parent, rect);
373 BDateColumn::CompareFields(BField* field1, BField* field2)
375 return((BDateField*)field1)->Seconds() - ((BDateField*)field2)->Seconds();
379 // #pragma mark - BSizeField
382 BSizeField::BSizeField(off_t size)
384 fSize(size)
389 void
390 BSizeField::SetSize(off_t size)
392 fSize = size;
396 off_t
397 BSizeField::Size()
399 return fSize;
403 // #pragma mark - BSizeColumn
406 BSizeColumn::BSizeColumn(const char* title, float width, float minWidth,
407 float maxWidth, alignment align)
409 BTitledColumn(title, width, minWidth, maxWidth, align)
414 void
415 BSizeColumn::DrawField(BField* _field, BRect rect, BView* parent)
417 char str[256];
418 float width = rect.Width() - (2 * kTEXT_MARGIN);
419 BFont font;
420 BString string;
421 off_t size = ((BSizeField*)_field)->Size();
423 parent->GetFont(&font);
424 if (size < kKB_SIZE) {
425 sprintf(str, "%" B_PRId64 " bytes", size);
426 if (font.StringWidth(str) > width)
427 sprintf(str, "%" B_PRId64 " B", size);
428 } else {
429 const char* suffix;
430 float float_value;
431 if (size >= kTB_SIZE) {
432 suffix = "TB";
433 float_value = (float)size / kTB_SIZE;
434 } else if (size >= kGB_SIZE) {
435 suffix = "GB";
436 float_value = (float)size / kGB_SIZE;
437 } else if (size >= kMB_SIZE) {
438 suffix = "MB";
439 float_value = (float)size / kMB_SIZE;
440 } else {
441 suffix = "KB";
442 float_value = (float)size / kKB_SIZE;
445 for (int32 index = 0; ; index++) {
446 if (!kSIZE_FORMATS[index])
447 break;
449 sprintf(str, kSIZE_FORMATS[index], float_value, suffix);
450 // strip off an insignificant zero so we don't get readings
451 // such as 1.00
452 char *period = 0;
453 char *tmp (NULL);
454 for (tmp = str; *tmp; tmp++) {
455 if (*tmp == '.')
456 period = tmp;
458 if (period && period[1] && period[2] == '0') {
459 // move the rest of the string over the insignificant zero
460 for (tmp = &period[2]; *tmp; tmp++)
461 *tmp = tmp[1];
463 if (font.StringWidth(str) <= width)
464 break;
468 string = str;
469 parent->TruncateString(&string, B_TRUNCATE_MIDDLE, width + 2);
470 DrawString(string.String(), parent, rect);
475 BSizeColumn::CompareFields(BField* field1, BField* field2)
477 return ((BSizeField*)field1)->Size() - ((BSizeField*)field2)->Size();
481 // #pragma mark - BIntegerField
484 BIntegerField::BIntegerField(int32 number)
486 fInteger(number)
491 void
492 BIntegerField::SetValue(int32 value)
494 fInteger = value;
498 int32
499 BIntegerField::Value()
501 return fInteger;
505 // #pragma mark - BIntegerColumn
508 BIntegerColumn::BIntegerColumn(const char* title, float width, float minWidth,
509 float maxWidth, alignment align)
511 BTitledColumn(title, width, minWidth, maxWidth, align)
516 void
517 BIntegerColumn::DrawField(BField *field, BRect rect, BView* parent)
519 char formatted[256];
520 float width = rect.Width() - (2 * kTEXT_MARGIN);
521 BString string;
523 sprintf(formatted, "%d", (int)((BIntegerField*)field)->Value());
525 string = formatted;
526 parent->TruncateString(&string, B_TRUNCATE_MIDDLE, width + 2);
527 DrawString(string.String(), parent, rect);
532 BIntegerColumn::CompareFields(BField *field1, BField *field2)
534 return (((BIntegerField*)field1)->Value() - ((BIntegerField*)field2)->Value());
538 // #pragma mark - GraphColumn
541 GraphColumn::GraphColumn(const char* name, float width, float minWidth,
542 float maxWidth, alignment align)
544 BIntegerColumn(name, width, minWidth, maxWidth, align)
549 void
550 GraphColumn::DrawField(BField* field, BRect rect, BView* parent)
552 int number = ((BIntegerField*)field)->Value();
554 if (number > 100)
555 number = 100;
556 else if (number < 0)
557 number = 0;
559 BRect graphRect(rect);
560 graphRect.InsetBy(5, 3);
561 parent->StrokeRect(graphRect);
562 if (number > 0) {
563 graphRect.InsetBy(1, 1);
564 float value = graphRect.Width() * (float)number / 100;
565 graphRect.right = graphRect.left + value;
566 parent->SetHighColor(0, 0, 190);
567 parent->FillRect(graphRect);
570 parent->SetDrawingMode(B_OP_INVERT);
571 parent->SetHighColor(128, 128, 128);
572 char numberString[256];
573 sprintf(numberString, "%d%%", number);
575 float width = be_plain_font->StringWidth(numberString);
576 parent->MovePenTo(rect.left + rect.Width() / 2 - width / 2, rect.bottom - FontHeight());
577 parent->DrawString(numberString);
581 // #pragma mark - BBitmapField
584 BBitmapField::BBitmapField(BBitmap* bitmap)
586 fBitmap(bitmap)
591 const BBitmap*
592 BBitmapField::Bitmap()
594 return fBitmap;
598 void
599 BBitmapField::SetBitmap(BBitmap* bitmap)
601 fBitmap = bitmap;
605 // #pragma mark - BBitmapColumn
608 BBitmapColumn::BBitmapColumn(const char* title, float width, float minWidth,
609 float maxWidth, alignment align)
611 BTitledColumn(title, width, minWidth, maxWidth, align)
616 void
617 BBitmapColumn::DrawField(BField* field, BRect rect, BView* parent)
619 BBitmapField* bitmapField = static_cast<BBitmapField*>(field);
620 const BBitmap* bitmap = bitmapField->Bitmap();
622 if (bitmap != NULL) {
623 float x = 0.0;
624 BRect r = bitmap->Bounds();
625 float y = rect.top + ((rect.Height() - r.Height()) / 2);
627 switch (Alignment()) {
628 default:
629 case B_ALIGN_LEFT:
630 x = rect.left + kTEXT_MARGIN;
631 break;
633 case B_ALIGN_CENTER:
634 x = rect.left + ((rect.Width() - r.Width()) / 2);
635 break;
637 case B_ALIGN_RIGHT:
638 x = rect.right - kTEXT_MARGIN - r.Width();
639 break;
641 // setup drawing mode according to bitmap color space,
642 // restore previous mode after drawing
643 drawing_mode oldMode = parent->DrawingMode();
644 if (bitmap->ColorSpace() == B_RGBA32
645 || bitmap->ColorSpace() == B_RGBA32_BIG) {
646 parent->SetDrawingMode(B_OP_ALPHA);
647 parent->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
648 } else {
649 parent->SetDrawingMode(B_OP_OVER);
652 parent->DrawBitmap(bitmap, BPoint(x, y));
654 parent->SetDrawingMode(oldMode);
660 BBitmapColumn::CompareFields(BField* /*field1*/, BField* /*field2*/)
662 // Comparing bitmaps doesn't really make sense...
663 return 0;
667 bool
668 BBitmapColumn::AcceptsField(const BField *field) const
670 return static_cast<bool>(dynamic_cast<const BBitmapField*>(field));