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