#include <ScrollView.h>
#include <TextView.h>
#include <String.h>
#include <limits.h>
#include "ErrorLogWindow.h"
rgb_color white = {255,255,255,255};
rgb_color notwhite = {255,255,200,255};
class Error : public BView {
public:
Error(BRect rect,alert_type type,const char *tag,const char *message,bool timestamp,rgb_color bkg);
void GetPreferredSize(float *width, float *height);
void Draw(BRect updateRect);
void FrameResized(float w, float h);
private:
alert_type type;
};
class ErrorPanel : public BView {
public:
ErrorPanel(BRect rect) : BView(rect,"ErrorScrollPanel",B_FOLLOW_ALL_SIDES,B_DRAW_ON_CHILDREN | B_FRAME_EVENTS), alerts_displayed(0), add_next_at(0) {}
void GetPreferredSize(float *width, float *height) {
*width = Bounds().Width();
*height = add_next_at;
}
void TargetedByScrollView(BScrollView *scroll_view) { scroll = scroll_view; /*scroll->ScrollBar(B_VERTICAL)->SetRange(0,add_next_at);*/ }
void FrameResized(float w, float /*h*/) {
add_next_at = 0;
for (int32 i = 0; i < CountChildren(); i++) {
ChildAt(i)->MoveTo(BPoint(0,add_next_at));
ChildAt(i)->ResizeTo(w, ChildAt(i)->Frame().Height());
ChildAt(i)->ResizeToPreferred();
add_next_at += ChildAt(i)->Bounds().Height();
}
}
int32 alerts_displayed;
float add_next_at;
BScrollView *scroll;
};
// #pragma mark -
ErrorLogWindow::ErrorLogWindow(BRect rect, const char *name, window_type type)
:
BWindow(rect, name, type, B_NO_WORKSPACE_ACTIVATION | B_NOT_MINIMIZABLE
| B_ASYNCHRONOUS_CONTROLS),
fIsRunning(false)
{
rect = Bounds();
rect.right -= B_V_SCROLL_BAR_WIDTH;
view = new ErrorPanel(rect);
AddChild(new BScrollView("ErrorScroller", view, B_FOLLOW_ALL_SIDES, 0, false, true));
Show();
Hide();
}
void
ErrorLogWindow::AddError(alert_type type, const char *message, const char *tag, bool timestamp)
{
ErrorPanel *panel = (ErrorPanel *)view;
// first call?
if (!fIsRunning) {
fIsRunning = true;
Show();
}
Lock();
Error *newError = new Error(BRect(0, panel->add_next_at, panel->Bounds().right,
panel->add_next_at + 1), type, tag, message, timestamp,
(panel->alerts_displayed++ % 2 == 0) ? white : notwhite);
newError->ResizeToPreferred();
panel->add_next_at += newError->Bounds().Height();
panel->AddChild(newError);
panel->ResizeToPreferred();
if (panel->add_next_at > Frame().Height()) {
BScrollBar *bar = panel->scroll->ScrollBar(B_VERTICAL);
bar->SetRange(0, panel->add_next_at - Frame().Height());
bar->SetSteps(1, Frame().Height());
bar->SetProportion(Frame().Height() / panel->add_next_at);
} else
panel->scroll->ScrollBar(B_VERTICAL)->SetRange(0,0);
if (IsHidden())
Show();
Unlock();
}
bool
ErrorLogWindow::QuitRequested()
{
Hide();
while (view->CountChildren() != 0) {
BView* child = view->ChildAt(0);
view->RemoveChild(child);
delete child;
}
ErrorPanel *panel = (ErrorPanel *)(view);
panel->add_next_at = 0;
panel->alerts_displayed = 0;
view->ResizeToPreferred();
return false;
}
void
ErrorLogWindow::FrameResized(float newWidth, float newHeight)
{
ErrorPanel *panel = (ErrorPanel *)view;
panel->Invalidate();
if (panel->add_next_at > newHeight) {
BScrollBar *bar = panel->scroll->ScrollBar(B_VERTICAL);
bar->SetRange(0, panel->add_next_at - Frame().Height());
bar->SetSteps(1, Frame().Height());
bar->SetProportion(Frame().Height() / panel->add_next_at);
} else
panel->scroll->ScrollBar(B_VERTICAL)->SetRange(0,0);
}
// #pragma mark -
Error::Error(BRect rect, alert_type atype, const char *tag, const char *message,
bool timestamp,rgb_color bkg)
:
BView(rect,"error",B_FOLLOW_LEFT | B_FOLLOW_RIGHT
| B_FOLLOW_TOP,B_NAVIGABLE | B_WILL_DRAW | B_FRAME_EVENTS),
type(atype)
{
SetViewColor(bkg);
SetLowColor(bkg);
text_run_array array;
array.count = 1;
array.runs[0].offset = 0;
array.runs[0].font = *be_bold_font;
array.runs[0].color = HighColor();
BString msgString(message);
msgString.RemoveAll("\r");
BTextView *view = new BTextView(BRect(20, 0, rect.Width(), rect.Height()),
"error_display", BRect(0,3,rect.Width() - 20 - 3, LONG_MAX),
B_FOLLOW_ALL_SIDES);
view->SetLowColor(bkg);
view->SetViewColor(bkg);
view->SetText(msgString.String());
view->MakeSelectable(true);
view->SetStylable(true);
view->MakeEditable(false);
if (tag != NULL) {
BString tagString(tag);
tagString += " ";
view->Insert(0, tagString.String(), tagString.Length(), &array);
}
if (timestamp) {
array.runs[0].color = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),B_DARKEN_2_TINT);
array.runs[0].font.SetSize(9);
time_t thetime = time(NULL);
BString atime = asctime(localtime(&thetime));
atime.Prepend(" [");
atime.RemoveAll("\n");
atime.Append("]");
view->Insert(view->TextLength(),atime.String(),atime.Length(),&array);
}
float height,width;
width = view->Frame().Width();
height = view->TextHeight(0,view->CountLines()) + 3;
view->ResizeTo(width,height);
AddChild(view);
}
void
Error::GetPreferredSize(float *width, float *height)
{
BTextView *view = static_cast<BTextView *>(FindView("error_display"));
*width = view->Frame().Width() + 20;
*height = view->TextHeight(0, INT32_MAX) + 3;
}
void
Error::Draw(BRect updateRect)
{
FillRect(updateRect, B_SOLID_LOW);
}
void
Error::FrameResized(float w, float h)
{
BTextView *view = static_cast<BTextView *>(FindView("error_display"));
view->ResizeTo(w - 20, h);
view->SetTextRect(BRect(0, 3, w - 20, h));
}
↑ V763 Parameter 'rect' is always rewritten in function body before being used.
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: scroll.