|
@@ -6,9 +6,6 @@
|
6
|
6
|
package org.openzen.zenscript.ide.ui.view.editor;
|
7
|
7
|
|
8
|
8
|
import java.io.IOException;
|
9
|
|
-import java.util.ArrayList;
|
10
|
|
-import java.util.Iterator;
|
11
|
|
-import java.util.List;
|
12
|
9
|
import java.util.Timer;
|
13
|
10
|
import java.util.TimerTask;
|
14
|
11
|
import org.openzen.drawablegui.DCanvas;
|
|
@@ -24,6 +21,7 @@ import org.openzen.drawablegui.DKeyEvent.KeyCode;
|
24
|
21
|
import org.openzen.drawablegui.DMouseEvent;
|
25
|
22
|
import org.openzen.drawablegui.DRectangle;
|
26
|
23
|
import org.openzen.drawablegui.DTransform2D;
|
|
24
|
+import org.openzen.drawablegui.listeners.ListenerHandle;
|
27
|
25
|
import org.openzen.drawablegui.live.LiveObject;
|
28
|
26
|
import org.openzen.drawablegui.live.SimpleLiveObject;
|
29
|
27
|
import org.openzen.zenscript.ide.host.IDESourceFile;
|
|
@@ -43,6 +41,8 @@ public class SourceEditor implements DComponent {
|
43
|
41
|
private final LiveObject<DDimensionPreferences> dimensionPreferences = new SimpleLiveObject<>(new DDimensionPreferences(0, 0));
|
44
|
42
|
private final String tab = " ";
|
45
|
43
|
private final IDESourceFile sourceFile;
|
|
44
|
+ private final TokenModel tokens;
|
|
45
|
+ private final ListenerHandle<TokenModel.Listener> tokenListener;
|
46
|
46
|
|
47
|
47
|
private DRectangle bounds;
|
48
|
48
|
private DDrawingContext context;
|
|
@@ -50,7 +50,6 @@ public class SourceEditor implements DComponent {
|
50
|
50
|
private int textLineHeight;
|
51
|
51
|
private int fullLineHeight;
|
52
|
52
|
private int selectionLineHeight;
|
53
|
|
- private final List<Line> lines = new ArrayList<>();
|
54
|
53
|
|
55
|
54
|
private int lineBarWidth;
|
56
|
55
|
private CursorPosition cursorStart = null;
|
|
@@ -65,6 +64,8 @@ public class SourceEditor implements DComponent {
|
65
|
64
|
|
66
|
65
|
public SourceEditor(IDESourceFile sourceFile) {
|
67
|
66
|
this.sourceFile = sourceFile;
|
|
67
|
+ tokens = new TokenModel(sourceFile.getName(), tab.length());
|
|
68
|
+ tokenListener = tokens.addListener(new TokenListener());
|
68
|
69
|
|
69
|
70
|
blink.scheduleAtFixedRate(new TimerTask() {
|
70
|
71
|
@Override
|
|
@@ -74,7 +75,8 @@ public class SourceEditor implements DComponent {
|
74
|
75
|
}, 300, 300);
|
75
|
76
|
|
76
|
77
|
try {
|
77
|
|
- parse();
|
|
78
|
+ TokenParser<ZSToken, ZSTokenType> parser = ZSTokenParser.createRaw(sourceFile.getName(), new ReaderCharReader(sourceFile.read()), tab.length());
|
|
79
|
+ tokens.set(parser);
|
78
|
80
|
} catch (IOException ex) {
|
79
|
81
|
ex.printStackTrace();
|
80
|
82
|
}
|
|
@@ -88,7 +90,7 @@ public class SourceEditor implements DComponent {
|
88
|
90
|
fullLineHeight = textLineHeight + fontMetrics.getLeading() + style.extraLineSpacing;
|
89
|
91
|
selectionLineHeight = textLineHeight + style.selectionPaddingTop + style.selectionPaddingBottom;
|
90
|
92
|
|
91
|
|
- dimensionPreferences.setValue(new DDimensionPreferences(0, fullLineHeight * lines.size()));
|
|
93
|
+ dimensionPreferences.setValue(new DDimensionPreferences(0, fullLineHeight * tokens.getLineCount()));
|
92
|
94
|
}
|
93
|
95
|
|
94
|
96
|
@Override
|
|
@@ -111,7 +113,7 @@ public class SourceEditor implements DComponent {
|
111
|
113
|
DIRectangle canvasBounds = canvas.getBounds();
|
112
|
114
|
canvas.fillRectangle(bounds.x, bounds.y, bounds.width, bounds.height, 0xFFFFFFFF);
|
113
|
115
|
|
114
|
|
- lineBarWidth = Math.max(50, fontMetrics.getWidth(Integer.toString(lines.size()))) + 5;
|
|
116
|
+ lineBarWidth = Math.max(50, fontMetrics.getWidth(Integer.toString(tokens.getLineCount()))) + 5;
|
115
|
117
|
canvas.fillRectangle(bounds.x, bounds.y, lineBarWidth, bounds.height, 0xFFE9E8E2);
|
116
|
118
|
canvas.strokePath(tracer -> {
|
117
|
119
|
tracer.moveTo(bounds.x + lineBarWidth, bounds.y);
|
|
@@ -148,14 +150,14 @@ public class SourceEditor implements DComponent {
|
148
|
150
|
|
149
|
151
|
int y = bounds.y + style.selectionPaddingTop;
|
150
|
152
|
int lineIndex = 1;
|
151
|
|
- for (Line line : lines) {
|
|
153
|
+ for (TokenLine line : tokens.getLines()) {
|
152
|
154
|
if (y + textLineHeight >= canvasBounds.y && y < canvasBounds.y + canvasBounds.height) {
|
153
|
155
|
String lineNumber = Integer.toString(lineIndex);
|
154
|
156
|
int lineNumberX = x - 15 - (int)canvas.measureTextLength(font, lineNumber);
|
155
|
157
|
canvas.drawText(font, 0xFFA0A0A0, lineNumberX, y + fontMetrics.getAscent(), lineNumber);
|
156
|
158
|
|
157
|
159
|
int lineX = x;
|
158
|
|
- for (ZSToken token : line.tokens) {
|
|
160
|
+ for (ZSToken token : line.getTokens()) {
|
159
|
161
|
String content = getDisplayContent(token);
|
160
|
162
|
canvas.drawText(font, TokenClass.get(token.type).color, lineX, y + fontMetrics.getAscent(), content);
|
161
|
163
|
lineX += canvas.measureTextLength(font, content);
|
|
@@ -248,19 +250,19 @@ public class SourceEditor implements DComponent {
|
248
|
250
|
int line = cursorEnd.line - 1;
|
249
|
251
|
CursorPosition position = new CursorPosition(
|
250
|
252
|
line,
|
251
|
|
- Math.min(lines.get(line).length, cursorEnd.offset));
|
|
253
|
+ Math.min(tokens.getLineLength(line), cursorEnd.offset));
|
252
|
254
|
setCursor(shift ? cursorStart : position, position);
|
253
|
255
|
}
|
254
|
256
|
break;
|
255
|
257
|
case DOWN:
|
256
|
|
- if (cursorEnd == null || cursorEnd.line >= lines.size() - 1)
|
|
258
|
+ if (cursorEnd == null || cursorEnd.line >= tokens.getLineCount() - 1)
|
257
|
259
|
return;
|
258
|
260
|
|
259
|
261
|
{
|
260
|
262
|
int line = cursorEnd.line + 1;
|
261
|
263
|
CursorPosition position = new CursorPosition(
|
262
|
264
|
line,
|
263
|
|
- Math.min(lines.get(line).length, cursorEnd.offset));
|
|
265
|
+ Math.min(tokens.getLineLength(line), cursorEnd.offset));
|
264
|
266
|
setCursor(shift ? cursorStart : position, position);
|
265
|
267
|
}
|
266
|
268
|
break;
|
|
@@ -272,7 +274,7 @@ public class SourceEditor implements DComponent {
|
272
|
274
|
CursorPosition position;
|
273
|
275
|
if (cursorEnd.offset == 0) {
|
274
|
276
|
int line = cursorEnd.line - 1;
|
275
|
|
- position = new CursorPosition(line, lines.get(line).length);
|
|
277
|
+ position = new CursorPosition(line, tokens.getLineLength(line));
|
276
|
278
|
} else {
|
277
|
279
|
position = new CursorPosition(cursorEnd.line, cursorEnd.offset - 1);
|
278
|
280
|
}
|
|
@@ -280,12 +282,12 @@ public class SourceEditor implements DComponent {
|
280
|
282
|
}
|
281
|
283
|
break;
|
282
|
284
|
case RIGHT:
|
283
|
|
- if (cursorEnd == null || (cursorEnd.offset == lines.get(cursorEnd.line).length && cursorEnd.line >= lines.size() - 1))
|
|
285
|
+ if (cursorEnd == null || (cursorEnd.offset == tokens.getLineLength(cursorEnd.line) && cursorEnd.line >= tokens.getLineCount() - 1))
|
284
|
286
|
return;
|
285
|
287
|
|
286
|
288
|
{
|
287
|
289
|
CursorPosition position;
|
288
|
|
- if (cursorEnd.offset == lines.get(cursorEnd.line).length) {
|
|
290
|
+ if (cursorEnd.offset == tokens.getLineLength(cursorEnd.line)) {
|
289
|
291
|
position = new CursorPosition(cursorEnd.line + 1, 0);
|
290
|
292
|
} else {
|
291
|
293
|
position = new CursorPosition(cursorEnd.line, cursorEnd.offset + 1);
|
|
@@ -303,7 +305,7 @@ public class SourceEditor implements DComponent {
|
303
|
305
|
newline();
|
304
|
306
|
break;
|
305
|
307
|
case TAB:
|
306
|
|
- type(tab);
|
|
308
|
+ type("\t");
|
307
|
309
|
break;
|
308
|
310
|
default:
|
309
|
311
|
if (e.character == DKeyEvent.CHAR_UNDEFINED)
|
|
@@ -326,38 +328,22 @@ public class SourceEditor implements DComponent {
|
326
|
328
|
}
|
327
|
329
|
|
328
|
330
|
private void save() {
|
329
|
|
- String content = contentToString();
|
|
331
|
+ String content = tokens.toString();
|
330
|
332
|
sourceFile.update(content);
|
331
|
333
|
}
|
332
|
334
|
|
333
|
|
- private String contentToString() {
|
334
|
|
- StringBuilder result = new StringBuilder();
|
335
|
|
- for (int i = 0; i < lines.size(); i++) {
|
336
|
|
- if (i > 0)
|
337
|
|
- result.append("\n");
|
338
|
|
-
|
339
|
|
- Line line = lines.get(i);
|
340
|
|
- for (ZSToken token : line.tokens) {
|
341
|
|
- result.append(token.content);
|
342
|
|
- }
|
343
|
|
- }
|
344
|
|
- return result.toString();
|
345
|
|
- }
|
346
|
|
-
|
347
|
335
|
private void delete() {
|
348
|
|
- Line line = lines.get(cursorEnd.line);
|
349
|
|
- if (cursorEnd.offset == line.length) {
|
|
336
|
+ TokenLine line = tokens.getLine(cursorEnd.line);
|
|
337
|
+ if (cursorEnd.offset == line.length()) {
|
350
|
338
|
// merge 2 lines
|
351
|
|
- if (cursorEnd.line == lines.size() - 1)
|
|
339
|
+ if (cursorEnd.line == tokens.getLineCount() - 1)
|
352
|
340
|
return;
|
353
|
341
|
|
354
|
|
- line.merge(cursorEnd.line, lines.get(cursorEnd.line + 1));
|
355
|
|
- lines.remove(cursorEnd.line + 1);
|
356
|
|
- onLinesUpdated();
|
|
342
|
+ tokens.deleteNewline(cursorEnd.line);
|
357
|
343
|
return;
|
358
|
344
|
}
|
359
|
345
|
|
360
|
|
- line.delete(cursorEnd.line, cursorEnd.offset);
|
|
346
|
+ tokens.deleteCharacter(cursorEnd.line, cursorEnd.offset);
|
361
|
347
|
repaintLine(cursorEnd.line);
|
362
|
348
|
}
|
363
|
349
|
|
|
@@ -366,47 +352,42 @@ public class SourceEditor implements DComponent {
|
366
|
352
|
if (cursorEnd.line == 0)
|
367
|
353
|
return;
|
368
|
354
|
|
369
|
|
- int length = lines.get(cursorEnd.line - 1).length;
|
370
|
|
- lines.get(cursorEnd.line - 1).merge(cursorEnd.line - 1, lines.get(cursorEnd.line));
|
371
|
|
- lines.remove(cursorEnd.line);
|
372
|
|
- onLinesUpdated();
|
|
355
|
+ int length = tokens.getLineLength(cursorEnd.line - 1);
|
|
356
|
+ tokens.deleteNewline(cursorEnd.line - 1);
|
373
|
357
|
|
374
|
358
|
CursorPosition position = new CursorPosition(cursorEnd.line - 1, length);
|
375
|
359
|
setCursor(position, position);
|
376
|
360
|
return;
|
377
|
361
|
}
|
378
|
362
|
|
379
|
|
- lines.get(cursorEnd.line).delete(cursorEnd.line, cursorEnd.offset - 1);
|
|
363
|
+ tokens.deleteCharacter(cursorEnd.line, cursorEnd.offset - 1);
|
380
|
364
|
CursorPosition position = new CursorPosition(cursorEnd.line, cursorEnd.offset - 1);
|
381
|
365
|
setCursor(position, position);
|
382
|
|
- repaintLine(cursorEnd.line);
|
383
|
366
|
}
|
384
|
367
|
|
385
|
368
|
private void type(String value) {
|
386
|
|
- lines.get(cursorEnd.line).insert(cursorEnd.line, cursorEnd.offset, value);
|
|
369
|
+ tokens.insert(cursorEnd.line, cursorEnd.offset, value);
|
387
|
370
|
CursorPosition position = new CursorPosition(cursorEnd.line, cursorEnd.offset + value.length());
|
388
|
371
|
setCursor(position, position);
|
389
|
|
- repaintLine(cursorEnd.line);
|
390
|
372
|
}
|
391
|
373
|
|
392
|
374
|
private void newline() {
|
393
|
|
- lines.get(cursorEnd.line).split(cursorEnd.line, cursorEnd.offset);
|
394
|
|
- onLinesUpdated();
|
395
|
|
-
|
396
|
|
- CursorPosition position = new CursorPosition(cursorEnd.line + 1, 0);
|
|
375
|
+ String indent = tokens.getLine(cursorEnd.line).getIndent();
|
|
376
|
+ tokens.insert(cursorEnd.line, cursorEnd.offset, "\n" + indent);
|
|
377
|
+ CursorPosition position = new CursorPosition(cursorEnd.line + 1, indent.length());
|
397
|
378
|
setCursor(position, position);
|
398
|
379
|
}
|
399
|
380
|
|
400
|
381
|
private TokenPosition getTokenAt(CursorPosition position) {
|
401
|
|
- Line line = lines.get(position.line);
|
|
382
|
+ TokenLine line = tokens.getLine(position.line);
|
402
|
383
|
int offset = 0;
|
403
|
|
- for (ZSToken token : line.tokens) {
|
|
384
|
+ for (ZSToken token : line.getTokens()) {
|
404
|
385
|
if (offset + token.content.length() > position.offset)
|
405
|
386
|
return new TokenPosition(token, position.offset - offset);
|
406
|
387
|
offset += token.content.length();
|
407
|
388
|
}
|
408
|
389
|
|
409
|
|
- return new TokenPosition(line.tokens.get(line.tokens.size() - 1), position.offset - offset);
|
|
390
|
+ return new TokenPosition(line.getLastToken(), position.offset - offset);
|
410
|
391
|
}
|
411
|
392
|
|
412
|
393
|
private class TokenPosition {
|
|
@@ -433,6 +414,9 @@ public class SourceEditor implements DComponent {
|
433
|
414
|
}
|
434
|
415
|
|
435
|
416
|
private void repaintLine(int line) {
|
|
417
|
+ if (bounds == null)
|
|
418
|
+ return;
|
|
419
|
+
|
436
|
420
|
context.repaint(bounds.x, lineToY(line), bounds.width, selectionLineHeight);
|
437
|
421
|
}
|
438
|
422
|
|
|
@@ -455,20 +439,20 @@ public class SourceEditor implements DComponent {
|
455
|
439
|
|
456
|
440
|
if (line < 0)
|
457
|
441
|
line = 0;
|
458
|
|
- if (line >= lines.size())
|
459
|
|
- line = lines.size() - 1;
|
|
442
|
+ if (line >= tokens.getLineCount())
|
|
443
|
+ line = tokens.getLineCount() - 1;
|
460
|
444
|
|
461
|
445
|
return new CursorPosition(line, offset);
|
462
|
446
|
}
|
463
|
447
|
|
464
|
448
|
private int xToOffset(int lineIndex, int x) {
|
465
|
|
- if (lineIndex < 0 || lineIndex >= lines.size())
|
|
449
|
+ if (lineIndex < 0 || lineIndex >= tokens.getLineCount())
|
466
|
450
|
return 0;
|
467
|
451
|
|
468
|
|
- Line line = lines.get(lineIndex);
|
|
452
|
+ TokenLine line = tokens.getLine(lineIndex);
|
469
|
453
|
int lineX = bounds.x + lineBarWidth + 10;
|
470
|
454
|
int offset = 0;
|
471
|
|
- for (ZSToken token : line.tokens) {
|
|
455
|
+ for (ZSToken token : line.getTokens()) {
|
472
|
456
|
String content = getDisplayContent(token);
|
473
|
457
|
int tokenWidth = fontMetrics.getWidth(content);
|
474
|
458
|
if (lineX + tokenWidth > x) {
|
|
@@ -490,7 +474,7 @@ public class SourceEditor implements DComponent {
|
490
|
474
|
|
491
|
475
|
private int getStringIndexForPixels(String str, int pixels) {
|
492
|
476
|
int previousX = 0;
|
493
|
|
- for (int i = 1; i < str.length(); i++) {
|
|
477
|
+ for (int i = 1; i <= str.length(); i++) {
|
494
|
478
|
int currentX = fontMetrics.getWidth(str, 0, i);
|
495
|
479
|
if (currentX >= pixels)
|
496
|
480
|
return (pixels - previousX < currentX - pixels) ? i - 1 : i;
|
|
@@ -510,13 +494,13 @@ public class SourceEditor implements DComponent {
|
510
|
494
|
}
|
511
|
495
|
|
512
|
496
|
private int offsetToX(int line, int offset) {
|
513
|
|
- if (line >= lines.size())
|
|
497
|
+ if (line >= tokens.getLineCount())
|
514
|
498
|
return 0;
|
515
|
499
|
|
516
|
500
|
int tokensOffset = 0;
|
517
|
501
|
int x = bounds.x + lineBarWidth + 10;
|
518
|
|
- Line lineData = lines.get(line);
|
519
|
|
- for (ZSToken token : lineData.tokens) {
|
|
502
|
+ TokenLine lineData = tokens.getLine(line);
|
|
503
|
+ for (ZSToken token : lineData.getTokens()) {
|
520
|
504
|
String content = getDisplayContent(token);
|
521
|
505
|
if (tokensOffset + token.content.length() >= offset) {
|
522
|
506
|
if (token.type == ZSTokenType.T_WHITESPACE_TAB)
|
|
@@ -535,190 +519,28 @@ public class SourceEditor implements DComponent {
|
535
|
519
|
return token.type == ZSTokenType.T_WHITESPACE_TAB ? tab : token.content;
|
536
|
520
|
}
|
537
|
521
|
|
538
|
|
- private void parse() throws IOException {
|
539
|
|
- lines.clear();
|
540
|
|
- lines.add(new Line());
|
541
|
|
-
|
542
|
|
- TokenParser<ZSToken, ZSTokenType> parser = ZSTokenParser.createRaw(sourceFile.getName(), new ReaderCharReader(sourceFile.read()), tab.length());
|
543
|
|
- insertTokens(0, 0, parser);
|
544
|
|
- }
|
545
|
|
-
|
546
|
522
|
private void onLinesUpdated() {
|
547
|
|
- dimensionPreferences.setValue(new DDimensionPreferences(0, fullLineHeight * lines.size()));
|
|
523
|
+ dimensionPreferences.setValue(new DDimensionPreferences(0, fullLineHeight * tokens.getLineCount()));
|
548
|
524
|
|
549
|
525
|
if (bounds != null)
|
550
|
526
|
context.repaint(bounds.x, bounds.y, bounds.width, bounds.height);
|
551
|
527
|
}
|
552
|
528
|
|
553
|
|
- public class Line {
|
554
|
|
- public final List<ZSToken> tokens = new ArrayList<>();
|
555
|
|
- private int length;
|
556
|
|
-
|
557
|
|
- private void calculateLength() {
|
558
|
|
- length = 0;
|
559
|
|
- for (ZSToken token : tokens)
|
560
|
|
- length += token.content.length();
|
561
|
|
- }
|
562
|
|
-
|
563
|
|
- public void merge(int lineIndex, Line other) {
|
564
|
|
- if (tokens.isEmpty()) {
|
565
|
|
- tokens.addAll(other.tokens);
|
566
|
|
- length = other.length;
|
567
|
|
- return;
|
568
|
|
- }
|
569
|
|
-
|
570
|
|
- int fromToken = tokens.size() - 1;
|
571
|
|
- int toToken = other.tokens.size() > 0 ? fromToken + 2 : fromToken + 1;
|
572
|
|
- tokens.addAll(other.tokens);
|
573
|
|
- length += other.length;
|
574
|
|
- reparse(lineIndex, fromToken, lineIndex, toToken);
|
575
|
|
- }
|
576
|
|
-
|
577
|
|
- public Line split(int lineIndex, int offset) {
|
578
|
|
- if (offset < 0)
|
579
|
|
- throw new IllegalArgumentException("offset must be >= 0");
|
580
|
|
-
|
581
|
|
- int tokenOffset = 0;
|
582
|
|
- for (int i = 0; i < tokens.size(); i++) {
|
583
|
|
- ZSToken token = tokens.get(i);
|
584
|
|
- if (tokenOffset + token.content.length() > offset) {
|
585
|
|
- ZSToken broken = token;
|
586
|
|
- Line newLine = new Line();
|
587
|
|
- if (offset - tokenOffset != token.content.length() && offset - tokenOffset != 0) {
|
588
|
|
- ZSToken.Pair split = token.split(offset - tokenOffset);
|
589
|
|
- broken = split.first;
|
590
|
|
- newLine.tokens.add(split.second);
|
591
|
|
- }
|
592
|
|
-
|
593
|
|
- tokens.set(i, broken);
|
594
|
|
- for (int j = i + 1; j < tokens.size(); j++)
|
595
|
|
- newLine.tokens.add(tokens.get(j));
|
596
|
|
- for (int j = tokens.size() - 1; j > i; j--)
|
597
|
|
- tokens.remove(j);
|
598
|
|
-
|
599
|
|
- lines.add(lineIndex + 1, newLine);
|
600
|
|
- reparse(lineIndex, i, lineIndex + 1, 1);
|
601
|
|
- return newLine;
|
602
|
|
- }
|
603
|
|
- tokenOffset += token.content.length();
|
604
|
|
- }
|
605
|
|
-
|
606
|
|
- Line result = new Line();
|
607
|
|
- lines.add(result);
|
608
|
|
- return result;
|
609
|
|
- }
|
610
|
|
-
|
611
|
|
- public void delete(int lineIndex, int offset) {
|
612
|
|
- int tokenOffset = 0;
|
613
|
|
- for (int i = 0; i < tokens.size(); i++) {
|
614
|
|
- ZSToken token = tokens.get(i);
|
615
|
|
- if (tokenOffset + token.content.length() > offset) {
|
616
|
|
- if (token.content.length() == 1) {
|
617
|
|
- tokens.remove(i);
|
618
|
|
- } else {
|
619
|
|
- token = token.delete(offset - tokenOffset, 1);
|
620
|
|
- tokens.set(i, token);
|
621
|
|
- }
|
622
|
|
- length--;
|
623
|
|
-
|
624
|
|
- reparse(lineIndex, i, lineIndex, i + 1);
|
625
|
|
- return;
|
626
|
|
- }
|
627
|
|
- tokenOffset += token.content.length();
|
628
|
|
- }
|
629
|
|
- }
|
630
|
|
-
|
631
|
|
- public void insert(int lineIndex, int offset, String value) {
|
632
|
|
- int tokenOffset = 0;
|
633
|
|
- if (tokens.isEmpty()) {
|
634
|
|
- tokens.add(new ZSToken(ZSTokenType.INVALID, value));
|
635
|
|
- reparse(lineIndex, 0, lineIndex, 1);
|
636
|
|
- return;
|
637
|
|
- }
|
638
|
|
-
|
639
|
|
- for (int i = 0; i < tokens.size(); i++) {
|
640
|
|
- ZSToken token = tokens.get(i);
|
641
|
|
- if (tokenOffset + token.content.length() > offset) {
|
642
|
|
- token = token.insert(offset - tokenOffset, value);
|
643
|
|
- tokens.set(i, token);
|
644
|
|
- length += value.length();
|
645
|
|
- reparse(lineIndex, i, lineIndex, i + 1);
|
646
|
|
- return;
|
647
|
|
- }
|
648
|
|
- tokenOffset += token.content.length();
|
649
|
|
- }
|
650
|
|
-
|
651
|
|
- ZSToken token = tokens.get(tokens.size() - 1);
|
652
|
|
- token = new ZSToken(token.type, token.content + value);
|
653
|
|
- tokens.set(tokens.size() - 1, token);
|
654
|
|
- length += value.length();
|
655
|
|
- reparse(lineIndex, tokens.size() - 1, lineIndex, tokens.size());
|
656
|
|
- }
|
657
|
|
- }
|
658
|
|
-
|
659
|
|
- private void reparse(int fromLine, int fromToken, int toLine, int toToken) {
|
660
|
|
- TokenReparser reparser = new TokenReparser(sourceFile.getName(), lines, fromLine, fromToken, toLine, toToken, tab.length());
|
661
|
|
- List<ZSToken> tokens = reparser.reparse();
|
662
|
|
- replaceTokens(fromLine, fromToken, reparser.getLine(), reparser.getToken(), tokens);
|
663
|
|
- }
|
664
|
|
-
|
665
|
|
- private void replaceTokens(int fromLine, int fromToken, int toLine, int toToken, List<ZSToken> tokens) {
|
666
|
|
- removeTokens(fromLine, fromToken, toLine, toToken);
|
667
|
|
- insertTokens(fromLine, fromToken, tokens.iterator());
|
668
|
|
- }
|
669
|
|
-
|
670
|
|
- private void removeTokens(int fromLine, int fromToken, int toLine, int toToken) {
|
671
|
|
- if (toLine > fromLine) {
|
672
|
|
- Line fromLineObject = lines.get(fromLine);
|
673
|
|
- for (int i = fromLineObject.tokens.size() - 1; i >= fromToken; i--)
|
674
|
|
- fromLineObject.tokens.remove(i);
|
675
|
|
-
|
676
|
|
- Line toLineObject = lines.get(fromLine);
|
677
|
|
- for (int i = toToken - 1; i >= 0; i--)
|
678
|
|
- toLineObject.tokens.remove(i);
|
679
|
|
-
|
680
|
|
- fromLineObject.merge(fromLine, lines.remove(toLine));
|
681
|
|
- for (int i = toLine - 1; i > fromLine; i--)
|
682
|
|
- lines.remove(i);
|
683
|
|
-
|
|
529
|
+ private class TokenListener implements TokenModel.Listener {
|
|
530
|
+
|
|
531
|
+ @Override
|
|
532
|
+ public void onLineInserted(int index) {
|
684
|
533
|
onLinesUpdated();
|
685
|
|
- } else {
|
686
|
|
- Line line = lines.get(fromLine);
|
687
|
|
- for (int i = toToken - 1; i >= fromToken; i--)
|
688
|
|
- line.tokens.remove(i);
|
689
|
534
|
}
|
690
|
|
- }
|
691
|
|
-
|
692
|
|
- private void insertTokens(int line, int tokenIndex, Iterator<ZSToken> tokens) {
|
693
|
|
- boolean linesUpdated = false;
|
694
|
|
- Line currentLine = lines.get(line);
|
695
|
|
- while (tokens.hasNext()) {
|
696
|
|
- ZSToken token = tokens.next();
|
697
|
|
- if (token.type == ZSTokenType.T_WHITESPACE_NEWLINE) {
|
698
|
|
- currentLine.calculateLength();
|
699
|
|
-
|
700
|
|
- Line newLine = new Line();
|
701
|
|
- if (tokenIndex < currentLine.tokens.size()) {
|
702
|
|
- for (int i = tokenIndex; i < currentLine.tokens.size(); i++) {
|
703
|
|
- newLine.tokens.add(currentLine.tokens.remove(tokenIndex));
|
704
|
|
- }
|
705
|
|
- }
|
706
|
|
- currentLine = newLine;
|
707
|
|
- tokenIndex = 0;
|
708
|
|
- lines.add(++line, currentLine);
|
709
|
|
- linesUpdated = true;
|
710
|
|
- } else if (token.type != ZSTokenType.T_WHITESPACE_CARRIAGE_RETURN) {
|
711
|
|
- currentLine.tokens.add(tokenIndex++, token);
|
712
|
|
- }
|
|
535
|
+
|
|
536
|
+ @Override
|
|
537
|
+ public void onLineChanged(int index) {
|
|
538
|
+ repaintLine(index);
|
713
|
539
|
}
|
714
|
|
-
|
715
|
|
- currentLine.calculateLength();
|
716
|
|
-
|
717
|
|
- if (linesUpdated) {
|
|
540
|
+
|
|
541
|
+ @Override
|
|
542
|
+ public void onLineDeleted(int index) {
|
718
|
543
|
onLinesUpdated();
|
719
|
|
- } else {
|
720
|
|
- // Could be further optimized to only repaint the modified characters
|
721
|
|
- repaintLine(line);
|
722
|
544
|
}
|
723
|
545
|
}
|
724
|
546
|
|
|
@@ -740,6 +562,9 @@ public class SourceEditor implements DComponent {
|
740
|
562
|
|
741
|
563
|
public static TokenClass get(ZSTokenType type) {
|
742
|
564
|
switch (type) {
|
|
565
|
+ case T_COMMENT_SCRIPT:
|
|
566
|
+ case T_COMMENT_SINGLELINE:
|
|
567
|
+ case T_COMMENT_MULTILINE:
|
743
|
568
|
case T_WHITESPACE_CARRIAGE_RETURN:
|
744
|
569
|
case T_WHITESPACE_NEWLINE:
|
745
|
570
|
case T_WHITESPACE_SPACE:
|