EditorBar.cpp

cbpporter cbpporter, 01/04/2017 04:42 PM

Download (11.8 KB)

 
1
#include "CodeEditor.h"
2

    
3
namespace Upp {
4

    
5
void Renumber(LineInfo& lf)
6
{
7
        LineInfo tf;
8
        int l = 0;
9
        if(lf.GetCount()) {
10
                LineInfoRecord& t = tf.Add();
11
                t.breakpoint = lf[0].breakpoint;
12
                t.lineno = 0;
13
                t.count = lf[0].count;
14
                t.error = lf[0].error;
15
                t.firstedited = lf[0].firstedited;
16
                t.edited = lf[0].edited;
17
                l += t.count;
18
        }
19
        for(int i = 1; i < lf.GetCount(); i++) {
20
                LineInfoRecord& r = lf[i];
21
                if(r.breakpoint.IsEmpty() && r.error == 0 && r.edited == 0 &&
22
                        tf.Top().breakpoint.IsEmpty() && tf.Top().error == 0 && tf.Top().edited == 0)
23
                        tf.Top().count += r.count;
24
                else {
25
                        LineInfoRecord& t = tf.Add();
26
                        t.breakpoint = r.breakpoint;
27
                        t.error = r.error;
28
                        t.firstedited = r.firstedited;
29
                        t.edited = r.edited;
30
                        t.count = r.count;
31
                        t.lineno = l;
32
                }
33
                l += r.count;
34
        }
35
        lf = pick(tf);
36
}
37

    
38
void ClearBreakpoints(LineInfo& lf)
39
{
40
        for(int i = 0; i < lf.GetCount(); i++)
41
                lf[i].breakpoint.Clear();
42
}
43

    
44
void ValidateBreakpoints(LineInfo& lf)
45
{
46
        for(int i = 0; i < lf.GetCount(); i++)
47
                if(lf[i].breakpoint[0] == 0xe)
48
                        lf[i].breakpoint = "1";
49
}
50

    
51
void EditorBar::sPaintImage(Draw& w, int x, int y, int fy, const Image& img)
52
{
53
        w.DrawImage(x, y + (fy - img.GetSize().cy) / 2, img);
54
}
55

    
56
void EditorBar::Paint(Draw& w)
57
{
58
        Size sz = GetSize();
59
        w.DrawRect(0, 0, sz.cx, sz.cy, SColorLtFace);
60
        if(!editor) return;
61
        int fy = editor->GetFontSize().cy;
62
        int hy = fy >> 1;
63
        int y = 0;
64
        int i = editor->GetScrollPos().y;
65
        int cy = GetSize().cy;
66
        String hl = editor->GetHighlight();
67
        bool hi_if = (hilite_if_endif && findarg(hl, "cpp", "cs", "java") >= 0);
68
        Vector<IfState> previf;
69
        if(hi_if)
70
                previf <<= editor->GetIfStack(i);
71
        int ptri[2];
72
        for(int q = 0; q < 2; q++)
73
                ptri[q] = ptrline[q] >= 0 ? GetLineNo(ptrline[q]) : -1;
74
        while(y < cy) {
75
                String b;
76
                int err = 0;
77
                int edit = 0;
78
                String ann;
79
                Image  icon;
80
                if(i < li.GetCount()) {
81
                        const LnInfo& l = li[i];
82
                        b = l.breakpoint;
83
                        err = l.error;
84
                        edit = l.edited;
85
                        icon = l.icon;
86
                        ann = l.annotation;
87
                }
88
                if(editor->GetCaret().top == y && editor->barline)
89
                        w.DrawRect(0, y, sz.cx, fy, Blend(SColorHighlight(), SColorLtFace(), 200));
90
                if(line_numbers && i < editor->GetLineCount()) {
91
                        String n = AsString((i + 1) % 1000000);
92
                        Font fnt = editor->GetFont();
93
                        Size tsz = GetTextSize(n, fnt);
94
                        w.DrawText(sz.cx - 2 - (hi_if ? 3 : 0) - tsz.cx - annotations, y + (fy - tsz.cy) / 2, n, fnt, Brown);
95
                }
96
                if(hi_if) {
97
                        Vector<IfState> nextif;
98
                        if(i < li.GetCount())
99
                                nextif <<= editor->GetIfStack(i + 1);
100
                        int pifl = previf.GetCount(), nifl = nextif.GetCount();
101
                        int dif = max(pifl, nifl);
102
                        if(--dif >= 0) {
103
                                char p = (dif < pifl ? previf[dif].state : 0);
104
                                char n = (dif < nifl ? nextif[dif].state : 0);
105
                                int wd = min(2 * (dif + 1), sz.cx);
106
                                int x = sz.cx - wd;
107
                                Color cn = EditorSyntax::IfColor(n);
108
                                if(p == n)
109
                                        w.DrawRect(x, y, 1, fy, cn);
110
                                else {
111
                                        Color cp = EditorSyntax::IfColor(p);
112
                                        w.DrawRect(x, y, 1, hy, cp);
113
                                        w.DrawRect(x, y + hy, wd, 1, Nvl(cn, cp));
114
                                        w.DrawRect(x, y + hy, 1, fy - hy, cn);
115
                                        if(--dif >= 0) {
116
                                                x = sz.cx - min(2 * (dif + 1), sz.cx);
117
                                                if(!p)
118
                                                        w.DrawRect(x, y, 1, hy, EditorSyntax::IfColor(dif < pifl ? previf[dif].state : 0));
119
                                                if(!n)
120
                                                        w.DrawRect(x, y + hy, 1, fy - hy, EditorSyntax::IfColor(dif < nifl ? nextif[dif].state : 0));
121
                                        }
122
                                }
123
                        }
124
                        previf = pick(nextif);
125
                }
126
                if(editor->GetMarkLines()) {
127
                        int width = 6;
128
                        if(edit)
129
                        {
130
                                int age = (int)(log((double)(editor->GetUndoCount() + 1 - edit)) * 30);
131
                                w.DrawRect(0, y, width, fy, Blend(LtBlue, SColorLtFace(), min(220, age)));
132
                        }
133
                        if(err)
134
                                w.DrawRect(width, y, width, fy, err == 1 ? LtRed : (err == 2 ? Color(255, 175, 0) : Green));
135
                }
136

    
137
                if(!b.IsEmpty())
138
                        sPaintImage(w, check_edited ? 7: 0, y, fy, b == "1"   ? CodeEditorImg::Breakpoint() :
139
                                              b == "\xe" ? CodeEditorImg::InvalidBreakpoint() :
140
                                                           CodeEditorImg::CondBreakpoint());
141
                for(int q = 0; q < 2; q++)
142
                        if(ptri[q] == i)
143
                                sPaintImage(w, 0, y, fy, ptrimg[q]);
144

    
145
                if(annotations && !IsNull(icon))
146
                        w.DrawImage(sz.cx - annotations, y + (fy - icon.GetSize().cy) / 2, icon);
147

    
148
                y += fy;
149
                i++;
150
        }
151
}
152

    
153
void EditorBar::MouseMove(Point p, dword flags)
154
{
155
        int pa = active_annotation;
156
        if(p.x > GetSize().cx - annotations)
157
                active_annotation = p.y / editor->GetFont().Info().GetHeight() + editor->GetScrollPos().y;
158
        else
159
                active_annotation = -1;
160
        if(active_annotation >= editor->GetLineCount())
161
                active_annotation = -1;
162
        if(pa != active_annotation)
163
                WhenAnnotationMove();
164
        if(editor)
165
                editor->MouseMove(Point(0, p.y), flags);
166
}
167

    
168
void EditorBar::MouseLeave()
169
{
170
        int pa = active_annotation;
171
        active_annotation = -1;
172
        if(pa != active_annotation)
173
                WhenAnnotationMove();
174
}
175

    
176
void EditorBar::LeftDown(Point p, dword flags)
177
{
178
        if(p.x > GetSize().cx - annotations)
179
                WhenAnnotationClick();
180
        else
181
        if(editor) {
182
                editor->LeftDown(Point(0, p.y), flags);
183
                ReleaseCtrlCapture();
184
        }
185
}
186

    
187
String& EditorBar::PointBreak(int& y)
188
{
189
        y = minmax(y / editor->GetFont().Info().GetHeight()
190
                + editor->GetScrollPos().y, 0, editor->GetLineCount());
191
        return li.At(y).breakpoint;
192
}
193

    
194
void EditorBar::LeftDouble(Point p, dword flags)
195
{
196
        if(!editor || !bingenabled) return;
197
        String& b = PointBreak(p.y);
198
        if(b.IsEmpty())
199
                b = "1";
200
        else
201
                b.Clear();
202
        WhenBreakpoint(p.y);
203
        Refresh();
204
}
205

    
206
void EditorBar::RightDown(Point p, dword flags)
207
{
208
        if(p.x > GetSize().cx - annotations)
209
                WhenAnnotationRightClick();
210
}
211

    
212
void EditorBar::MouseWheel(Point p, int zdelta, dword keyflags)
213
{
214
        if(editor) {
215
                int i = editor->GetScrollPos().y;
216
                editor->MouseWheel(p, zdelta, keyflags);
217
                if(i != editor->GetScrollPos().y)
218
                        MouseMove(p, keyflags);
219
        }
220
}
221

    
222
void EditorBar::InsertLines(int i, int count)
223
{
224
        li.InsertN(minmax(i + 1, 0, li.GetCount()), max(count, 0));
225
        if(editor->GetCheckEdited()) {
226
                if(editor->IsUndoOp() && li_removed.GetCount() >= count) {
227
                        for(int t = 0; t < count; t++) {
228
                                li.At(i + t).firstedited = li_removed[li_removed.GetCount() - count + t].firstedited;
229
                                li[i + t].edited = li_removed[li_removed.GetCount() - count + t].edited;
230
                        }
231
                        li_removed.Drop(count);
232
                        SetEdited(i + count, 1);
233
                        ignored_next_edit = true;
234
                }
235
                else {
236
                        if (li[i].firstedited == 0) {
237
                                bool fe = li[i].firstedited;
238
                                li.At(i + count).firstedited = fe;
239
                        }
240
                        SetEdited(i + 1, count);
241
                }
242
        }
243
        Refresh();
244
}
245

    
246
void EditorBar::RemoveLines(int i, int count)
247
{
248
        if(editor->GetCheckEdited() && !editor->IsUndoOp()) {
249
                for(int t = i - 1; t < i + count - 1; t++) {
250
                        LineInfoRemRecord& rm = li_removed.Add();
251
                        rm.firstedited = li[t].firstedited;
252
                        rm.edited = li[t].edited;
253
                }
254
                if(li.At(i + count - 1).firstedited)
255
                        next_age = li[i + count - 1].firstedited;
256
                else
257
                        next_age = editor->GetUndoCount();
258
        }
259
        i = minmax(i, 0, li.GetCount());
260
        li.Remove(i, minmax(count, 0, li.GetCount() - i));
261
        Refresh();
262
}
263

    
264
void EditorBar::ClearLines()
265
{
266
        li.Clear();
267
        li.Shrink();
268
        li_removed.Clear();
269
        li_removed.Shrink();
270
        Refresh();
271
}
272

    
273
LineInfo EditorBar::GetLineInfo() const
274
{
275
        LineInfo lf;
276
        int l = -2;
277
        for(int i = 0; i < li.GetCount(); i++) {
278
                const LnInfo& ln = li[i];
279
                if(!ln.breakpoint.IsEmpty() || ln.error || ln.edited) {
280
                        LineInfoRecord& r = lf.Add();
281
                        r.lineno = ln.lineno;
282
                        r.count = 1;
283
                        r.breakpoint = ln.breakpoint;
284
                        r.error = ln.error;
285
                        r.firstedited = ln.firstedited;
286
                        r.edited = ln.edited;
287
                        l = -2;
288
                }
289
                else
290
                if(ln.lineno != l) {
291
                        LineInfoRecord& r = lf.Add();
292
                        r.lineno = l = ln.lineno;
293
                        r.count = 1;
294
                }
295
                else
296
                        lf.Top().count++;
297
                if(l >= 0) l++;
298
        }
299
        return lf;
300
}
301

    
302
void EditorBar::SetLineInfo(const LineInfo& lf, int total)
303
{
304
        li.Clear();
305
        if(lf.GetCount() == 0) {
306
                for(int i = 0; i < total; i++)
307
                        li.Add().lineno = i;
308
        }
309
        else {
310
                for(int i = 0; i < lf.GetCount() && (total < 0 || li.GetCount() < total); i++) {
311
                        const LineInfoRecord& r = lf[i];
312
                        int l = r.lineno;
313
                        for(int j = r.count; j-- && li.GetCount() < total;) {
314
                                LnInfo& ln = li.Add();
315
                                ln.lineno = l;
316
                                ln.breakpoint = r.breakpoint;
317
                                ln.error = r.error;
318
                                ln.firstedited = r.firstedited;
319
                                ln.edited = r.edited;
320
                                if(l >= 0) l++;
321
                        }
322
                }
323
                while(li.GetCount() < total)
324
                        li.Add().lineno = -1;
325
        }
326
}
327

    
328
void EditorBar::Renumber(int linecount)
329
{
330
        li.SetCount(linecount);
331
        for(int i = 0; i < linecount; i++)
332
                li[i].lineno = i;
333
}
334

    
335
void EditorBar::ClearBreakpoints()
336
{
337
        for(int i = 0; i < li.GetCount(); i++)
338
                li[i].breakpoint.Clear();
339
        Refresh();
340
}
341

    
342
void EditorBar::ValidateBreakpoints()
343
{
344
        for(int i = 0; i < li.GetCount(); i++)
345
                if(li[i].breakpoint[0] == 0xe)
346
                        li[i].breakpoint = "1";
347
        Refresh();
348
}
349

    
350
String EditorBar::GetBreakpoint(int ln)
351
{
352
        return ln < li.GetCount() ? li[ln].breakpoint : Null;
353
}
354

    
355
void EditorBar::ClearAnnotations()
356
{
357
        for(int i = 0; i < li.GetCount(); i++) {
358
                li[i].icon.Clear();
359
                li[i].annotation.Clear();
360
        }
361
}
362

    
363
void EditorBar::SetAnnotation(int line, const Image& img, const String& ann)
364
{
365
        if(line >= 0 && line < li.GetCount()) {
366
                li[line].icon = img;
367
                li[line].annotation = ann;
368
        }
369
        Refresh();
370
}
371

    
372
String EditorBar::GetAnnotation(int line) const
373
{
374
        return line >= 0 && line < li.GetCount() ? li[line].annotation : String();
375
}
376

    
377
void EditorBar::SetBreakpoint(int ln, const String& s)
378
{
379
        li.At(ln).breakpoint = s;
380
        WhenBreakpoint(ln);
381
}
382

    
383
void EditorBar::SetEdited(int ln, int count)
384
{
385
        if(ignored_next_edit) {
386
                ignored_next_edit = false;
387
                return;
388
        }
389
        int age = editor->GetUndoCount() + 1;
390
        bool undo = editor->IsUndoOp();
391
        for(int i = 0; i < count; i++) {
392
                if(undo) {
393
                        if (li.At(ln + i).firstedited >= age - 1) {
394
                                li[ln + i].firstedited = 0;
395
                                li[ln + i].edited = 0;
396
                        }
397
                }
398
                else {
399
                        if(next_age) {
400
                                li[ln + i].firstedited = next_age;
401
                                li[ln + i].edited = age;
402
                                next_age = 0;
403
                        }
404
                        else {
405
                                if(li.At(ln + i).firstedited == 0)
406
                                        li[ln + i].firstedited = age;
407
                                li[ln + i].edited = age;
408
                        }
409
                }
410
        }
411
        Refresh();
412
}
413

    
414
void EditorBar::ClearEdited()
415
{
416
        for(int i = 0; i < li.GetCount(); i++) {
417
                li.At(i).firstedited = 0;
418
                li[i].edited = 0;
419
        }
420
        li_removed.Clear();
421
        li_removed.Shrink();
422
        Refresh();
423
}
424

    
425
void EditorBar::SetError(int ln, int err)
426
{
427
        li.At(ln).error = err;
428
}
429

    
430
void EditorBar::ClearErrors(int line)
431
{
432
        int count;
433
        if(line < 0) {
434
                line = 0;
435
                count = li.GetCount();
436
        }
437
        else
438
        if(line >= li.GetCount())
439
                return;
440
        else
441
                count = line + 1;
442

    
443
        for(int i = line; i < count; i++)
444
                li[i].error = 0;
445
}
446

    
447
int  EditorBar::GetLineNo(int lineno) const {
448
        for(int i = 0; i < li.GetCount(); i++) {
449
                if(lineno <= li[i].lineno)
450
                        return i;
451
        }
452
        return lineno;
453
}
454

    
455
int  EditorBar::GetNoLine(int line) const {
456
        int n = 0;
457
        for(int i = 0; i < li.GetCount(); i++) {
458
                if(li[i].lineno >= 0)
459
                        n = li[i].lineno;
460
                if(i == line) return n;
461
        }
462
        return n;
463
}
464

    
465
void EditorBar::SetPtr(int line, const Image& img, int i)
466
{
467
        ASSERT(i >= 0 && i < 2);
468
        ptrline[i] = line;
469
        ptrimg[i] = img;
470
        Refresh();
471
}
472

    
473
void EditorBar::HidePtr()
474
{
475
        ptrline[0] = ptrline[1] = -1;
476
        Refresh();
477
}
478

    
479
void EditorBar::SyncSize()
480
{
481
        int n = editor ? editor->GetLineCount() : 0;
482
        int i = 0;
483
        while(n) {
484
                i++;
485
                n /= 10;
486
        }
487
        
488
        bool hi_if = hilite_if_endif;
489
        if (editor && hi_if) {
490
                String hl = editor->GetHighlight();
491
                hi_if = (hilite_if_endif && findarg(hl, "cpp", "cs", "java") >= 0);
492
        }
493
        
494
        int w = annotations;
495
        if (line_numbers && editor)
496
                w += editor->GetFont()['0'] * i + 4;
497
        if (check_edited)
498
                w += 6 + 1;
499
        if (hi_if)
500
                w += 3;
501
        if (bingenabled)
502
                w += CodeEditorImg::Breakpoint().GetWidth() + 2 + 1;
503
        if(w != GetWidth()) {
504
                Width(w);
505
                Show(w);
506
        }
507
        
508
        Refresh();
509
}
510

    
511
void EditorBar::LineNumbers(bool b)
512
{
513
        line_numbers = b;
514
        SyncSize();
515
}
516

    
517
void EditorBar::Annotations(int width)
518
{
519
        annotations = width;
520
        SyncSize();
521
}
522

    
523
EditorBar::EditorBar()
524
{
525
        editor = NULL;
526
        check_edited = false;
527
        //LineNumbers(false);
528
        bingenabled = true;
529
        hilite_if_endif = true;
530
        line_numbers = false;
531
        annotations = 0;
532
        ignored_next_edit = false;
533
        next_age = 0;
534
        SyncSize();
535
        Show(GetWidth());
536
}
537

    
538
EditorBar::~EditorBar()
539
{
540
}
541

    
542
void ClearErrors(LineInfo& li)
543
{
544
        for(int i = 0; i < li.GetCount(); i++)
545
                li[i].error = 0;
546
}
547

    
548
void SetError(LineInfo& li, int line, int err)
549
{
550
        li.At(line).error = err;
551
}
552

    
553
}