blob: 1c62c75c91270715effd03333321324e362c96c0 [file] [log] [blame]
/*
* Copyright (C) 2023 Adrien Destugues <pulkomandy@pulkomandy.tk>
*
* Distributed under terms of the MIT license.
*/
#include <Application.h>
#include <private/interface/ColumnListView.h>
#include <private/interface/ColumnTypes.h>
#include <GroupLayout.h>
#include <LayoutBuilder.h>
#include <MenuBar.h>
#include <Window.h>
#include <ctype.h>
#include "../BeDC.h"
class BColorStringField: public BStringField
{
public:
BColorStringField(const char* string, rgb_color color)
: BStringField(string)
, fColor(color)
{
}
rgb_color fColor;
};
class BColorStringColumn: public BStringColumn
{
public:
BColorStringColumn(const char* title, float w, float minw, float maxw)
: BStringColumn(title, w, minw, maxw, false)
{
}
void DrawField(BField* field, BRect rect, BView* parent) override
{
BColorStringField* csField = dynamic_cast<BColorStringField*>(field);
if (csField) {
parent->SetHighColor(csField->fColor);
}
BStringColumn::DrawField(field, rect, parent);
}
};
static char sanechar(int32 input) {
input = input & 0xff;
if (isprint(input))
return (char)input;
else
return '.';
}
class LoggerWindow: public BWindow
{
public:
LoggerWindow()
: BWindow(BRect(100, 100, 900, 700), "Dev console", B_DOCUMENT_WINDOW,
B_QUIT_ON_WINDOW_CLOSE | B_AUTO_UPDATE_SIZE_LIMITS)
{
BGroupLayout* layout = new BGroupLayout(B_VERTICAL);
SetLayout(layout);
layout->SetSpacing(0);
fEventList = new BColumnListView("messages", 0, B_NO_BORDER);
fEventList->AddColumn(new BColorStringColumn("Name", 100, 50, 200), 0);
fEventList->AddColumn(new BColorStringColumn("Text", INT16_MAX, 50, INT16_MAX), 1);
BLayoutBuilder::Group<>(layout)
.SetInsets(0, -1, -1, -1)
.Add(new BMenuBar("main menu"))
.Add(fEventList)
.End();
}
void MessageReceived(BMessage* message) override
{
switch(message->what) {
case BEDC_MESSAGE:
{
// TODO parse all info: bedc_ver, bedc_main_type
// bedc_ver: "1.0" (can be changed in later versions if the message format changes)
// bedc_main_type: BEDC_BMESSAGE or BEDC_PLAIN_MESSAGE
BString name = message->FindString("bedc_name");
BString text = message->FindString("bedc_text");
int8 colorEnum = message->FindInt8("bedc_color");
int8 type = message->FindInt8("bedc_type");
int8 main_type = message->FindInt8("bedc_main_type");
if (type == DC_CLEAR) {
fEventList->Clear();
return;
}
if (main_type == BEDC_BMESSAGE && text.IsEmpty()) {
int32 what = message->FindInt32("bedc_what");
text.SetToFormat("BMessage(what=%#010x, %d, '%c%c%c%c')", what, what,
sanechar(what >> 24), sanechar(what >> 16),
sanechar(what >> 8), sanechar(what >> 0));
}
// TODO: generic BMessage handling (results in one line per item in the message)
// TODO: separators
//
//
BRow* row = new BRow();
if (colorEnum == 0) {
row->SetField(new BStringField(name), 0);
} else {
rgb_color color;
switch(colorEnum) {
case DC_WHITE:
color = make_color(128, 128, 128, 255);
break;
case DC_BLACK:
color = make_color(64, 64, 64, 255);
break;
case DC_BLUE:
color = make_color(0, 0, 128, 255);
break;
case DC_RED:
color = make_color(0, 128, 0, 255);
break;
case DC_YELLOW:
color = make_color(128, 128, 0, 255);
break;
case DC_GREEN:
color = make_color(128, 0, 0, 255);
break;
}
row->SetField(new BColorStringField(name, color), 0);
}
if (type == DC_SUCCESS)
row->SetField(new BColorStringField(text, ui_color(B_SUCCESS_COLOR)), 1);
else if (type == DC_ERROR)
row->SetField(new BColorStringField(text, ui_color(B_FAILURE_COLOR)), 1);
else if (type == DC_MESSAGE)
row->SetField(new BStringField(text), 1);
else if (type == DC_SEPARATOR)
row->SetField(new BStringField("-----"), 1);
else {
message->PrintToStream();
}
fEventList->AddRow(row, -1);
if (main_type == BEDC_BMESSAGE) {
int index = 0;
char* nameFound;
type_code typeFound;
int32 countFound;
while (message->GetInfo(B_ANY_TYPE, index++, &nameFound, &typeFound, &countFound) == B_OK) {
// Don't display all the bedc_ internal stuff
if (BString(nameFound).StartsWith("bedc_"))
continue;
for (int j = 0; j < countFound; j++) {
name.SetToFormat("%s[%d] (%c%c%c%c)", nameFound, j,
(typeFound >> 24) & 0xFF, (typeFound >> 16) & 0xFF,
(typeFound >> 8) & 0xFF, (typeFound >> 0) & 0xFF
);
switch(typeFound) {
#if 0
B_AFFINE_TRANSFORM_TYPE = 'AMTX',
B_ALIGNMENT_TYPE = 'ALGN',
B_ANY_TYPE = 'ANYT',
B_ATOM_TYPE = 'ATOM',
B_ATOMREF_TYPE = 'ATMR',
B_BOOL_TYPE = 'BOOL',
B_CHAR_TYPE = 'CHAR',
B_COLOR_8_BIT_TYPE = 'CLRB',
B_DOUBLE_TYPE = 'DBLE',
B_FLOAT_TYPE = 'FLOT',
B_GRAYSCALE_8_BIT_TYPE = 'GRYB',
B_INT16_TYPE = 'SHRT',
B_INT64_TYPE = 'LLNG',
B_INT8_TYPE = 'BYTE',
B_LARGE_ICON_TYPE = 'ICON',
B_MEDIA_PARAMETER_GROUP_TYPE = 'BMCG',
B_MEDIA_PARAMETER_TYPE = 'BMCT',
B_MEDIA_PARAMETER_WEB_TYPE = 'BMCW',
B_MESSAGE_TYPE = 'MSGG',
B_MESSENGER_TYPE = 'MSNG',
B_MIME_TYPE = 'MIME',
B_MINI_ICON_TYPE = 'MICN',
B_MONOCHROME_1_BIT_TYPE = 'MNOB',
B_OBJECT_TYPE = 'OPTR',
B_OFF_T_TYPE = 'OFFT',
B_PATTERN_TYPE = 'PATN',
B_POINTER_TYPE = 'PNTR',
B_PROPERTY_INFO_TYPE = 'SCTD',
B_RAW_TYPE = 'RAWT',
B_RECT_TYPE = 'RECT',
B_REF_TYPE = 'RREF',
B_NODE_REF_TYPE = 'NREF',
B_RGB_32_BIT_TYPE = 'RGBB',
B_RGB_COLOR_TYPE = 'RGBC',
B_SIZE_TYPE = 'SIZE',
B_SIZE_T_TYPE = 'SIZT',
B_SSIZE_T_TYPE = 'SSZT',
B_STRING_LIST_TYPE = 'STRL',
B_TIME_TYPE = 'TIME',
B_UINT16_TYPE = 'USHT',
B_UINT32_TYPE = 'ULNG',
B_UINT64_TYPE = 'ULLG',
B_UINT8_TYPE = 'UBYT',
B_VECTOR_ICON_TYPE = 'VICN',
B_XATTR_TYPE = 'XATR',
B_NETWORK_ADDRESS_TYPE = 'NWAD',
B_MIME_STRING_TYPE = 'MIMS',
#endif
case B_STRING_TYPE:
text = message->FindString(nameFound, j);
break;
case B_INT32_TYPE:
{
int32 val = message->FindInt32(nameFound, j);
text.SetToFormat("%d (%#010x)", val, val);
break;
}
case B_POINT_TYPE:
{
BPoint val = message->FindPoint(nameFound, j);
text.SetToFormat("X: %f Y: %f", val.x, val.y);
break;
}
default:
text.SetTo("TODO: unhandled message content type");
break;
}
BRow* subRow = new BRow();
subRow->SetField(new BStringField(name), 0);
subRow->SetField(new BStringField(text), 1);
fEventList->AddRow(subRow, row);
}
}
}
break;
}
default:
BWindow::MessageReceived(message);
break;
}
}
private:
BColumnListView* fEventList;
};
class LoggerApp: public BApplication
{
public:
LoggerApp()
: BApplication("application/x-vnd.ml-BeDCApp")
{
LoggerWindow* window = new LoggerWindow();
window->Show();
}
void MessageReceived(BMessage* message) override
{
switch(message->what) {
case BEDC_MESSAGE:
WindowAt(0)->PostMessage(message);
break;
default:
BApplication::MessageReceived(message);
break;
}
}
};
int main(void)
{
LoggerApp app;
app.Run();
}