26af4746334753acefc4931e87f7596d7aac319f
[sdk] / ide / src / panels / BreakpointsView.ec
1 import "ide"
2
3 class BreakpointsView : Window
4 {
5    visible = false;
6    borderStyle = sizable;
7    background = { 224, 224, 224 };
8    hasClose = true;
9    text = $"Breakpoints";
10    clientSize = Size { 206, 624 };
11    //anchor = Anchor { left = 0.8, top = 200, right = 0, bottom = 200 };
12    //size = { 150 };
13    anchor = Anchor { left = 0, right = 0, bottom = 0 };
14    size.h = 240;
15
16    bool moved, logging;
17
18    ListBox listBox
19    {
20       parent = this, resizable = true, hasHeader = true, alwaysEdit = true, collapseControl = true, size = { 206, 624 };
21       anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 }; //visible = true
22
23       background = viewsBackground;
24       foreground = viewsText;
25       selectionColor = selectionColor, selectionText = selectionText;
26
27       bool NotifyChanged(ListBox listBox, DataRow row)
28       {
29          if(listBox.currentField == locationField)
30          {
31             char * location = (char *)row.GetData(locationField);
32             if(location && location[0])
33             {
34                TrimLSpaces(location, location);
35                TrimRSpaces(location, location);
36             }
37             if(location && location[0])
38             {
39                if(row == listBox.lastRow)
40                {
41                   DataRow newRow = listBox.AddRow();
42                   newRow.SetData(locationField, null);
43                }
44                ide.workspace.ChangeBreakpoint(row, location); // TODO make sure passing only unix style path
45             }
46             else
47             {
48                ide.workspace.RemoveBreakpoint((Breakpoint)(intptr)row.tag);
49                // This is already done by Workspace::RemoveBreakpoint!
50                // listBox.DeleteRow(null);
51             }
52          }
53          else if(listBox.currentField == ignoreField || listBox.currentField == levelField)
54          {
55             int value = 0;
56             char * string = (char *)row.GetData(listBox.currentField);
57             //char str[16];
58             if(string && string[0])
59             {
60                TrimLSpaces(string, string);
61                TrimRSpaces(string, string);
62                value = atoi(string);
63             }
64             else if(listBox.currentField == levelField)
65                value = -1;
66             //str[0] = '\0';
67             //sprintf(str, "%d", value);
68             //listBox.StopEditing(true);
69             //row.SetData(listBox.currentField, str);
70             if((listBox.currentField == ignoreField && value < 1) ||
71                   (listBox.currentField == levelField && value < 0))
72                row.SetData(listBox.currentField, null);
73             if(listBox.currentField == levelField && value == 0)
74                row.SetData(listBox.currentField, "0");
75             if(listBox.currentField == ignoreField)
76                ide.workspace.ChangeBreakpointIgnore(row, value);
77             else if(listBox.currentField == levelField)
78                ide.workspace.ChangeBreakpointLevel(row, value);
79          }
80          else if(listBox.currentField == conditionField)
81          {
82             char * condition = (char *)row.GetData(conditionField);
83             if(condition && condition[0])
84             {
85                TrimLSpaces(condition, condition);
86                TrimRSpaces(condition, condition);
87             }
88             ide.workspace.ChangeBreakpointCondition(row, (condition && condition[0]) ? condition : null);
89          }
90          return true;
91       }
92
93       bool NotifyKeyDown(ListBox listBox, DataRow row, Key key, unichar ch)
94       {
95          if((SmartKey)key == enter)
96             GoToBpLocation(listBox.currentRow);
97          return true;
98       }
99
100       bool NotifyKeyHit(ListBox listBox, DataRow row, Key key, unichar ch)
101       {
102          if(row && (SmartKey)key == del)
103          {
104             listBox.StopEditing(true);
105             ide.workspace.RemoveBreakpoint((Breakpoint)(intptr)row.tag);
106          }
107          return true;
108       }
109
110       bool NotifyDoubleClick(ListBox listBox, int x, int y, Modifiers mods)
111       {
112          GoToBpLocation(listBox.currentRow);
113          return true;
114       }
115    };
116
117    // TODO: set field size based on font and i18n header string
118    // TODO: save column widths to ide settings
119    DataField locationField    { "char *", true , width = 220, header = $"Location" };
120    DataField hitsField        { "int"   , false, width =  28, header = $"Hits" };
121    DataField breaksField      { "int"   , false, width =  46, header = $"Breaks" };
122    DataField ignoreField      { "char *", true , width =  80, header = $"Ignore Count" };
123    DataField levelField       { "char *", true , width =  74, header = $"Stack Depth" };
124    DataField conditionField   { "char *", true , width = 130, header = $"Condition" };
125
126    BreakpointsView()
127    {
128       listBox.AddField(locationField);
129       listBox.AddField(hitsField);
130       listBox.AddField(breaksField);
131       listBox.AddField(ignoreField);
132       listBox.AddField(levelField);
133       listBox.AddField(conditionField);
134    }
135
136    bool OnKeyDown(Key key, unichar ch)
137    {
138       switch(key)
139       {
140          case escape: ide.ShowCodeEditor(); break;
141       }
142       return true;
143    }
144
145    bool OnClose(bool parentClosing)
146    {
147       visible = false;
148       if(!parentClosing)
149          ide.RepositionWindows(false);
150       return parentClosing;
151    }
152
153    void OnRedraw(Surface surface)
154    {
155       bool error;
156       int lineActive, lineUser;
157       int lineH;
158       //int scrollY = listBox.scroll.y;
159       //int boxH = clientSize.h;
160
161       displaySystem.FontExtent(listBox.font.font, " ", 1, null, &lineH);
162       //Window::OnRedraw(surface);
163       ide.debugger.GetCallStackCursorLine(&error, &lineActive, &lineUser);
164       // todo DrawLineMarginIcon(surface, error ? ide.bmpErrorActiveCursor : ide.bmpActiveCursor, lineActive, lineH, scrollY, boxH);
165    }
166
167    void DrawLineMarginIcon(Surface surface, BitmapResource resource, int line, int lineH, int scrollY, int boxH)
168    {
169       int lineY;
170       if(line)
171       {
172          lineY = (line - 1) * lineH;
173          if(lineY + lineH > scrollY && lineY + lineH < scrollY + boxH)
174          {
175             Bitmap bitmap = resource.bitmap;
176             if(bitmap)
177                surface.Blit(bitmap, 0, lineY - scrollY + (lineH - bitmap.height) / 2 + 1, 0, 0, bitmap.width, bitmap.height);
178          }
179       }
180    }
181
182    void Show()
183    {
184       visible = true;
185       ide.RepositionWindows(false);
186       Activate();
187    }
188
189    void LoadFromWorkspace()
190    {
191       for(bp : ide.workspace.breakpoints; bp.type == user)
192          AddBreakpoint(bp);
193    }
194
195    void AddBreakpoint(Breakpoint bp)
196    {
197       DataRow row = listBox.AddRow();
198       row.tag = (int64)(intptr)bp;
199       bp.row = row;
200       UpdateBreakpoint(row);
201       ide.callStackView.Update(null);
202    }
203
204    void RemoveBreakpoint(Breakpoint bp)
205    {
206       listBox.DeleteRow(bp.row);
207       bp.row = null;
208       ide.callStackView.Update(null);
209       Update(null);
210    }
211
212    void UpdateBreakpoint(DataRow row)
213    {
214       if(row && row.tag)
215       {
216          char string[32];
217          char * location;
218          Breakpoint bp = (Breakpoint)(intptr)row.tag;
219          location = bp.CopyUserLocationString();
220 #if defined(__WIN32__)
221          ChangeCh(location, '/', '\\');
222 #endif
223          row.SetData(locationField, location);
224          delete location;
225          if(bp.ignore == 0)
226             string[0] = '\0';
227          else
228             sprintf(string, "%d", bp.ignore);
229          row.SetData(ignoreField, string);
230          if(bp.level == -1)
231             string[0] = '\0';
232          else
233             sprintf(string, "%d", bp.level);
234          row.SetData(levelField, string);
235          if(bp.condition)
236             row.SetData(conditionField, bp.condition.expression);
237          else
238             row.SetData(conditionField, null);
239          row.SetData(hitsField, bp.hits);
240          row.SetData(breaksField, bp.breaks);
241       }
242    }
243
244    void Clear()
245    {
246       listBox.Clear();
247    }
248
249 private:
250    void GoToBpLocation(DataRow row)
251    {
252       if(row)
253       {
254          char * location = (char *)row.GetData(locationField);
255          if(location)
256             ide.debugger.GoToCodeLine(location);
257       }
258    }
259
260 }
261