2 * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 * Distributed under the terms of the MIT License.
7 #include "TypeEditors.h"
8 #include "DataEditor.h"
17 #include <IconUtils.h>
18 #include <LayoutBuilder.h>
20 #include <MenuField.h>
23 #include <PopUpMenu.h>
24 #include <ScrollBar.h>
25 #include <ScrollView.h>
28 #include <StringView.h>
29 #include <TextControl.h>
31 #include <TranslationUtils.h>
32 #include <TranslatorFormats.h>
35 #undef B_TRANSLATION_CONTEXT
36 #define B_TRANSLATION_CONTEXT "TypeEditors"
38 static const uint32 kMsgValueChanged
= 'vlch';
39 static const uint32 kMsgScaleChanged
= 'scch';
40 static const uint32 kMimeTypeItem
= 'miti';
43 class StringEditor
: public TypeEditorView
{
45 StringEditor(DataEditor
& editor
);
47 virtual void AttachedToWindow();
48 virtual void DetachedFromWindow();
49 virtual void MessageReceived(BMessage
* message
);
51 virtual void CommitChanges();
57 BString fPreviousText
;
61 class MimeTypeEditor
: public TypeEditorView
{
63 MimeTypeEditor(BRect rect
, DataEditor
& editor
);
65 virtual void AttachedToWindow();
66 virtual void DetachedFromWindow();
67 virtual void MessageReceived(BMessage
* message
);
69 virtual void CommitChanges();
70 virtual bool TypeMatches();
75 BTextControl
* fTextControl
;
76 BString fPreviousText
;
80 class NumberEditor
: public TypeEditorView
{
82 NumberEditor(BRect rect
, DataEditor
& editor
);
84 virtual void AttachedToWindow();
85 virtual void DetachedFromWindow();
86 virtual void MessageReceived(BMessage
* message
);
88 virtual void CommitChanges();
89 virtual bool TypeMatches();
93 const char* _TypeLabel();
94 status_t
_Format(char* buffer
);
97 BTextControl
* fTextControl
;
98 BString fPreviousText
;
102 class BooleanEditor
: public TypeEditorView
{
104 BooleanEditor(BRect rect
, DataEditor
& editor
);
106 virtual void AttachedToWindow();
107 virtual void DetachedFromWindow();
108 virtual void MessageReceived(BMessage
* message
);
110 virtual void CommitChanges();
111 virtual bool TypeMatches();
114 void _UpdateMenuField();
116 BMenuItem
* fFalseMenuItem
;
117 BMenuItem
* fTrueMenuItem
;
121 class ImageView
: public TypeEditorView
{
123 ImageView(DataEditor
&editor
);
124 virtual ~ImageView();
126 virtual void AttachedToWindow();
127 virtual void DetachedFromWindow();
128 virtual void MessageReceived(BMessage
*message
);
129 virtual void Draw(BRect updateRect
);
135 BStringView
* fDescriptionView
;
136 BSlider
* fScaleSlider
;
140 class MessageView
: public TypeEditorView
{
142 MessageView(BRect rect
, DataEditor
& editor
);
143 virtual ~MessageView();
145 virtual void AttachedToWindow();
146 virtual void DetachedFromWindow();
147 virtual void MessageReceived(BMessage
* message
);
149 void SetTo(BMessage
& message
);
152 BString
_TypeToString(type_code type
);
153 void _UpdateMessage();
155 BTextView
* fTextView
;
159 // #pragma mark - TypeEditorView
162 TypeEditorView::TypeEditorView(BRect rect
, const char *name
,
163 uint32 resizingMode
, uint32 flags
, DataEditor
& editor
)
164 : BView(rect
, name
, resizingMode
, flags
),
170 TypeEditorView::TypeEditorView(const char *name
, uint32 flags
,
172 : BView(name
, flags
),
178 TypeEditorView::~TypeEditorView()
184 TypeEditorView::CommitChanges()
186 // the default just does nothing here
191 TypeEditorView::TypeMatches()
193 // the default is to accept anything that easily fits into memory
196 get_system_info(&info
);
198 return uint64(fEditor
.FileSize()) / B_PAGE_SIZE
< info
.max_pages
/ 2;
202 // #pragma mark - StringEditor
205 StringEditor::StringEditor(DataEditor
& editor
)
206 : TypeEditorView(B_TRANSLATE("String editor"), 0, editor
)
208 SetViewUIColor(B_PANEL_BACKGROUND_COLOR
);
209 SetLayout(new BGroupLayout(B_VERTICAL
));
211 BStringView
*stringView
= new BStringView(B_EMPTY_STRING
,
212 B_TRANSLATE("Contents:"));
213 stringView
->ResizeToPreferred();
214 AddChild(stringView
);
216 fTextView
= new BTextView(B_EMPTY_STRING
, B_WILL_DRAW
);
218 BScrollView
* scrollView
= new BScrollView("scroller", fTextView
,
219 B_WILL_DRAW
, true, true);
220 AddChild(scrollView
);
225 StringEditor::_UpdateText()
227 BAutolock
locker(fEditor
);
229 size_t viewSize
= fEditor
.ViewSize();
230 // that may need some more memory...
231 if ((off_t
)viewSize
< fEditor
.FileSize())
232 fEditor
.SetViewSize(fEditor
.FileSize());
235 if (fEditor
.GetViewBuffer((const uint8
**)&buffer
) == B_OK
) {
236 fTextView
->SetText(buffer
);
237 fPreviousText
.SetTo(buffer
);
240 // restore old view size
241 fEditor
.SetViewSize(viewSize
);
246 StringEditor::CommitChanges()
248 if (fPreviousText
!= fTextView
->Text()) {
249 fEditor
.Replace(0, (const uint8
*)fTextView
->Text(),
250 fTextView
->TextLength() + 1);
256 StringEditor::AttachedToWindow()
258 fEditor
.StartWatching(this);
265 StringEditor::DetachedFromWindow()
267 fEditor
.StopWatching(this);
274 StringEditor::MessageReceived(BMessage
*message
)
276 BView::MessageReceived(message
);
280 // #pragma mark - MimeTypeEditor
283 MimeTypeEditor::MimeTypeEditor(BRect rect
, DataEditor
& editor
)
284 : TypeEditorView(rect
, B_TRANSLATE("MIME type editor"), B_FOLLOW_LEFT_RIGHT
, 0, editor
)
286 SetViewUIColor(B_PANEL_BACKGROUND_COLOR
);
288 fTextControl
= new BTextControl(rect
.InsetByCopy(5, 5), B_EMPTY_STRING
,
289 B_TRANSLATE("MIME type:"), NULL
, new BMessage(kMsgValueChanged
), B_FOLLOW_ALL
);
290 fTextControl
->SetDivider(StringWidth(fTextControl
->Label()) + 8);
293 fTextControl
->GetPreferredSize(&width
, &height
);
294 fTextControl
->ResizeTo(rect
.Width() - 10, height
);
296 ResizeTo(rect
.Width(), height
+ 10);
298 AddChild(fTextControl
);
303 MimeTypeEditor::_UpdateText()
305 BAutolock
locker(fEditor
);
307 const char* mimeType
;
308 if (fEditor
.GetViewBuffer((const uint8
**)&mimeType
) == B_OK
) {
309 fTextControl
->SetText(mimeType
);
310 fPreviousText
.SetTo(mimeType
);
316 MimeTypeEditor::CommitChanges()
318 if (fPreviousText
!= fTextControl
->Text()) {
319 fEditor
.Replace(0, (const uint8
*)fTextControl
->Text(),
320 strlen(fTextControl
->Text()) + 1);
326 MimeTypeEditor::TypeMatches()
328 // TODO: check contents?
329 return fEditor
.FileSize() <= B_MIME_TYPE_LENGTH
;
334 MimeTypeEditor::AttachedToWindow()
336 fTextControl
->SetTarget(this);
337 fEditor
.StartWatching(this);
344 MimeTypeEditor::DetachedFromWindow()
346 fEditor
.StopWatching(this);
353 MimeTypeEditor::MessageReceived(BMessage
*message
)
355 switch (message
->what
) {
356 case kMsgValueChanged
:
357 fEditor
.Replace(0, (const uint8
*)fTextControl
->Text(),
358 strlen(fTextControl
->Text()) + 1);
361 case kMsgDataEditorUpdate
:
366 BView::MessageReceived(message
);
371 // #pragma mark - NumberEditor
374 NumberEditor::NumberEditor(BRect rect
, DataEditor
&editor
)
375 : TypeEditorView(rect
, B_TRANSLATE("Number editor"), B_FOLLOW_LEFT_RIGHT
, 0, editor
)
377 SetViewUIColor(B_PANEL_BACKGROUND_COLOR
);
379 fTextControl
= new BTextControl(rect
.InsetByCopy(5, 5), B_EMPTY_STRING
,
380 _TypeLabel(), NULL
, new BMessage(kMsgValueChanged
), B_FOLLOW_ALL
);
381 fTextControl
->SetDivider(StringWidth(fTextControl
->Label()) + 8);
382 fTextControl
->SetAlignment(B_ALIGN_RIGHT
, B_ALIGN_RIGHT
);
383 ResizeTo(rect
.Width(), 30);
385 AddChild(fTextControl
);
390 NumberEditor::_UpdateText()
392 if (fEditor
.Lock()) {
394 if (fEditor
.GetViewBuffer((const uint8
**)&number
) == B_OK
) {
397 switch (fEditor
.Type()) {
400 float value
= *(float*)number
;
401 snprintf(buffer
, sizeof(buffer
), "%g", value
);
406 double value
= *(double *)number
;
407 snprintf(buffer
, sizeof(buffer
), "%g", value
);
421 int8 value
= *(int8
*)number
;
422 snprintf(buffer
, sizeof(buffer
), format
, value
);
427 int16 value
= *(int16
*)number
;
428 snprintf(buffer
, sizeof(buffer
), format
, value
);
433 int32 value
= *(int32
*)number
;
434 snprintf(buffer
, sizeof(buffer
), format
, value
);
439 int64 value
= *(int64
*)number
;
440 snprintf(buffer
, sizeof(buffer
), format
, value
);
453 uint8 value
= *(uint8
*)number
;
454 snprintf(buffer
, sizeof(buffer
), format
, value
);
459 uint16 value
= *(uint16
*)number
;
460 snprintf(buffer
, sizeof(buffer
), format
, value
);
465 uint32 value
= *(uint32
*)number
;
466 snprintf(buffer
, sizeof(buffer
), format
, value
);
471 uint64 value
= *(uint64
*)number
;
472 snprintf(buffer
, sizeof(buffer
), format
, value
);
479 fTextControl
->SetText(buffer
);
480 fPreviousText
.SetTo(buffer
);
489 NumberEditor::TypeMatches()
491 return fEditor
.FileSize() >= (off_t
)_Size();
492 // we only look at as many bytes we need to
497 NumberEditor::CommitChanges()
499 if (fPreviousText
== fTextControl
->Text())
502 const char *number
= fTextControl
->Text();
505 switch (fEditor
.Type()) {
508 float value
= strtod(number
, NULL
);
509 *(float *)buffer
= value
;
514 double value
= strtod(number
, NULL
);
515 *(double *)buffer
= value
;
520 int64 value
= strtoll(number
, NULL
, 0);
521 if (value
> CHAR_MAX
)
523 else if (value
< CHAR_MIN
)
525 *(int8
*)buffer
= (int8
)value
;
530 int64 value
= strtoull(number
, NULL
, 0);
531 if (value
> UCHAR_MAX
)
533 *(uint8
*)buffer
= (uint8
)value
;
538 int64 value
= strtoll(number
, NULL
, 0);
539 if (value
> SHRT_MAX
)
541 else if (value
< SHRT_MIN
)
543 *(int16
*)buffer
= (int16
)value
;
548 int64 value
= strtoull(number
, NULL
, 0);
549 if (value
> USHRT_MAX
)
551 *(uint16
*)buffer
= (uint16
)value
;
557 int64 value
= strtoll(number
, NULL
, 0);
558 if (value
> LONG_MAX
)
560 else if (value
< LONG_MIN
)
562 *(int32
*)buffer
= (int32
)value
;
569 uint64 value
= strtoull(number
, NULL
, 0);
570 if (value
> ULONG_MAX
)
572 *(uint32
*)buffer
= (uint32
)value
;
578 int64 value
= strtoll(number
, NULL
, 0);
579 *(int64
*)buffer
= value
;
584 uint64 value
= strtoull(number
, NULL
, 0);
585 *(uint64
*)buffer
= value
;
592 fEditor
.Replace(0, buffer
, _Size());
593 fPreviousText
.SetTo((char *)buffer
);
598 NumberEditor::_TypeLabel()
600 switch (fEditor
.Type()) {
602 return B_TRANSLATE("8 bit signed value:");
604 return B_TRANSLATE("8 bit unsigned value:");
606 return B_TRANSLATE("16 bit signed value:");
608 return B_TRANSLATE("16 bit unsigned value:");
610 return B_TRANSLATE("32 bit signed value:");
612 return B_TRANSLATE("32 bit unsigned value:");
614 return B_TRANSLATE("64 bit signed value:");
616 return B_TRANSLATE("64 bit unsigned value:");
618 return B_TRANSLATE("Floating-point value:");
620 return B_TRANSLATE("Double precision floating-point value:");
622 return B_TRANSLATE("32 bit size or status:");
624 return B_TRANSLATE("32 bit unsigned size:");
626 return B_TRANSLATE("64 bit signed offset:");
628 return B_TRANSLATE("32 bit unsigned pointer:");
630 return B_TRANSLATE("Number:");
636 NumberEditor::_Size()
638 switch (fEditor
.Type()) {
667 NumberEditor::_Format(char *buffer
)
669 switch (fEditor
.Type()) {
671 strcpy(buffer
, "%hd");
674 strcpy(buffer
, "%hu");
677 strcpy(buffer
, "%hd");
680 strcpy(buffer
, "%hu");
684 strcpy(buffer
, "%ld");
689 strcpy(buffer
, "%lu");
693 strcpy(buffer
, "%Ld");
696 strcpy(buffer
, "%Lu");
699 strcpy(buffer
, "%g");
702 strcpy(buffer
, "%lg");
712 NumberEditor::AttachedToWindow()
714 fTextControl
->SetTarget(this);
715 fEditor
.StartWatching(this);
722 NumberEditor::DetachedFromWindow()
724 fEditor
.StopWatching(this);
731 NumberEditor::MessageReceived(BMessage
*message
)
733 switch (message
->what
) {
734 case kMsgValueChanged
:
737 case kMsgDataEditorUpdate
:
742 BView::MessageReceived(message
);
747 // #pragma mark - BooleanEditor
750 BooleanEditor::BooleanEditor(BRect rect
, DataEditor
&editor
)
751 : TypeEditorView(rect
, B_TRANSLATE("Boolean editor"), B_FOLLOW_NONE
, 0, editor
)
753 SetViewUIColor(B_PANEL_BACKGROUND_COLOR
);
755 BPopUpMenu
*menu
= new BPopUpMenu("bool");
757 menu
->AddItem(fFalseMenuItem
= new BMenuItem("false",
758 new BMessage(kMsgValueChanged
)));
759 menu
->AddItem(fTrueMenuItem
= new BMenuItem("true",
760 message
= new BMessage(kMsgValueChanged
)));
761 message
->AddInt8("value", 1);
763 BMenuField
*menuField
= new BMenuField(rect
.InsetByCopy(5, 5),
764 B_EMPTY_STRING
, B_TRANSLATE("Boolean value:"), menu
, B_FOLLOW_LEFT_RIGHT
);
765 menuField
->SetDivider(StringWidth(menuField
->Label()) + 8);
766 menuField
->ResizeToPreferred();
767 ResizeTo(menuField
->Bounds().Width() + 10,
768 menuField
->Bounds().Height() + 10);
777 BooleanEditor::TypeMatches()
779 // we accept everything: we just look at the first byte, anyway
785 BooleanEditor::_UpdateMenuField()
787 if (fEditor
.FileSize() != 1)
790 if (fEditor
.Lock()) {
792 if (fEditor
.GetViewBuffer((const uint8
**)&buffer
) == B_OK
)
793 (buffer
[0] != 0 ? fTrueMenuItem
: fFalseMenuItem
)->SetMarked(true);
801 BooleanEditor::CommitChanges()
803 // we're commiting the changes as they happen
808 BooleanEditor::AttachedToWindow()
810 fTrueMenuItem
->SetTarget(this);
811 fFalseMenuItem
->SetTarget(this);
813 fEditor
.StartWatching(this);
818 BooleanEditor::DetachedFromWindow()
820 fEditor
.StopWatching(this);
825 BooleanEditor::MessageReceived(BMessage
*message
)
827 switch (message
->what
) {
828 case kMsgValueChanged
:
830 uint8 boolean
= message
->FindInt8("value");
831 fEditor
.Replace(0, (const uint8
*)&boolean
, 1);
834 case kMsgDataEditorUpdate
:
839 BView::MessageReceived(message
);
844 // #pragma mark - ImageView
847 ImageView::ImageView(DataEditor
&editor
)
848 : TypeEditorView(B_TRANSLATE_COMMENT("Image view", "Image means here a "
849 "picture file, not a disk image."),
850 B_WILL_DRAW
| B_FULL_UPDATE_ON_RESIZE
, editor
),
854 if (editor
.Type() == B_MINI_ICON_TYPE
855 || editor
.Type() == B_LARGE_ICON_TYPE
856 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
857 || editor
.Type() == B_VECTOR_ICON_TYPE
860 SetName(B_TRANSLATE("Icon view"));
862 fDescriptionView
= new BStringView("",
863 B_TRANSLATE_COMMENT("Could not read image", "Image means "
864 "here a picture file, not a disk image."));
865 fDescriptionView
->SetAlignment(B_ALIGN_CENTER
);
867 if (editor
.Type() == B_VECTOR_ICON_TYPE
) {
869 fScaleSlider
= new BSlider("", NULL
,
870 new BMessage(kMsgScaleChanged
), 2, 32, B_HORIZONTAL
);
871 fScaleSlider
->SetModificationMessage(new BMessage(kMsgScaleChanged
));
872 fScaleSlider
->ResizeToPreferred();
873 fScaleSlider
->SetValue(8);
874 fScaleSlider
->SetHashMarks(B_HASH_MARKS_BOTH
);
875 fScaleSlider
->SetHashMarkCount(15);
877 BLayoutBuilder::Group
<>(this, B_HORIZONTAL
)
878 .SetInsets(B_USE_WINDOW_SPACING
, 256, B_USE_WINDOW_SPACING
,
879 B_H_SCROLL_BAR_HEIGHT
) // Leave space for the icon
881 .AddGroup(B_VERTICAL
)
882 .Add(fDescriptionView
)
887 BLayoutBuilder::Group
<>(this, B_HORIZONTAL
)
888 .SetInsets(B_USE_WINDOW_SPACING
, 256, B_USE_WINDOW_SPACING
,
889 B_USE_WINDOW_SPACING
) // Leave space for the icon
891 .Add(fDescriptionView
)
897 ImageView::~ImageView()
904 ImageView::AttachedToWindow()
906 if (Parent() != NULL
)
907 SetViewColor(Parent()->ViewColor());
909 SetViewUIColor(B_PANEL_BACKGROUND_COLOR
);
911 fEditor
.StartWatching(this);
912 if (fScaleSlider
!= NULL
)
913 fScaleSlider
->SetTarget(this);
920 ImageView::DetachedFromWindow()
922 fEditor
.StopWatching(this);
927 ImageView::MessageReceived(BMessage
*message
)
929 switch (message
->what
) {
930 case kMsgDataEditorUpdate
:
934 case kMsgScaleChanged
:
939 BView::MessageReceived(message
);
945 ImageView::Draw(BRect updateRect
)
947 if (fBitmap
!= NULL
) {
948 SetDrawingMode(B_OP_ALPHA
);
949 DrawBitmap(fBitmap
, BPoint((Bounds().Width() - fBitmap
->Bounds().Width()) / 2, 0));
950 SetDrawingMode(B_OP_COPY
);
956 ImageView::_UpdateImage()
958 // ToDo: add scroller if necessary?!
960 BAutolock
locker(fEditor
);
962 // we need all the data...
964 size_t viewSize
= fEditor
.ViewSize();
965 // that may need some more memory...
966 if ((off_t
)viewSize
< fEditor
.FileSize())
967 fEditor
.SetViewSize(fEditor
.FileSize());
970 if (fEditor
.GetViewBuffer((const uint8
**)&data
) != B_OK
) {
971 fEditor
.SetViewSize(viewSize
);
975 if (fBitmap
!= NULL
&& (fEditor
.Type() == B_MINI_ICON_TYPE
976 || fEditor
.Type() == B_LARGE_ICON_TYPE
)) {
977 // optimize icon update...
978 fBitmap
->SetBits(data
, fEditor
.FileSize(), 0, B_CMAP8
);
979 fEditor
.SetViewSize(viewSize
);
982 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
983 if (fBitmap
!= NULL
&& fEditor
.Type() == B_VECTOR_ICON_TYPE
984 && fScaleSlider
->Value() * 8 - 1 == fBitmap
->Bounds().Width()) {
985 if (BIconUtils::GetVectorIcon((const uint8
*)data
,
986 (size_t)fEditor
.FileSize(), fBitmap
) == B_OK
) {
987 fEditor
.SetViewSize(viewSize
);
996 switch (fEditor
.Type()) {
997 case B_MINI_ICON_TYPE
:
998 fBitmap
= new BBitmap(BRect(0, 0, 15, 15), B_CMAP8
);
999 if (fBitmap
->InitCheck() == B_OK
)
1000 fBitmap
->SetBits(data
, fEditor
.FileSize(), 0, B_CMAP8
);
1002 case B_LARGE_ICON_TYPE
:
1003 fBitmap
= new BBitmap(BRect(0, 0, 31, 31), B_CMAP8
);
1004 if (fBitmap
->InitCheck() == B_OK
)
1005 fBitmap
->SetBits(data
, fEditor
.FileSize(), 0, B_CMAP8
);
1007 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
1008 case B_VECTOR_ICON_TYPE
:
1009 fBitmap
= new BBitmap(BRect(0, 0, fScaleSlider
->Value() * 8 - 1,
1010 fScaleSlider
->Value() * 8 - 1), B_RGB32
);
1011 if (fBitmap
->InitCheck() != B_OK
1012 || BIconUtils::GetVectorIcon((const uint8
*)data
,
1013 (size_t)fEditor
.FileSize(), fBitmap
) != B_OK
) {
1021 BMemoryIO
stream(data
, fEditor
.FileSize());
1022 fBitmap
= BTranslationUtils::GetBitmap(&stream
);
1025 case B_MESSAGE_TYPE
:
1028 // ToDo: this could be problematic if the data is not large
1029 // enough to contain the message...
1030 if (message
.Unflatten(data
) == B_OK
)
1031 fBitmap
= new BBitmap(&message
);
1036 // Update the bitmap description. If no image can be displayed,
1037 // we will show our "unsupported" message
1039 if (fBitmap
!= NULL
&& fBitmap
->InitCheck() != B_OK
) {
1044 if (fBitmap
!= NULL
) {
1046 const char *type
= B_TRANSLATE("Unknown type");
1047 switch (fEditor
.Type()) {
1048 case B_MINI_ICON_TYPE
:
1049 case B_LARGE_ICON_TYPE
:
1050 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
1051 case B_VECTOR_ICON_TYPE
:
1053 type
= B_TRANSLATE("Icon");
1056 type
= B_TRANSLATE("PNG format");
1058 case B_MESSAGE_TYPE
:
1059 type
= B_TRANSLATE("Flattened bitmap");
1064 const char *colorSpace
;
1065 switch (fBitmap
->ColorSpace()) {
1068 colorSpace
= B_TRANSLATE("Grayscale");
1071 colorSpace
= B_TRANSLATE("8 bit palette");
1077 colorSpace
= B_TRANSLATE("32 bit");
1083 colorSpace
= B_TRANSLATE("15 bit");
1087 colorSpace
= B_TRANSLATE("16 bit");
1090 colorSpace
= B_TRANSLATE("Unknown format");
1093 snprintf(buffer
, sizeof(buffer
), "%s, %g x %g, %s", type
,
1094 fBitmap
->Bounds().Width() + 1, fBitmap
->Bounds().Height() + 1,
1096 fDescriptionView
->SetText(buffer
);
1098 fDescriptionView
->SetText(B_TRANSLATE_COMMENT("Could not read image",
1099 "Image means here a picture file, not a disk image."));
1101 if (fBitmap
!= NULL
) {
1102 if (fScaleSlider
!= NULL
) {
1103 if (fScaleSlider
->IsHidden())
1104 fScaleSlider
->Show();
1106 } else if (fScaleSlider
!= NULL
&& !fScaleSlider
->IsHidden())
1107 fScaleSlider
->Hide();
1111 // restore old view size
1112 fEditor
.SetViewSize(viewSize
);
1116 // #pragma mark - MessageView
1119 MessageView::MessageView(BRect rect
, DataEditor
&editor
)
1120 : TypeEditorView(rect
, B_TRANSLATE("Message View"), B_FOLLOW_ALL
, 0, editor
)
1122 SetViewUIColor(B_PANEL_BACKGROUND_COLOR
);
1124 rect
= Bounds().InsetByCopy(10, 10);
1125 rect
.right
-= B_V_SCROLL_BAR_WIDTH
;
1126 rect
.bottom
-= B_H_SCROLL_BAR_HEIGHT
;
1128 fTextView
= new BTextView(rect
, B_EMPTY_STRING
,
1129 rect
.OffsetToCopy(B_ORIGIN
).InsetByCopy(5, 5),
1130 B_FOLLOW_ALL
, B_WILL_DRAW
);
1131 fTextView
->SetViewUIColor(ViewUIColor());
1132 fTextView
->SetLowUIColor(ViewUIColor());
1134 BScrollView
*scrollView
= new BScrollView("scroller", fTextView
,
1135 B_FOLLOW_ALL
, B_WILL_DRAW
, true, true);
1136 AddChild(scrollView
);
1140 MessageView::~MessageView()
1146 MessageView::_TypeToString(type_code type
)
1148 // TODO: move this to a utility function (it's a copy from something
1149 // similar in ProbeView.cpp)
1151 for (int32 i
= 0; i
< 4; i
++) {
1152 text
[i
] = type
>> (24 - 8 * i
);
1153 if (text
[i
] < ' ' || text
[i
] == 0x7f) {
1154 snprintf(text
, sizeof(text
), "0x%04" B_PRIx32
, type
);
1160 return BString(text
);
1165 MessageView::SetTo(BMessage
& message
)
1167 // TODO: when we have a real column list/tree view, redo this using
1168 // it with nice editors as well.
1170 fTextView
->SetText("");
1173 snprintf(text
, sizeof(text
), B_TRANSLATE_COMMENT("what: '%.4s'\n\n",
1174 "'What' is a message specifier that defines the type of the message."),
1175 (char*)&message
.what
);
1176 fTextView
->Insert(text
);
1180 #ifdef HAIKU_TARGET_PLATFORM_DANO
1184 for (int32 i
= 0; message
.GetInfo(B_ANY_TYPE
, i
, &name
, &type
, &count
)
1186 snprintf(text
, sizeof(text
), "%s\t", _TypeToString(type
).String());
1187 fTextView
->Insert(text
);
1189 text_run_array array
;
1191 array
.runs
[0].offset
= 0;
1192 array
.runs
[0].font
.SetFace(B_BOLD_FACE
);
1193 array
.runs
[0].color
= (rgb_color
){0, 0, 0, 255};
1195 fTextView
->Insert(name
, &array
);
1197 array
.runs
[0].font
= be_plain_font
;
1198 fTextView
->Insert("\n", &array
);
1200 for (int32 j
= 0; j
< count
; j
++) {
1203 if (message
.FindData(name
, type
, j
, (const void**)&data
, &size
)
1211 snprintf(text
, sizeof(text
), "%" B_PRId64
, *(int64
*)data
);
1214 snprintf(text
, sizeof(text
), "%" B_PRIu64
, *(uint64
*)data
);
1217 snprintf(text
, sizeof(text
), "%" B_PRId32
, *(int32
*)data
);
1220 snprintf(text
, sizeof(text
), "%" B_PRIu32
, *(uint32
*)data
);
1224 strcpy(text
, "true");
1226 strcpy(text
, "false");
1229 case B_MIME_STRING_TYPE
:
1231 snprintf(text
, sizeof(text
), "%s", data
);
1237 fTextView
->Insert("\t\t");
1240 snprintf(index
, sizeof(index
), "%" B_PRId32
".\t", j
);
1241 fTextView
->Insert(index
);
1243 fTextView
->Insert(text
);
1244 fTextView
->Insert("\n");
1252 MessageView::_UpdateMessage()
1254 BAutolock
locker(fEditor
);
1256 size_t viewSize
= fEditor
.ViewSize();
1257 // that may need some more memory...
1258 if ((off_t
)viewSize
< fEditor
.FileSize())
1259 fEditor
.SetViewSize(fEditor
.FileSize());
1262 if (fEditor
.GetViewBuffer((const uint8
**)&buffer
) == B_OK
) {
1264 message
.Unflatten(buffer
);
1268 // restore old view size
1269 fEditor
.SetViewSize(viewSize
);
1274 MessageView::AttachedToWindow()
1276 fEditor
.StartWatching(this);
1283 MessageView::DetachedFromWindow()
1285 fEditor
.StopWatching(this);
1290 MessageView::MessageReceived(BMessage
* message
)
1292 BView::MessageReceived(message
);
1300 GetTypeEditorFor(BRect rect
, DataEditor
& editor
)
1302 switch (editor
.Type()) {
1304 return new StringEditor(editor
);
1305 case B_MIME_STRING_TYPE
:
1306 return new MimeTypeEditor(rect
, editor
);
1308 return new BooleanEditor(rect
, editor
);
1319 case B_SSIZE_T_TYPE
:
1322 case B_POINTER_TYPE
:
1323 return new NumberEditor(rect
, editor
);
1324 case B_MESSAGE_TYPE
:
1325 // TODO: check for archived bitmaps!!!
1326 return new MessageView(rect
, editor
);
1327 case B_MINI_ICON_TYPE
:
1328 case B_LARGE_ICON_TYPE
:
1330 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
1331 case B_VECTOR_ICON_TYPE
:
1333 return new ImageView(editor
);
1341 GetNthTypeEditor(int32 index
, const char** _name
)
1343 static const char* kEditors
[] = {
1344 B_TRANSLATE_COMMENT("Text", "This is the type of editor"),
1345 B_TRANSLATE_COMMENT("Number", "This is the type of editor"),
1346 B_TRANSLATE_COMMENT("Boolean", "This is the type of editor"),
1347 B_TRANSLATE_COMMENT("Message", "This is the type of view"),
1348 B_TRANSLATE_COMMENT("Image", "This is the type of view")
1351 if (index
< 0 || index
>= int32(sizeof(kEditors
) / sizeof(kEditors
[0])))
1354 *_name
= kEditors
[index
];
1360 GetTypeEditorAt(int32 index
, BRect rect
, DataEditor
& editor
)
1362 TypeEditorView
* view
= NULL
;
1366 view
= new StringEditor(editor
);
1369 view
= new NumberEditor(rect
, editor
);
1372 view
= new BooleanEditor(rect
, editor
);
1375 view
= new MessageView(rect
, editor
);
1378 view
= new ImageView(editor
);
1388 if (!view
->TypeMatches()) {