Skip to content

Commit 2ed121c

Browse files
committed
Refresh CodeLens with invalidate text presentation. See
#181
1 parent 4d8037b commit 2ed121c

File tree

12 files changed

+474
-147
lines changed

12 files changed

+474
-147
lines changed
+98-62
Original file line numberDiff line numberDiff line change
@@ -6,44 +6,51 @@
66
import java.util.Collections;
77
import java.util.List;
88
import java.util.concurrent.CompletableFuture;
9+
import java.util.concurrent.atomic.AtomicInteger;
910

10-
import org.eclipse.jface.text.ITextListener;
11+
import org.eclipse.jface.text.BadLocationException;
12+
import org.eclipse.jface.text.IDocument;
13+
import org.eclipse.jface.text.IRegion;
1114
import org.eclipse.jface.text.ITextViewer;
12-
import org.eclipse.jface.text.TextEvent;
1315
import org.eclipse.jface.text.provisional.codelens.internal.CodeLens;
1416
import org.eclipse.jface.text.provisional.codelens.internal.CodeLensData;
1517
import org.eclipse.jface.text.provisional.codelens.internal.CodeLensHelper;
1618
import org.eclipse.jface.text.provisional.viewzones.ViewZoneChangeAccessor;
19+
import org.eclipse.jface.text.reconciler.DirtyRegion;
20+
import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
21+
import org.eclipse.swt.custom.StyledText;
22+
import org.eclipse.swt.custom.patch.StyledTextPatcher;
1723
import org.eclipse.swt.widgets.Display;
1824

