1
1
/*
2
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
25
25
package org .graalvm .visualvm .jfr .views .sampler ;
26
26
27
27
import java .awt .BorderLayout ;
28
+ import java .awt .Component ;
29
+ import java .awt .Container ;
30
+ import java .awt .Dimension ;
28
31
import java .awt .Font ;
32
+ import java .awt .LayoutManager ;
33
+ import java .awt .event .ActionEvent ;
29
34
import java .util .HashMap ;
30
35
import java .util .Map ;
36
+ import javax .swing .AbstractAction ;
37
+ import javax .swing .Action ;
38
+ import javax .swing .ActionMap ;
39
+ import javax .swing .InputMap ;
40
+ import javax .swing .JComponent ;
41
+ import javax .swing .JMenuItem ;
31
42
import javax .swing .JPanel ;
43
+ import javax .swing .JPopupMenu ;
32
44
import javax .swing .SortOrder ;
33
45
import javax .swing .SwingUtilities ;
46
+ import javax .swing .UIManager ;
34
47
import javax .swing .table .AbstractTableModel ;
35
48
import org .graalvm .visualvm .core .ui .components .DataViewComponent ;
36
49
import org .graalvm .visualvm .jfr .model .JFREvent ;
40
53
import org .graalvm .visualvm .jfr .model .JFRThread ;
41
54
import org .graalvm .visualvm .jfr .views .components .MessageComponent ;
42
55
import org .graalvm .visualvm .lib .jfluid .utils .StringUtils ;
56
+ import org .graalvm .visualvm .lib .profiler .api .ActionsSupport ;
57
+ import org .graalvm .visualvm .lib .profiler .api .GoToSource ;
43
58
import org .graalvm .visualvm .lib .profiler .api .icons .Icons ;
44
59
import org .graalvm .visualvm .lib .profiler .api .icons .LanguageIcons ;
45
60
import org .graalvm .visualvm .lib .profiler .api .icons .ProfilerIcons ;
46
61
import org .graalvm .visualvm .lib .ui .Formatters ;
62
+ import org .graalvm .visualvm .lib .ui .swing .FilterUtils ;
47
63
import org .graalvm .visualvm .lib .ui .swing .ProfilerTable ;
48
64
import org .graalvm .visualvm .lib .ui .swing .ProfilerTableContainer ;
65
+ import org .graalvm .visualvm .lib .ui .swing .SearchUtils ;
49
66
import org .graalvm .visualvm .lib .ui .swing .renderer .HideableBarRenderer ;
50
67
import org .graalvm .visualvm .lib .ui .swing .renderer .JavaNameRenderer ;
51
68
import org .graalvm .visualvm .lib .ui .swing .renderer .LabelRenderer ;
@@ -72,6 +89,10 @@ static final class HeapViewSupport extends JPanel implements JFREventVisitor {
72
89
private ProfilerTable table ;
73
90
private HideableBarRenderer [] renderers ;
74
91
92
+ private JComponent bottomPanel ;
93
+ private JComponent filterPanel ;
94
+ private JComponent searchPanel ;
95
+
75
96
76
97
HeapViewSupport (JFRModel model ) {
77
98
hasData = model .containsEvent (JFRSnapshotSamplerViewProvider .ObjectCountChecker .class );
@@ -163,7 +184,31 @@ private void initComponents() {
163
184
add (MessageComponent .noData ("Heap histogram" , JFRSnapshotSamplerViewProvider .ObjectCountChecker .checkedTypes ()), BorderLayout .CENTER );
164
185
} else {
165
186
tableModel = new HeapTableModel ();
166
- table = new ProfilerTable (tableModel , true , true , null );
187
+ table = new ProfilerTable (tableModel , true , true , null ) {
188
+ protected void populatePopup (JPopupMenu popup , Object value , Object userValue ) {
189
+ final String selectedClass = value == null ? null : value .toString ();
190
+
191
+ if (GoToSource .isAvailable ()) {
192
+ popup .add (new JMenuItem (NbBundle .getMessage (MemorySamplerViewSupport .class , "MemoryView_Context_GoToSource" )) { // NOI18N
193
+ { setEnabled (selectedClass != null ); setFont (getFont ().deriveFont (Font .BOLD )); }
194
+ protected void fireActionPerformed (ActionEvent e ) { GoToSource .openSource (null , selectedClass , null , null ); }
195
+ });
196
+ popup .addSeparator ();
197
+ }
198
+
199
+ popup .add (createCopyMenuItem ());
200
+ popup .addSeparator ();
201
+
202
+ popup .add (new JMenuItem (FilterUtils .ACTION_FILTER ) {
203
+ protected void fireActionPerformed (ActionEvent e ) { HeapViewSupport .this .activateFilter (); }
204
+ });
205
+ popup .add (new JMenuItem (SearchUtils .ACTION_FIND ) {
206
+ protected void fireActionPerformed (ActionEvent e ) { HeapViewSupport .this .activateSearch (); }
207
+ });
208
+ }
209
+ };
210
+
211
+ table .providePopupMenu (true );
167
212
168
213
table .setMainColumn (0 );
169
214
table .setFitWidthColumn (0 );
@@ -183,7 +228,159 @@ private void initComponents() {
183
228
table .setColumnRenderer (2 , renderers [1 ]);
184
229
185
230
add (new ProfilerTableContainer (table , false , null ), BorderLayout .CENTER );
231
+
232
+ InputMap inputMap = getInputMap (JComponent .WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
233
+ ActionMap actionMap = getActionMap ();
234
+
235
+ final String filterKey = org .graalvm .visualvm .lib .ui .swing .FilterUtils .FILTER_ACTION_KEY ;
236
+ Action filterAction = new AbstractAction () {
237
+ public void actionPerformed (ActionEvent e ) {
238
+ HeapViewSupport .this .activateFilter ();
239
+ }
240
+ };
241
+ ActionsSupport .registerAction (filterKey , filterAction , actionMap , inputMap );
242
+
243
+ final String findKey = SearchUtils .FIND_ACTION_KEY ;
244
+ Action findAction = new AbstractAction () {
245
+ public void actionPerformed (ActionEvent e ) {
246
+ HeapViewSupport .this .activateSearch ();
247
+ }
248
+ };
249
+ ActionsSupport .registerAction (findKey , findAction , actionMap , inputMap );
250
+
251
+ SwingUtilities .invokeLater (new Runnable () {
252
+ public void run () { SearchUtils .enableSearchActions (table ); }
253
+ });
254
+ }
255
+ }
256
+
257
+ private JComponent getBottomPanel () {
258
+ if (bottomPanel == null ) {
259
+ bottomPanel = new JPanel (new FilterFindLayout ());
260
+ bottomPanel .setOpaque (true );
261
+ bottomPanel .setBackground (UIManager .getColor ("controlShadow" )); // NOI18N
262
+ add (bottomPanel , BorderLayout .SOUTH );
263
+ }
264
+ return bottomPanel ;
265
+ }
266
+
267
+ private void activateFilter () {
268
+ JComponent panel = getBottomPanel ();
269
+
270
+ if (filterPanel == null ) {
271
+ filterPanel = FilterUtils .createFilterPanel (table , null );
272
+ panel .add (filterPanel );
273
+ Container parent = panel .getParent ();
274
+ parent .invalidate ();
275
+ parent .revalidate ();
276
+ parent .repaint ();
277
+ }
278
+
279
+ panel .setVisible (true );
280
+
281
+ filterPanel .setVisible (true );
282
+ filterPanel .requestFocusInWindow ();
283
+ }
284
+
285
+ private void activateSearch () {
286
+ JComponent panel = getBottomPanel ();
287
+
288
+ if (searchPanel == null ) {
289
+ searchPanel = SearchUtils .createSearchPanel (table );
290
+ panel .add (searchPanel );
291
+ Container parent = panel .getParent ();
292
+ parent .invalidate ();
293
+ parent .revalidate ();
294
+ parent .repaint ();
295
+ }
296
+
297
+ panel .setVisible (true );
298
+
299
+ searchPanel .setVisible (true );
300
+ searchPanel .requestFocusInWindow ();
301
+ }
302
+
303
+
304
+ private final class FilterFindLayout implements LayoutManager {
305
+
306
+ public void addLayoutComponent (String name , Component comp ) {}
307
+ public void removeLayoutComponent (Component comp ) {}
308
+
309
+ public Dimension preferredLayoutSize (Container parent ) {
310
+ JComponent filter = filterPanel ;
311
+ if (filter != null && !filter .isVisible ()) filter = null ;
312
+
313
+ JComponent search = searchPanel ;
314
+ if (search != null && !search .isVisible ()) search = null ;
315
+
316
+ Dimension dim = new Dimension ();
317
+
318
+ if (filter != null && search != null ) {
319
+ Dimension dim1 = filter .getPreferredSize ();
320
+ Dimension dim2 = search .getPreferredSize ();
321
+ dim .width = dim1 .width + dim2 .width + 1 ;
322
+ dim .height = Math .max (dim1 .height , dim2 .height );
323
+ } else if (filter != null ) {
324
+ dim = filter .getPreferredSize ();
325
+ } else if (search != null ) {
326
+ dim = search .getPreferredSize ();
327
+ }
328
+
329
+ if ((filter != null || search != null ) /*&& hasBottomFilterFindMargin()*/ )
330
+ dim .height += 1 ;
331
+
332
+ return dim ;
186
333
}
334
+
335
+ public Dimension minimumLayoutSize (Container parent ) {
336
+ JComponent filter = filterPanel ;
337
+ if (filter != null && !filter .isVisible ()) filter = null ;
338
+
339
+ JComponent search = searchPanel ;
340
+ if (search != null && !search .isVisible ()) search = null ;
341
+
342
+ Dimension dim = new Dimension ();
343
+
344
+ if (filter != null && search != null ) {
345
+ Dimension dim1 = filter .getMinimumSize ();
346
+ Dimension dim2 = search .getMinimumSize ();
347
+ dim .width = dim1 .width + dim2 .width + 1 ;
348
+ dim .height = Math .max (dim1 .height , dim2 .height );
349
+ } else if (filter != null ) {
350
+ dim = filter .getMinimumSize ();
351
+ } else if (search != null ) {
352
+ dim = search .getMinimumSize ();
353
+ }
354
+
355
+ if ((filter != null || search != null ) /*&& hasBottomFilterFindMargin()*/ )
356
+ dim .height += 1 ;
357
+
358
+ return dim ;
359
+ }
360
+
361
+ public void layoutContainer (Container parent ) {
362
+ JComponent filter = filterPanel ;
363
+ if (filter != null && !filter .isVisible ()) filter = null ;
364
+
365
+ JComponent search = searchPanel ;
366
+ if (search != null && !search .isVisible ()) search = null ;
367
+
368
+ int bottomOffset = /* hasBottomFilterFindMargin() ? 1 :*/ 0 ;
369
+
370
+ if (filter != null && search != null ) {
371
+ Dimension size = parent .getSize ();
372
+ int w = (size .width - 1 ) / 2 ;
373
+ filter .setBounds (0 , 0 , w , size .height - bottomOffset );
374
+ search .setBounds (w + 1 , 0 , size .width - w - 1 , size .height - bottomOffset );
375
+ } else if (filter != null ) {
376
+ Dimension size = parent .getSize ();
377
+ filter .setBounds (0 , 0 , size .width , size .height - bottomOffset );
378
+ } else if (search != null ) {
379
+ Dimension size = parent .getSize ();
380
+ search .setBounds (0 , 0 , size .width , size .height - bottomOffset );
381
+ }
382
+ }
383
+
187
384
}
188
385
189
386
0 commit comments