ide/Debugger: (#798) Fixed hiding Debugger views when GDB is lost
[sdk] / ide / src / panels / WatchesView.ec
1 import "ide"
2
3 class WatchesView : Window
4 {
5    visible = false;
6    text = $"Watches";
7    borderStyle = sizable;
8    background = { 224, 224, 224 };
9    hasClose = true;
10    anchor = Anchor { left = 0, right = 0, bottom = 0 };
11    size.h = 240;
12
13    bool moved, logging;
14
15    ListBox listBox
16    {
17       parent = this, hasHeader = true, hasVertScroll = true, alwaysEdit = true, collapseControl = true, resizable = true;
18       anchor = Anchor { left = 0, right = 0, top = 0, bottom = 0 };
19       background = viewsBackground;
20       foreground = viewsText;
21       selectionColor = selectionColor, selectionText = selectionText;
22
23       bool NotifyChanged(ListBox listBox, DataRow row)
24       {
25          char * expression = row.GetData(expressionField);
26          
27          if(expression && expression[0])
28          {
29             TrimLSpaces(expression, expression);
30             TrimRSpaces(expression, expression);
31          }
32          
33          if(expression && expression[0])
34          {
35             row.SetData(valueField, null);
36             if(row == listBox.lastRow)
37             {
38                DataRow newRow = listBox.AddRow();
39                newRow.SetData(expressionField, null);
40                newRow.SetData(valueField, null);
41                listBox.currentRow = newRow;
42             }
43             ide.debugger.ChangeWatch(row, expression);
44          }
45          else
46          {
47             ide.debugger.ChangeWatch(row, expression);
48             if(row != listBox.lastRow)
49             {
50                //Type type = (Type)row.GetData(typeField);
51                //if(type) FreeType(type);
52                listBox.DeleteRow(row);
53             }
54             else
55                row.SetData(valueField, null);
56          }
57          return true;
58       }
59
60       bool NotifyKeyHit(ListBox listBox, DataRow row, Key key, unichar ch)
61       {
62          if((SmartKey)key == del)
63          {
64             listBox.StopEditing(true);
65             if(row && row != listBox.lastRow)
66             {
67                //Type type = (Type)row.GetData(typeField);
68                ide.debugger.ChangeWatch(row, null);
69                //if(type) FreeType(type);
70                listBox.DeleteRow(null);
71             }
72          }
73          return true;
74       }
75    };
76    DataField expressionField { "char *", true, width = 130, header = $"Expression" };
77    DataField typeField { "Type", false, width = 180, header = $"Type" };
78    //DataField addressField { "char *", true, width = 80, header = $"Symbol Address" };
79    DataField valueField { class(WatchMultiLineString), true, width = 330, header = $"Value", freeData = false };
80
81    WatchesView()
82    {
83       listBox.AddField(expressionField);
84       listBox.AddField(typeField);
85       listBox.AddField(valueField);
86    }
87
88    bool OnKeyDown(Key key, unichar ch)
89    {
90       switch(key)
91       {
92          case escape: ide.ShowCodeEditor(); break;
93       }
94       return true;
95    }
96
97    bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
98    {
99       if(active)
100       {
101          //listBox.SelectRow(listBox.firstRow);
102          ide.RepositionWindows(false);
103       }
104       return true;
105    }
106
107    bool OnClose(bool parentClosing)
108    {
109       visible = false;
110       if(!parentClosing)
111          ide.RepositionWindows(false);
112       return parentClosing;
113    }
114
115    void Show()
116    {
117       visible = true;
118       Activate();
119    }
120
121    void LoadFromWorkspace()
122    {
123       for(wh : ide.workspace.watches)
124          AddWatch(wh);
125    }
126
127    void AddWatch(Watch wh)
128    {
129       DataRow row = listBox.AddRowAfter(listBox.lastRow.previous);
130       row.tag = (int64)wh;
131       wh.row = row;
132       UpdateWatch(wh);
133    }
134
135    void UpdateWatch(Watch wh)
136    {
137       if(wh)
138       {
139          DataRow row = wh.row;
140          if(row && row.tag)
141          {
142             row.SetData(expressionField, wh.expression);
143             row.SetData(typeField, wh.type);
144             //row.SetData(addressField, wh.address);
145             row.SetData(valueField, wh.value);
146          }
147       }
148    }
149
150    void Clear()
151    {
152       DataRow row;
153       listBox.Clear();
154       row = listBox.AddRow();
155       row.SetData(expressionField, null);
156       row.SetData(typeField, null);
157       row.SetData(valueField, null);
158       if(ide.workspace)
159       {
160          for(w : ide.workspace.watches)
161             w.row = null;
162       }
163    }
164 }
165
166 class WatchMultiLineString : String
167 {
168    Window OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)
169    {
170       if(this && strchr(this, '\n'))
171       {
172          // Don't show the editbox right away so that the text is highlighted by default
173          EditBox editBox
174          {
175             parent = dataBox, master = obsolete, visible = false,
176             borderStyle = contour,
177             //interim = true,
178             hasHorzScroll = true, hasVertScroll = true,
179             modifyVirtualArea = false,
180             anchor = { 0, 0, 0, 0 };
181             //position = { x + dataBox.absPosition.x, y + dataBox.absPosition.y };
182             //size = { w, h * 4 }; 
183             multiLine = true;
184
185             bool OnKeyDown(Key key, unichar ch)
186             {
187                /*if(key == escape)
188                {
189                   ((ListBox)master.master).currentField = ((ListBox)master.master).firstField;
190                   return false;
191                }*/
192                return EditBox::OnKeyDown(key, ch);
193             }
194
195             bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
196             {
197                if(active) SelectAll(); else Deselect();
198                return EditBox::OnActivate(active, previous, goOnWithActivation, direct);
199             }
200
201             void DataBox::NotifyUpdate(EditBox editBox)
202             {
203                Modified();          
204
205             }
206          };
207          dataBox.size = { w, h * 4 + 2 }; 
208          if(dataBox.size.h + dataBox.position.y > dataBox.parent.clientSize.h)
209             dataBox.position.y = dataBox.parent.clientSize.h - dataBox.size.h;
210          if(dataBox.size.w + dataBox.position.x > dataBox.parent.clientSize.w)
211             dataBox.position.x = dataBox.parent.clientSize.w - dataBox.size.w;
212
213          editBox.contents = this;
214          editBox.visible = true;
215          editBox.Create();
216          if(!dataBox.active)
217          {
218             editBox.Deselect();
219             editBox.Home();
220          }
221          return editBox;
222       }
223       else
224          return String::OnEdit(dataBox, obsolete, x, y, w,h, userData);
225    }
226
227    bool OnSaveEdit(Window window, void * object)
228    {
229       bool changed = false;
230       EditBox editBox = (EditBox)window;
231       if(editBox.modifiedDocument)
232       {
233       /*
234          EditLine line;
235          int size = 0;
236          char * string;
237
238          delete this;
239
240          for(line = editBox.firstLine; line; line = line.next)
241             size += line.count+1;
242          this = string = new char[size+1];
243          size = 0;
244          for(line = editBox.firstLine; line; line = line.next)
245          {
246             memcpy(string + size, line.text, line.count);
247             size += line.count;
248             string[size] = '\n';
249             size++;
250          }
251          string[size] = '\0';
252 */
253          changed = true;
254       }
255       return changed;
256    }
257
258    void OnDisplay(Surface surface, int x, int y, int width, void * fieldData, Alignment alignment, DataDisplayFlags displayFlags)
259    {
260       if(this)
261       {
262          char ch;
263          char * string = this;
264          char actualString[8196];
265          int c, len = 0;
266          for(c = 0; (ch = string[c]) && len < sizeof(actualString)-1; c++)
267          {
268             if(ch == '\t') { actualString[len++] = '\\'; actualString[len++] = 't'; }
269             else if(ch == '\r') { actualString[len++] = '\\'; actualString[len++] = 'r'; }
270             else if(ch == '\n') { actualString[len++] = '\\'; actualString[len++] = 'n'; }
271             else actualString[len++] = ch;
272          }
273          actualString[len] = 0;
274          ((void (*)(void *, void *, void *, int, int, int, void *, uint, uint))(void *)class(String)._vTbl[__ecereVMethodID_class_OnDisplay])(class(String), actualString, surface, x, y, width, null, alignment, displayFlags);
275       }
276    }
277 };