cleaned all trailing white space from source files.
[sdk] / ide / src / panels / OutputView.ec
1 #include <stdarg.h>
2
3 import "ecere"
4 import "CodeEditor"
5
6 enum OutputViewTab { build, debug, find
7 #ifdef GDB_DEBUG_OUTPUT
8 , gdb
9 #endif
10 };
11
12 class OutputView : Window
13 {
14    visible = false;
15    borderStyle = sizable;
16    hasClose = true;
17    mergeMenus = false;
18    text = "Output";
19    menu = Menu { };
20    anchor = Anchor { left = 0, right = 0, bottom = 0 };
21    size.h = 240;
22    background = formColor;
23
24    virtual void OnGotoError(char * line, bool noParsing);
25    virtual void OnCodeLocationParseAndGoTo(char * line);
26
27    FindDialog findDialog { master = this, editBox = buildBox, isModal = true, autoCreate = false, text = "Find" };
28
29    Button buildBtn
30    {
31       this, inactive = true, text = "Build", bevelOver = true, isRadio = true, bitmap = null, checked = true;
32       size = { 99, 20 };
33       anchor = { left = 0, top = 1 };
34       font = { $"Tahoma", 8.25f, bold = true };
35
36       bool NotifyClicked(Button button, int x, int y, Modifiers mods)
37       {
38          SelectTab(build);
39          return true;
40       }
41    };
42
43    Button debugBtn
44    {
45       this, inactive = true, text = "Debug", bevelOver = true, isRadio = true, bitmap = null;
46       size = { 99, 20 };
47       anchor = { left = 100, top = 1 };
48
49       bool NotifyClicked(Button button, int x, int y, Modifiers mods)
50       {
51          SelectTab(debug);
52          return true;
53       }
54    };
55
56    Button findBtn
57    {
58       this, inactive = true, text = "Find", bevelOver = true, isRadio = true, bitmap = null;
59       size = { 99, 20 };
60       anchor = { left = 200, top = 1 };
61
62       bool NotifyClicked(Button button, int x, int y, Modifiers mods)
63       {
64          SelectTab(find);
65          return true;
66       }
67    };
68
69 #ifdef GDB_DEBUG_OUTPUT
70    Button gdbBtn
71    {
72       this, inactive = true, text = "GDB", bevelOver = true, isRadio = true, bitmap = null;
73       size = { 99, 20 };
74       anchor = { left = 300, top = 1 };
75
76       bool NotifyClicked(Button button, int x, int y, Modifiers mods)
77       {
78          SelectTab(gdb);
79          return true;
80       }
81    };
82 #endif
83
84    void SelectTab(OutputViewTab tab)
85    {
86       Button activeBtn = null;
87       if(tab == build)
88          activeBtn = buildBtn, activeBox = buildBox;
89       else if(tab == debug)
90          activeBtn = debugBtn, activeBox = debugBox;
91       else if(tab == find)
92          activeBtn = findBtn, activeBox = findBox;
93 #ifdef GDB_DEBUG_OUTPUT
94       else if(tab == gdb)
95          activeBtn = gdbBtn, activeBox = gdbBox;
96 #endif
97       if(activeBtn && activeBox)
98       {
99          activeBtn.checked = true;
100          activeBtn.font = { $"Tahoma", 8.25f, bold = true };
101          if(buildBtn != activeBtn) buildBtn.font = null;
102          if(debugBtn != activeBtn) debugBtn.font = null;
103          if(findBtn != activeBtn) findBtn.font = null;
104 #ifdef GDB_DEBUG_OUTPUT
105          if(gdbBtn != activeBtn) gdbBtn.font = null;
106 #endif
107
108          activeBox.visible = false;
109          activeBtn.Activate();      // Ensure proper cycling (until tab order?)
110          activeBox.visible = true;
111          activeBox.Activate();
112          findDialog.editBox = activeBox;
113       }
114    }
115
116    EditBox activeBox;
117    activeBox = buildBox;
118
119    LogBox buildBox
120    {
121       parent = this, freeCaret = true, autoEmpty = true, multiLine = true;
122       readOnly = true, hasVertScroll = true, hasHorzScroll = true;
123       anchor = Anchor { left = 0, right = 0, top = 23, bottom = 0 };
124       font = { panelFont.faceName, panelFont.size };
125       background = outputBackground;
126       foreground = outputText;
127       selectionColor = selectionColor, selectionText = selectionText;
128
129       bool NotifyDoubleClick(EditBox editBox, EditLine line, Modifiers mods)
130       {
131          OnGotoError(editBox.line.text, mods.ctrl && mods.shift);
132          return false;
133       }
134
135       bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
136       {
137          if(key.code == enter || key.code == keyPadEnter)
138          {
139             OnGotoError(editBox.line.text, key.ctrl && key.shift);
140             return false;
141          }
142          return true;
143       }
144    };
145
146    LogBox debugBox
147    {
148       parent = this, freeCaret = true, autoEmpty = true, multiLine = true;
149       readOnly = true, hasVertScroll = true, hasHorzScroll = true, visible = false;
150       anchor = Anchor { left = 0, right = 0, top = 23, bottom = 0 };
151       font = { panelFont.faceName, panelFont.size };
152       background = outputBackground;
153       foreground = outputText;
154       selectionColor = selectionColor, selectionText = selectionText;
155
156       bool NotifyDoubleClick(EditBox editBox, EditLine line, Modifiers mods)
157       {
158          OnCodeLocationParseAndGoTo(editBox.line.text);
159          return false;
160       }
161
162       bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
163       {
164          if((SmartKey)key == enter)
165          {
166             OnCodeLocationParseAndGoTo(editBox.line.text);
167             return false;
168          }
169          return true;
170       }
171    };
172
173    LogBox findBox
174    {
175       parent = this, freeCaret = true, autoEmpty = true, multiLine = true;
176       readOnly = true, hasVertScroll = true, hasHorzScroll = true, visible = false;
177       anchor = Anchor { left = 0, right = 0, top = 23, bottom = 0 };
178       font = { panelFont.faceName, panelFont.size };
179       background = outputBackground;
180       foreground = outputText;
181       selectionColor = selectionColor, selectionText = selectionText;
182
183       bool NotifyDoubleClick(EditBox editBox, EditLine line, Modifiers mods)
184       {
185          OnCodeLocationParseAndGoTo(editBox.line.text);
186          return false;
187       }
188
189       bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
190       {
191          if((SmartKey)key == enter)
192          {
193             OnCodeLocationParseAndGoTo(editBox.line.text);
194             return false;
195          }
196          return true;
197       }
198    };
199
200 #ifdef GDB_DEBUG_OUTPUT
201    LogBox gdbBox
202    {
203       parent = this, freeCaret = true, autoEmpty = true, multiLine = true;
204       readOnly = true, hasVertScroll = true, hasHorzScroll = true, visible = false;
205       anchor = Anchor { left = 0, right = 0, top = 23, bottom = 0 };
206       font = { panelFont.faceName, panelFont.size };
207       background = outputBackground;
208       foreground = outputText;
209       selectionColor = selectionColor, selectionText = selectionText;
210    };
211 #endif
212
213    Menu editMenu { menu, $"Edit", e };
214
215    MenuItem item;
216    MenuItem copyItem
217    {
218       editMenu, $"Copy", c, ctrlC;
219       bool NotifySelect(MenuItem selection, Modifiers mods)
220       {
221          activeBox.Copy();
222          return true;
223       }
224    };
225    MenuDivider { editMenu };
226    MenuItem { editMenu, $"Find Previous", e, Key { f3, shift = true }, NotifySelect = MenuEditFind, id = 0 };
227    MenuItem { editMenu, $"Find Next", n, f3, NotifySelect = MenuEditFind, id = 1 };
228    MenuItem { editMenu, $"Find", f, ctrlF, NotifySelect = MenuEditFind, id = 2 };
229
230    bool MenuEditFind(MenuItem selection, Modifiers mods)
231    {
232       int64 id = selection.id;
233       char * searchString = findDialog.searchString;
234       if(id != 2 && searchString[0])
235       {
236          activeBox.Find(searchString, findDialog.wholeWord, findDialog.matchCase, (bool)id);
237          return true;
238       }
239       findDialog.Create();
240       return true;
241    }
242
243    void Show()
244    {
245       visible = true;
246       ide.RepositionWindows(false);
247       Activate();
248    }
249    void ShowClearSelectTab(OutputViewTab tab)
250    {
251       Show();
252       if(tab == build)
253          buildBox.Clear();
254       else if(tab == debug)
255          debugBox.Clear();
256       else if(tab == find)
257       {
258          findBox.Clear();
259       }
260 #ifdef GDB_DEBUG_OUTPUT
261       else if(tab == gdb)
262          gdbBox.Clear();
263 #endif
264       SelectTab(tab);
265    }
266
267    bool OnKeyDown(Key key, unichar ch)
268    {
269       switch(key)
270       {
271          case shiftTab:
272          {
273             OutputViewTab switchTo;
274             if(activeBox == buildBox)
275 #ifdef GDB_DEBUG_OUTPUT
276                switchTo = gdb;
277 #else
278                switchTo = find;
279 #endif
280             else if(activeBox == debugBox)
281                switchTo = build;
282             else if(activeBox == findBox)
283                switchTo = debug;
284 #ifdef GDB_DEBUG_OUTPUT
285             else if(activeBox == gdbBox)
286                switchTo = build;
287 #endif
288             SelectTab(switchTo);
289             break;
290          }
291          case tab:
292          {
293             OutputViewTab switchTo = debug;
294             if(activeBox == buildBox)
295                switchTo = debug;
296             else if(activeBox == debugBox)
297                switchTo = find;
298             else if(activeBox == findBox)
299 #ifdef GDB_DEBUG_OUTPUT
300                switchTo = gdb;
301             else if(activeBox == gdbBox)
302 #endif
303                switchTo = build;
304             SelectTab(switchTo);
305             break;
306          }
307       }
308       return true;
309    }
310 }
311
312 class LogBox : EditBox
313 {
314    bool moved, logging, tell;
315
316    void Logf(char * format, ...)
317    {
318       char string[MAX_F_STRING*10];
319       va_list args;
320       va_start(args, format);
321       vsnprintf(string, sizeof(string), format, args);
322       string[sizeof(string)-1] = 0;
323       va_end(args);
324
325       LogRaw(string);
326    }
327
328    void LogSprintf(char * entry)
329    {
330       char string[MAX_F_STRING];
331       sprintf(string, entry);
332       LogRaw(string);
333    }
334
335    void LogRaw(char * entry)
336    {
337       // Cut the line longer than 1024 because Logf prints to a buffer (and we don't want to output crazy long lines either)
338       //if(len > 1023) line[1023] = '\0';
339       /* Fixed, but disabled this ... Not sure if there's any reason to keep it? The EditBox should be fine with long lines
340          and it's easier to copy commands and go to errors */
341       /*int len = strlen(entry);
342       if(len > 1023)
343       {
344          char * newStart, * start = entry;
345
346          while(len > 1023)
347          {
348             char backup[3];
349             newStart = start + 1020;
350             strncpy(backup, newStart, 3);
351             strncpy(newStart, "\n ", 3);
352             Log(start);
353             strncpy(newStart, backup, 3);
354             start = newStart;
355             len = strlen(start);
356          }
357          Log(start);
358       }
359       else*/
360          Log(entry);
361    }
362
363    void Log(char * string)
364    {
365       int x1, y1, x2, y2;
366       Point scrl;
367       EditLine line1;
368       EditLine line2;
369       logging = true;
370       if(moved)
371       {
372          GetSelPos(&line1, &y1, &x1, &line2, &y2, &x2, false);
373          scrl = scroll;
374       }
375       End();
376       if(tell)
377       {
378          ClearLine();
379          tell = false;
380       }
381       PutS(string);
382       Update(null);
383       if(moved)
384       {
385          scroll = scrl;
386          SetSelPos(line1, y1, x1, line2, y2, x2);
387       }
388       logging = false;
389    }
390
391    void Tellf(char * format, ...)
392    {
393       char string[MAX_F_STRING*10];
394       va_list args;
395       va_start(args, format);
396       vsnprintf(string, sizeof(string), format, args);
397       string[sizeof(string)-1] = 0;
398       va_end(args);
399
400       Tell(string);
401    }
402
403    void Tell(char * string)
404    {
405       Log(string);
406       if(!moved)
407       {
408          Point caretPos;
409          GetCaretPosition(caretPos);
410          SetCaret(0, caretPos.y, GetCaretSize());
411       }
412       tell = true;
413    }
414
415    void Clear()
416    {
417       EditBox::Clear();
418       moved = false;
419    }
420
421    void NotifyCaretMove(EditBox editBox, int line, int charPos)
422    {
423       LogBox logBox = (LogBox)editBox;
424       if(!logBox.logging)
425       {
426          int y1, y2;
427          logBox.GetSelPos(null, &y1, null, null, &y2, null, false);
428          logBox.moved = (y1 == logBox.numLines - 1 && y2 == y1) ? false : true;
429       }
430    }
431 }