6
6
package io .flutter .samples ;
7
7
8
8
import com .google .common .annotations .VisibleForTesting ;
9
+ import com .intellij .ide .BrowserUtil ;
9
10
import com .intellij .openapi .application .ApplicationManager ;
10
11
import com .intellij .openapi .editor .Document ;
11
12
import com .intellij .openapi .editor .Editor ;
13
+ import com .intellij .openapi .editor .colors .EditorColors ;
12
14
import com .intellij .openapi .fileEditor .FileEditor ;
13
15
import com .intellij .openapi .fileEditor .TextEditor ;
14
- import com .intellij .openapi .project .DumbAware ;
15
16
import com .intellij .openapi .project .Project ;
16
17
import com .intellij .openapi .util .Computable ;
17
- import com .intellij .openapi .util .Key ;
18
18
import com .intellij .openapi .vfs .VirtualFile ;
19
19
import com .intellij .psi .PsiDocumentManager ;
20
20
import com .intellij .psi .PsiFile ;
21
21
import com .intellij .psi .util .PsiTreeUtil ;
22
22
import com .intellij .ui .EditorNotificationPanel ;
23
- import com .intellij .ui .EditorNotifications ;
23
+ import com .intellij .ui .EditorNotificationProvider ;
24
+ import com .intellij .ui .HyperlinkLabel ;
24
25
import com .jetbrains .lang .dart .psi .DartClass ;
26
+ import icons .FlutterIcons ;
25
27
import io .flutter .sdk .FlutterSdk ;
26
28
import org .jetbrains .annotations .NotNull ;
27
29
import org .jetbrains .annotations .Nullable ;
28
30
31
+ import javax .swing .*;
29
32
import java .util .ArrayList ;
30
33
import java .util .Collections ;
31
34
import java .util .List ;
35
+ import java .util .function .Function ;
32
36
import java .util .regex .Pattern ;
33
37
34
- public class FlutterSampleNotificationProvider extends EditorNotifications .Provider <EditorNotificationPanel > implements DumbAware {
35
- private static final Key <EditorNotificationPanel > KEY = Key .create ("flutter.sample" );
36
-
38
+ public class FlutterSampleNotificationProvider implements EditorNotificationProvider {
37
39
@ NotNull final Project project ;
38
40
39
41
public FlutterSampleNotificationProvider (@ NotNull Project project ) {
40
42
this .project = project ;
41
43
}
42
44
43
- @ NotNull
44
- @ Override
45
- public Key <EditorNotificationPanel > getKey () {
46
- return KEY ;
47
- }
48
-
49
45
@ Nullable
50
46
@ Override
51
- public EditorNotificationPanel createNotificationPanel (@ NotNull VirtualFile file ,
52
- @ NotNull FileEditor fileEditor ,
53
- @ NotNull Project project ) {
54
- if (!(fileEditor instanceof TextEditor textEditor )) {
55
- return null ;
56
- }
57
-
47
+ public Function <? super @ NotNull FileEditor , ? extends @ Nullable JComponent > collectNotificationData (@ NotNull Project project ,
48
+ @ NotNull VirtualFile file ) {
58
49
final FlutterSdk sdk = FlutterSdk .getFlutterSdk (project );
59
50
if (sdk == null ) {
60
51
return null ;
61
52
}
62
53
63
54
final String flutterPackagePath = sdk .getHomePath () + "/packages/flutter/lib/src/" ;
64
- final String filePath = file .getPath ();
65
55
66
56
// Only show for files in the flutter sdk.
57
+ final String filePath = file .getPath ();
67
58
if (!filePath .startsWith (flutterPackagePath )) {
68
59
return null ;
69
60
}
70
61
62
+ return fileEditor -> createPanelForSamples (fileEditor , project , file , filePath , sdk , flutterPackagePath );
63
+ }
64
+
65
+ @ Nullable
66
+ private EditorNotificationPanel createPanelForSamples (@ NotNull FileEditor fileEditor ,
67
+ @ NotNull Project project ,
68
+ @ NotNull VirtualFile file ,
69
+ @ NotNull String filePath ,
70
+ @ NotNull FlutterSdk sdk ,
71
+ @ NotNull String flutterPackagePath ) {
72
+ if (!(fileEditor instanceof TextEditor textEditor )) {
73
+ return null ;
74
+ }
75
+
71
76
final Editor editor = textEditor .getEditor ();
72
77
final Document document = editor .getDocument ();
78
+ final PsiDocumentManager psiDocumentManager = PsiDocumentManager .getInstance (project );
79
+ if (psiDocumentManager == null ) {
80
+ return null ;
81
+ }
73
82
74
- final PsiFile psiFile = PsiDocumentManager . getInstance ( project ) .getPsiFile (document );
83
+ final PsiFile psiFile = psiDocumentManager .getPsiFile (document );
75
84
if (psiFile == null || !psiFile .isValid ()) {
76
85
return null ;
77
86
}
78
87
79
88
// Run the code to query the document in a read action.
80
89
final List <FlutterSample > samples = ApplicationManager .getApplication ().
81
90
runReadAction ((Computable <List <FlutterSample >>)() -> {
82
- //noinspection CodeBlock2Expr
83
91
return getSamplesFromDoc (flutterPackagePath , document , filePath );
84
92
});
85
93
86
- return samples .isEmpty () ? null : new FlutterSampleActionsPanel (samples );
94
+ if (samples != null && !samples .isEmpty ()) {
95
+ return new FlutterSampleActionsPanel (samples );
96
+ }
97
+ return null ;
87
98
}
88
99
89
- private List <FlutterSample > getSamplesFromDoc (String flutterPackagePath , Document document , String filePath ) {
100
+ @ NotNull
101
+ private List <FlutterSample > getSamplesFromDoc (@ NotNull String flutterPackagePath , @ NotNull Document document , @ NotNull String filePath ) {
90
102
final List <FlutterSample > samples = new ArrayList <>();
91
103
92
104
// Find all candidate class definitions.
@@ -111,7 +123,8 @@ private List<FlutterSample> getSamplesFromDoc(String flutterPackagePath, Documen
111
123
try {
112
124
// Context: https://github.com/flutter/flutter-intellij/issues/5634
113
125
dartdoc = DartDocumentUtils .getDartdocFor (document , declaration );
114
- }catch (IndexOutOfBoundsException e ) {
126
+ }
127
+ catch (IndexOutOfBoundsException e ) {
115
128
// ignore
116
129
}
117
130
if (dartdoc != null && containsDartdocFlutterSample (dartdoc )) {
@@ -127,7 +140,6 @@ private List<FlutterSample> getSamplesFromDoc(String flutterPackagePath, Documen
127
140
}
128
141
}
129
142
}
130
-
131
143
return samples ;
132
144
}
133
145
@@ -153,3 +165,28 @@ public static boolean containsDartdocFlutterSample(@NotNull List<String> lines)
153
165
return false ;
154
166
}
155
167
}
168
+
169
+ class FlutterSampleActionsPanel extends EditorNotificationPanel {
170
+ FlutterSampleActionsPanel (@ NotNull List <FlutterSample > samples ) {
171
+ super (EditorColors .GUTTER_BACKGROUND );
172
+
173
+ icon (FlutterIcons .Flutter );
174
+ text ("View example on flutter.dev" );
175
+
176
+ for (int i = 0 ; i < samples .size (); i ++) {
177
+ if (i != 0 ) {
178
+ myLinksPanel .add (new JSeparator (SwingConstants .VERTICAL ));
179
+ }
180
+
181
+ final FlutterSample sample = samples .get (i );
182
+
183
+ final HyperlinkLabel label = createActionLabel (sample .getClassName (), () -> browseTo (sample ));
184
+ label .setToolTipText (sample .getHostedDocsUrl ());
185
+ }
186
+ }
187
+
188
+ private void browseTo (FlutterSample sample ) {
189
+ BrowserUtil .browse (sample .getHostedDocsUrl ());
190
+ }
191
+ }
192
+
0 commit comments