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