ide/Panels: (#965) Fixed non-sensical repositioning of Windows on activation
[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 OnClose(bool parentClosing)
98    {
99       visible = false;
100       if(!parentClosing)
101          ide.RepositionWindows(false);
102       return parentClosing;
103    }
104
105    void Show()
106    {
107       visible = true;
108       ide.RepositionWindows(false);
109       Activate();
110    }
111
112    void LoadFromWorkspace()
113    {
114       for(wh : ide.workspace.watches)
115          AddWatch(wh);
116    }
117
118    void AddWatch(Watch wh)
119    {
120       DataRow row = listBox.AddRowAfter(listBox.lastRow.previous);
121       row.tag = (int64)wh;
122       wh.row = row;
123       UpdateWatch(wh);
124    }
125
126    void UpdateWatch(Watch wh)
127    {
128       if(wh)
129       {
130          DataRow row = wh.row;
131          if(row && row.tag)
132          {
133             row.SetData(expressionField, wh.expression);
134             row.SetData(typeField, wh.type);
135             //row.SetData(addressField, wh.address);
136             row.SetData(valueField, wh.value);
137          }
138       }
139    }
140
141    void Clear()
142    {
143       DataRow row;
144       listBox.Clear();
145       row = listBox.AddRow();
146       row.SetData(expressionField, null);
147       row.SetData(typeField, null);
148       row.SetData(valueField, null);
149       if(ide.workspace)
150       {
151          for(w : ide.workspace.watches)
152             w.row = null;
153       }
154    }
155 }
156
157 class WatchMultiLineString : String
158 {
159    Window OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)
160    {
161       if(this && strchr(this, '\n'))
162       {
163          // Don't show the editbox right away so that the text is highlighted by default
164          EditBox editBox
165          {
166             parent = dataBox, master = obsolete, visible = false,
167             borderStyle = contour,
168             //interim = true,
169             hasHorzScroll = true, hasVertScroll = true,
170             modifyVirtualArea = false,
171             anchor = { 0, 0, 0, 0 };
172             //position = { x + dataBox.absPosition.x, y + dataBox.absPosition.y };
173             //size = { w, h * 4 }; 
174             multiLine = true;
175
176             bool OnKeyDown(Key key, unichar ch)
177             {
178                /*if(key == escape)
179                {
180                   ((ListBox)master.master).currentField = ((ListBox)master.master).firstField;
181                   return false;
182                }*/
183                return EditBox::OnKeyDown(key, ch);
184             }
185
186             bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
187             {
188                if(active) SelectAll(); else Deselect();
189                return EditBox::OnActivate(active, previous, goOnWithActivation, direct);
190             }
191
192             void DataBox::NotifyUpdate(EditBox editBox)
193             {
194                Modified();          
195
196             }
197          };
198          dataBox.size = { w, h * 4 + 2 }; 
199          if(dataBox.size.h + dataBox.position.y > dataBox.parent.clientSize.h)
200             dataBox.position.y = dataBox.parent.clientSize.h - dataBox.size.h;
201          if(dataBox.size.w + dataBox.position.x > dataBox.parent.clientSize.w)
202             dataBox.position.x = dataBox.parent.clientSize.w - dataBox.size.w;
203
204          editBox.contents = this;
205          editBox.visible = true;
206          editBox.Create();
207          if(!dataBox.active)
208          {
209             editBox.Deselect();
210             editBox.Home();
211          }
212          return editBox;
213       }
214       else
215          return String::OnEdit(dataBox, obsolete, x, y, w,h, userData);
216    }
217
218    bool OnSaveEdit(Window window, void * object)
219    {
220       bool changed = false;
221       EditBox editBox = (EditBox)window;
222       if(editBox.modifiedDocument)
223       {
224       /*
225          EditLine line;
226          int size = 0;
227          char * string;
228
229          delete this;
230
231          for(line = editBox.firstLine; line; line = line.next)
232             size += line.count+1;
233          this = string = new char[size+1];
234          size = 0;
235          for(line = editBox.firstLine; line; line = line.next)
236          {
237             memcpy(string + size, line.text, line.count);
238             size += line.count;
239             string[size] = '\n';
240             size++;
241          }
242          string[size] = '\0';
243 */
244          changed = true;
245       }
246       return changed;
247    }
248
249    void OnDisplay(Surface surface, int x, int y, int width, void * fieldData, Alignment alignment, DataDisplayFlags displayFlags)
250    {
251       if(this)
252       {
253          char ch;
254          char * string = this;
255          char actualString[8196];
256          int c, len = 0;
257          for(c = 0; (ch = string[c]) && len < sizeof(actualString)-1; c++)
258          {
259             if(ch == '\t') { actualString[len++] = '\\'; actualString[len++] = 't'; }
260             else if(ch == '\r') { actualString[len++] = '\\'; actualString[len++] = 'r'; }
261             else if(ch == '\n') { actualString[len++] = '\\'; actualString[len++] = 'n'; }
262             else actualString[len++] = ch;
263          }
264          actualString[len] = 0;
265          ((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);
266       }
267    }
268 };