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
+ private List <FlutterSample > getSamplesFromDoc (@ NotNull String flutterPackagePath , @ NotNull Document document , @ NotNull String filePath ) {
90
101
final List <FlutterSample > samples = new ArrayList <>();
91
102
92
103
// Find all candidate class definitions.
@@ -111,7 +122,8 @@ private List<FlutterSample> getSamplesFromDoc(String flutterPackagePath, Documen
111
122
try {
112
123
// Context: https://github.com/flutter/flutter-intellij/issues/5634
113
124
dartdoc = DartDocumentUtils .getDartdocFor (document , declaration );
114
- }catch (IndexOutOfBoundsException e ) {
125
+ }
126
+ catch (IndexOutOfBoundsException e ) {
115
127
// ignore
116
128
}
117
129
if (dartdoc != null && containsDartdocFlutterSample (dartdoc )) {
@@ -127,7 +139,6 @@ private List<FlutterSample> getSamplesFromDoc(String flutterPackagePath, Documen
127
139
}
128
140
}
129
141
}
130
-
131
142
return samples ;
132
143
}
133
144
@@ -153,3 +164,28 @@ public static boolean containsDartdocFlutterSample(@NotNull List<String> lines)
153
164
return false ;
154
165
}
155
166
}
167
+
168
+ class FlutterSampleActionsPanel extends EditorNotificationPanel {
169
+ FlutterSampleActionsPanel (@ NotNull List <FlutterSample > samples ) {
170
+ super (EditorColors .GUTTER_BACKGROUND );
171
+
172
+ icon (FlutterIcons .Flutter );
173
+ text ("View example on flutter.dev" );
174
+
175
+ for (int i = 0 ; i < samples .size (); i ++) {
176
+ if (i != 0 ) {
177
+ myLinksPanel .add (new JSeparator (SwingConstants .VERTICAL ));
178
+ }
179
+
180
+ final FlutterSample sample = samples .get (i );
181
+
182
+ final HyperlinkLabel label = createActionLabel (sample .getClassName (), () -> browseTo (sample ));
183
+ label .setToolTipText (sample .getHostedDocsUrl ());
184
+ }
185
+ }
186
+
187
+ private void browseTo (FlutterSample sample ) {
188
+ BrowserUtil .browse (sample .getHostedDocsUrl ());
189
+ }
190
+ }
191
+
0 commit comments