1925
// /vscode/src/vs/editor/contrib/codelens/common/codelens.ts
20-
public class CodeLensContribution {
26+
public class CodeLensStrategy implements IReconcilingStrategy {
2127

2228
private final ITextViewer textViewer;
2329
private final List<String> targets;
24-
private ITextListener internalListener = new ITextListener() {
2530

26-
@Override
27-
public void textChanged(TextEvent event) {
28-
if (event.getDocumentEvent() != null) {
29-
onModelChange();
30-
}
31-
}
32-
};
31+
private AtomicInteger count = new AtomicInteger(0);
3332

3433
private ViewZoneChangeAccessor accessor;
3534
private List<CodeLens> _lenses;
36-
private CompletableFuture<Collection<CodeLensData>> symbolsPromise;
35+
private CompletableFuture<Void> symbolsPromise;
36+
private boolean invalidateTextPresentation;
37+
38+
public CodeLensStrategy(ITextViewer textViewer) {
39+
this(textViewer, true);
40+
}
3741

38-
public CodeLensContribution(ITextViewer textViewer) {
42+
public CodeLensStrategy(ITextViewer textViewer, boolean invalidateTextPresentation) {
3943
this.textViewer = textViewer;
44+
this.invalidateTextPresentation = invalidateTextPresentation;
4045
this.targets = new ArrayList<>();
41-
textViewer.addTextListener(internalListener);
42-
try {
43-
this.accessor = new ViewZoneChangeAccessor(textViewer);
44-
} catch (Exception e) {
45-
e.printStackTrace();
46-
}
46+
textViewer.getTextWidget().getDisplay().syncExec(new Runnable() {
47+
48+
@Override
49+
public void run() {
50+
CodeLensStrategy.this.accessor = new ViewZoneChangeAccessor(textViewer);
51+
}
52+
});
53+
4754
this._lenses = new ArrayList<>();
4855
}
4956

@@ -55,16 +62,19 @@ private void onModelChange() {
5562
if (symbolsPromise != null) {
5663
symbolsPromise.cancel(true);
5764
}
58-
symbolsPromise = getCodeLensData(textViewer, targets);
59-
// symbols.exceptionally(ex -> ex.printStackTrace());
60-
symbolsPromise.thenAccept(symbols -> {
65+
int modelCount = count.incrementAndGet();
66+
symbolsPromise = getCodeLensData(textViewer, targets, modelCount).thenAccept(symbols -> {
6167
renderCodeLensSymbols(symbols);
68+
}).exceptionally(e -> {
69+
e.printStackTrace();
70+
return null;
6271
});
72+
;
6373

6474
}
6575

66-
private static CompletableFuture<Collection<CodeLensData>> getCodeLensData(ITextViewer textViewer,
67-
List<String> targets) {
76+
private CompletableFuture<Collection<CodeLensData>> getCodeLensData(ITextViewer textViewer, List<String> targets,
77+
int modelCount) {
6878
return CompletableFuture.supplyAsync(() -> {
6979
List<CodeLensData> symbols = new ArrayList<>();
7080
for (String target : targets) {
@@ -128,7 +138,14 @@ private void renderCodeLensSymbols(Collection<CodeLensData> symbols) {
128138
while (groupsIndex < groups.size() && codeLensIndex < this._lenses.size()) {
129139

130140
int symbolsLineNumber = groups.get(groupsIndex).get(0).getSymbol().getRange().startLineNumber;
131-
int codeLensLineNumber = this._lenses.get(codeLensIndex).getLineNumber();
141+
int offset = this._lenses.get(codeLensIndex).getOffsetAtLine();
142+
int codeLensLineNumber = -1;
143+
try {
144+
codeLensLineNumber = offset != -1 ? textViewer.getDocument().getLineOfOffset(offset) + 1 : -1;
145+
} catch (BadLocationException e) {
146+
// TODO Auto-generated catch block
147+
e.printStackTrace();
148+
} // this._lenses.get(codeLensIndex).getLineNumber();
132149

133150
if (codeLensLineNumber < symbolsLineNumber) {
134151
this._lenses.get(codeLensIndex).dispose(helper, accessor);
@@ -151,7 +168,6 @@ private void renderCodeLensSymbols(Collection<CodeLensData> symbols) {
151168
groupsIndex++;
152169
}
153170
}
154-
155171
// Delete extra code lenses
156172
while (codeLensIndex < this._lenses.size()) {
157173
this._lenses.get(codeLensIndex).dispose(helper, accessor);
@@ -170,24 +186,35 @@ private void renderCodeLensSymbols(Collection<CodeLensData> symbols) {
170186
}
171187

172188
// helper.commit(changeAccessor);
173-
189+
// Display.getDefault().asyncExec(() -> {
190+
//// this._lenses.forEach((lens) -> {
191+
//// lens.redraw(accessor);
192+
//// });
193+
// textViewer.getTextWidget().redraw();
194+
// });
174195
_onViewportChanged();
175196
}
176197

177198
private void _onViewportChanged() {
178199
List<List<CodeLensData>> toResolve = new ArrayList<>();
179200
List<CodeLens> lenses = new ArrayList<>();
180201

181-
this._lenses.forEach((lens) -> {
202+
Integer topMargin = null;
203+
for (CodeLens lens : _lenses) {
182204
List<CodeLensData> request = lens.computeIfNecessary(null);
183205
if (request != null) {
184206
toResolve.add(request);
185207
lenses.add(lens);
208+
209+
Integer top = lens.getTopMargin();
210+
if (top != null) {
211+
topMargin = top;
212+
}
186213
}
187-
});
214+
}
188215

189216
if (toResolve.isEmpty()) {
190-
return;
217+
// return;
191218
}
192219

193220
int i = 0;
@@ -203,19 +230,40 @@ private void _onViewportChanged() {
203230
i++;
204231
}
205232

233+
final Integer top = topMargin;
206234
Display.getDefault().syncExec(() -> {
207-
this._lenses.forEach((lens) -> {
208-
lens.redraw(accessor);
209-
});
235+
StyledText styledText = textViewer.getTextWidget();
236+
if (invalidateTextPresentation) {
237+
// if (top != null && styledText.getTopMargin() != top) {
238+
// try {
239+
// Field f = styledText.getClass().getDeclaredField("topMargin");
240+
// f.setAccessible(true);
241+
// f.set(styledText, top);
242+
// } catch (Exception e) {
243+
// // TODO Auto-generated catch block
244+
// e.printStackTrace();
245+
// }
246+
// }
247+
textViewer.invalidateTextPresentation();
248+
} else {
249+
if (top != null && styledText.getTopMargin() != top) {
250+
styledText.setTopMargin(top);
251+
} else {
252+
int offset = styledText.getCaretOffset();
253+
StyledTextPatcher.setVariableLineHeight(styledText);
254+
styledText.redraw();
255+
styledText.setCaretOffset(offset);
256+
}
257+
}
210258
});
211259
}
212260

213-
public CodeLensContribution addTarget(String target) {
261+
public CodeLensStrategy addTarget(String target) {
214262
targets.add(target);
215263
return this;
216264
}
217265

218-
public CodeLensContribution removeTarget(String target) {
266+
public CodeLensStrategy removeTarget(String target) {
219267
targets.remove(target);
220268
return this;
221269
}
@@ -224,32 +272,20 @@ public void dispose() {
224272

225273
}
226274

227-
/*
228-
* private Collection<CompletableFuture<CodeLensData>>
229-
* getCodeLensData(ITextViewer textViewer) {
230-
*
231-
* Collection<CodeLensData> symbols = new ArrayList<>(); String
232-
* contentTypeId = "";
233-
*
234-
* // Collection<CompletableFuture<CodeLensData>> promises =
235-
* registry.all(contentTypeId).stream().map(provider -> { //
236-
* CompletableFuture<CodeLensData> promise =
237-
* CompletableFuture.supplyAsync(() -> { //
238-
* provider.provideCodeLenses(textViewer); // });
239-
*
240-
* // // // // new CompletableFuture<CodeLensData>(); // //promise. // //
241-
* promise.thenAccept(result -> { // if (result != null) { // for (ICodeLens
242-
* symbol : result) { // symbols.add(new CodeLensData(symbol, provider)); //
243-
* } // } // }) return promise; }).collect(Collectors.toList());
244-
*
245-
* for (
246-
*
247-
* ICodeLensProvider provider : providers) { ICodeLens[] result =
248-
* provider.provideCodeLenses(textViewer); if (result != null) { for
249-
* (ICodeLens symbol : result) { symbols.add(new CodeLensData(symbol,
250-
* provider)); } } }
251-
*
252-
* }
253-
*/
275+
@Override
276+
public void setDocument(IDocument document) {
277+
// TODO Auto-generated method stub
278+
279+
}
280+
281+
@Override
282+
public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
283+
onModelChange();
284+
}
285+
286+
@Override
287+
public void reconcile(IRegion partition) {
288+
onModelChange();
289+
}
254290

255291
}

eclipse/codelens/org.eclipse.codelens/src/org/eclipse/jface/text/provisional/codelens/internal/CodeLens.java

+15-1
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,16 @@ public int getLineNumber() {
3030
if (!isValid()) {
3131
return -1;
3232
}
33-
return zone.getAfterLineNumber();
33+
return zone.getAfterLineNumber() + 1;
3434
}
3535

36+
public int getOffsetAtLine() {
37+
if (!isValid()) {
38+
return -1;
39+
}
40+
return zone.getOffsetAtLine();
41+
}
42+
3643
public void updateCodeLensSymbols(List<CodeLensData> data, CodeLensHelper helper) {
3744
this._data = data;
3845
}
@@ -61,4 +68,11 @@ public void updateCommands(List<ICodeLens> resolvedSymbols) {
6168
public void redraw(ViewZoneChangeAccessor accessor) {
6269
accessor.layoutZone(zone);
6370
}
71+
72+
public Integer getTopMargin() {
73+
if (isValid() && zone.getAfterLineNumber() == 0) {
74+
return zone.getHeightInPx();
75+
}
76+
return null;
77+
}
6478
}

eclipse/codelens/org.eclipse.codelens/src/org/eclipse/jface/text/provisional/codelens/internal/CodeLensViewZone.java

+21
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package org.eclipse.jface.text.provisional.codelens.internal;
22

33
import org.eclipse.jface.text.provisional.viewzones.ViewZone;
4+
import org.eclipse.swt.events.MouseEvent;
45

56
public class CodeLensViewZone extends ViewZone {
67

78
private String text;
9+
private MouseEvent hover;
810

911
public CodeLensViewZone(int afterLineNumber, int height) {
1012
super(afterLineNumber, height, CodeLensViewZoneRenderer.getInstance());
@@ -17,4 +19,23 @@ public void setText(String text) {
1719
public String getText() {
1820
return text;
1921
}
22+
23+
@Override
24+
public void mouseHover(MouseEvent event) {
25+
hover = event;
26+
}
27+
28+
@Override
29+
public void mouseEnter(MouseEvent event) {
30+
hover = event;
31+
}
32+
33+
@Override
34+
public void mouseExit(MouseEvent event) {
35+
hover = null;
36+
}
37+
38+
public MouseEvent getHover() {
39+
return hover;
40+
}
2041
}

eclipse/codelens/org.eclipse.codelens/src/org/eclipse/jface/text/provisional/codelens/internal/CodeLensViewZoneRenderer.java

+12-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public void draw(CodeLensViewZone viewZone, int paintX, int paintY, GC gc, Style
2121
Rectangle client = styledText.getClientArea();
2222
gc.setBackground(styledText.getDisplay().getSystemColor(SWT.COLOR_WHITE));
2323
styledText.drawBackground(gc, paintX, paintY, client.width, viewZone.getHeightInPx());
24+
2425
gc.setForeground(styledText.getDisplay().getSystemColor(SWT.COLOR_GRAY));
2526

2627
String text = viewZone.getText();
@@ -32,7 +33,17 @@ public void draw(CodeLensViewZone viewZone, int paintX, int paintY, GC gc, Style
3233
}
3334
Font font = new Font(styledText.getDisplay(), "Arial", 9, SWT.ITALIC);
3435
gc.setFont(font);
35-
gc.drawText(text, paintX, paintY + 4);
36+
int x = paintX;
37+
int y = paintY + 4;
38+
gc.drawText(text, x, y);
39+
40+
if (viewZone.getHover() != null) {
41+
styledText.setCursor(styledText.getDisplay().getSystemCursor(SWT.CURSOR_HAND));
42+
Point extent = gc.textExtent(text);
43+
gc.drawLine(x - 1, y + extent.y - 1, x + extent.x - 1, y + extent.y - 1);
44+
} else {
45+
styledText.setCursor(null);
46+
}
3647
}
3748
}
3849

eclipse/codelens/org.eclipse.codelens/src/org/eclipse/jface/text/provisional/viewzones/IViewZone.java

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.eclipse.jface.text.provisional.viewzones;
22

33
import org.eclipse.swt.custom.StyledText;
4+
import org.eclipse.swt.events.MouseEvent;
45

56
public interface IViewZone {
67

@@ -24,4 +25,10 @@ public interface IViewZone {
2425

2526
void dispose();
2627

28+
void mouseHover(MouseEvent event);
29+
30+
void mouseExit(MouseEvent event);
31+
32+
void mouseEnter(MouseEvent event);
33+
2734
}

0 commit comments

Comments
 (0)