1#include <ScrollView.h>
2#include <TextView.h>
3#include <String.h>
4#include <limits.h>
5
6#include "ErrorLogWindow.h"
7
8rgb_color white = {255,255,255,255};
9rgb_color notwhite = {255,255,200,255};
10
11class Error : public BView {
12	public:
13		Error(BRect rect,alert_type type,const char *tag,const char *message,bool timestamp,rgb_color bkg);
14
15		void GetPreferredSize(float *width, float *height);
16		void Draw(BRect updateRect);
17		void FrameResized(float w, float h);
18	private:
19		alert_type type;
20};
21
22class ErrorPanel : public BView {
23	public:
24		ErrorPanel(BRect rect) : BView(rect,"ErrorScrollPanel",B_FOLLOW_ALL_SIDES,B_DRAW_ON_CHILDREN | B_FRAME_EVENTS), alerts_displayed(0), add_next_at(0) {}
25
26		void GetPreferredSize(float *width, float *height) {
27			*width = Bounds().Width();
28			*height = add_next_at;
29		}
30
31		void TargetedByScrollView(BScrollView *scroll_view) { scroll = scroll_view; /*scroll->ScrollBar(B_VERTICAL)->SetRange(0,add_next_at);*/ }
32		void FrameResized(float w, float /*h*/) {
33			add_next_at = 0;
34			for (int32 i = 0; i < CountChildren(); i++) {
35				ChildAt(i)->MoveTo(BPoint(0,add_next_at));
36				ChildAt(i)->ResizeTo(w, ChildAt(i)->Frame().Height());
37				ChildAt(i)->ResizeToPreferred();
38				add_next_at += ChildAt(i)->Bounds().Height();
39			}
40		}
41		int32 alerts_displayed;
42		float add_next_at;
43		BScrollView *scroll;
44};
45
46
47//	#pragma mark -
48
49
50ErrorLogWindow::ErrorLogWindow(BRect rect, const char *name, window_type type)
51	:
52	BWindow(rect, name, type, B_NO_WORKSPACE_ACTIVATION | B_NOT_MINIMIZABLE
53		| B_ASYNCHRONOUS_CONTROLS),
54	fIsRunning(false)
55{
56	rect = Bounds();
57	rect.right -= B_V_SCROLL_BAR_WIDTH;
58
59	view = new ErrorPanel(rect);
60	AddChild(new BScrollView("ErrorScroller", view, B_FOLLOW_ALL_SIDES, 0, false, true));
61	Show();
62	Hide();
63}
64
65
66void
67ErrorLogWindow::AddError(alert_type type, const char *message, const char *tag, bool timestamp)
68{
69	ErrorPanel *panel = (ErrorPanel *)view;
70
71	// first call?
72	if (!fIsRunning) {
73		fIsRunning = true;
74		Show();
75	}
76
77	Lock();
78
79	Error *newError = new Error(BRect(0, panel->add_next_at, panel->Bounds().right,
80		panel->add_next_at + 1), type, tag, message, timestamp,
81		(panel->alerts_displayed++ % 2 == 0) ? white : notwhite);
82
83	newError->ResizeToPreferred();
84	panel->add_next_at += newError->Bounds().Height();
85	panel->AddChild(newError);
86	panel->ResizeToPreferred();
87
88	if (panel->add_next_at > Frame().Height()) {
89		BScrollBar *bar = panel->scroll->ScrollBar(B_VERTICAL);
90
91		bar->SetRange(0, panel->add_next_at - Frame().Height());
92		bar->SetSteps(1, Frame().Height());
93		bar->SetProportion(Frame().Height() / panel->add_next_at);
94	} else
95		panel->scroll->ScrollBar(B_VERTICAL)->SetRange(0,0);
96
97	if (IsHidden())
98		Show();
99
100	Unlock();
101}
102
103
104bool
105ErrorLogWindow::QuitRequested()
106{
107	Hide();
108
109	while (view->CountChildren() != 0) {
110		BView* child = view->ChildAt(0);
111		view->RemoveChild(child);
112		delete child;
113	}
114
115	ErrorPanel *panel = (ErrorPanel *)(view);
116	panel->add_next_at = 0;
117	panel->alerts_displayed = 0;
118
119	view->ResizeToPreferred();
120	return false;
121}
122
123
124void
125ErrorLogWindow::FrameResized(float newWidth, float newHeight)
126{
127	ErrorPanel *panel = (ErrorPanel *)view;
128	panel->Invalidate();
129
130	if (panel->add_next_at > newHeight) {
131		BScrollBar *bar = panel->scroll->ScrollBar(B_VERTICAL);
132
133		bar->SetRange(0, panel->add_next_at - Frame().Height());
134		bar->SetSteps(1, Frame().Height());
135		bar->SetProportion(Frame().Height() / panel->add_next_at);
136	} else
137		panel->scroll->ScrollBar(B_VERTICAL)->SetRange(0,0);
138}
139
140
141//	#pragma mark -
142
143
144Error::Error(BRect rect, alert_type atype, const char *tag, const char *message,
145	bool timestamp,rgb_color bkg)
146	:
147	BView(rect,"error",B_FOLLOW_LEFT | B_FOLLOW_RIGHT
148		| B_FOLLOW_TOP,B_NAVIGABLE | B_WILL_DRAW | B_FRAME_EVENTS),
149	type(atype)
150{
151	SetViewColor(bkg);
152	SetLowColor(bkg);
153
154	text_run_array array;
155	array.count = 1;
156	array.runs[0].offset = 0;
157	array.runs[0].font = *be_bold_font;
158	array.runs[0].color = HighColor();
159
160	BString msgString(message);
161	msgString.RemoveAll("\r");
162
163	BTextView *view = new BTextView(BRect(20, 0, rect.Width(), rect.Height()),
164		"error_display", BRect(0,3,rect.Width() - 20 - 3, LONG_MAX),
165		B_FOLLOW_ALL_SIDES);
166	view->SetLowColor(bkg);
167	view->SetViewColor(bkg);
168	view->SetText(msgString.String());
169	view->MakeSelectable(true);
170	view->SetStylable(true);
171	view->MakeEditable(false);
172
173	if (tag != NULL) {
174		BString tagString(tag);
175		tagString += " ";
176		view->Insert(0, tagString.String(), tagString.Length(), &array);
177	}
178
179	if (timestamp) {
180		array.runs[0].color = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),B_DARKEN_2_TINT);
181		array.runs[0].font.SetSize(9);
182		time_t thetime = time(NULL);
183		BString atime = asctime(localtime(&thetime));
184		atime.Prepend(" [");
185		atime.RemoveAll("\n");
186		atime.Append("]");
187		view->Insert(view->TextLength(),atime.String(),atime.Length(),&array);
188	}
189
190	float height,width;
191	width = view->Frame().Width();
192	height = view->TextHeight(0,view->CountLines()) + 3;
193	view->ResizeTo(width,height);
194	AddChild(view);
195}
196
197
198void
199Error::GetPreferredSize(float *width, float *height)
200{
201	BTextView *view = static_cast<BTextView *>(FindView("error_display"));
202
203	*width = view->Frame().Width() + 20;
204	*height = view->TextHeight(0, INT32_MAX) + 3;
205}
206
207
208void
209Error::Draw(BRect updateRect)
210{
211	FillRect(updateRect, B_SOLID_LOW);
212}
213
214
215void
216Error::FrameResized(float w, float h)
217{
218	BTextView *view = static_cast<BTextView *>(FindView("error_display"));
219
220	view->ResizeTo(w - 20, h);
221	view->SetTextRect(BRect(0, 3, w - 20, h));
222}
223