• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package ohos.devtools.views.layout.chartview.memory.javaagent;
17 
18 import com.intellij.ui.JBColor;
19 import com.intellij.ui.components.JBLabel;
20 import com.intellij.ui.components.JBPanel;
21 import com.intellij.ui.components.JBTabbedPane;
22 import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns;
23 import com.intellij.ui.treeStructure.treetable.TreeTableModel;
24 import net.miginfocom.swing.MigLayout;
25 import ohos.devtools.datasources.utils.profilerlog.ProfilerLogManager;
26 import ohos.devtools.services.memory.agentbean.AgentHeapBean;
27 import ohos.devtools.views.common.ColorConstants;
28 import ohos.devtools.views.common.LayoutConstants;
29 import ohos.devtools.views.common.UtConstant;
30 import ohos.devtools.views.common.customcomp.CustomComboBox;
31 import ohos.devtools.views.common.customcomp.CustomJBComboBoxUI;
32 import ohos.devtools.views.common.customcomp.CustomJBTextField;
33 import ohos.devtools.views.common.treetable.ExpandTreeTable;
34 import ohos.devtools.views.layout.chartview.memory.MemoryItemView;
35 import org.apache.logging.log4j.LogManager;
36 import org.apache.logging.log4j.Logger;
37 
38 import javax.swing.BorderFactory;
39 import javax.swing.SwingUtilities;
40 import javax.swing.event.ChangeEvent;
41 import javax.swing.event.ChangeListener;
42 import javax.swing.event.DocumentEvent;
43 import javax.swing.event.DocumentListener;
44 import javax.swing.tree.DefaultMutableTreeNode;
45 import java.awt.BorderLayout;
46 import java.awt.Dimension;
47 import java.awt.Font;
48 import java.awt.event.FocusEvent;
49 import java.awt.event.FocusListener;
50 import java.util.ArrayList;
51 import java.util.List;
52 import java.util.stream.Collectors;
53 
54 import static ohos.devtools.views.common.Constant.IS_DEVELOP_MODE;
55 
56 /**
57  * MemoryTreeTablePanel
58  *
59  * @since : 2021/10/25
60  */
61 public class MemoryTreeTablePanel extends JBPanel {
62     private static final Logger LOGGER = LogManager.getLogger(MemoryTreeTablePanel.class);
63     private static final int FEATURES_WIDTH = 1520;
64 
65     private static final int NUM_5 = 5;
66     private static final int NUM_8 = 8;
67 
68     private MemoryAgentHeapInfoPanel memoryAgentHeapInfoPanel;
69 
70     /**
71      * MemoryTreeTablePanel
72      *
73      * @param memoryItemView memoryItemView
74      * @param sessionId sessionId
75      * @param chartName chartName
76      */
MemoryTreeTablePanel(MemoryItemView memoryItemView, long sessionId, String chartName)77     public MemoryTreeTablePanel(MemoryItemView memoryItemView, long sessionId, String chartName) {
78         if (ProfilerLogManager.isInfoEnabled()) {
79             LOGGER.info("MemoryTreeTablePanel");
80         }
81         this.setOpaque(true);
82         this.setLayout(new BorderLayout());
83         // leftTab
84         JBLabel leftTab = new JBLabel("Table");
85         leftTab.setBorder(BorderFactory
86             .createEmptyBorder(LayoutConstants.NUM_2, LayoutConstants.RECORD_BORDER_SPACE, LayoutConstants.NUM_2, 0));
87         leftTab.setOpaque(false);
88         leftTab.setPreferredSize(new Dimension(LayoutConstants.JPA_LABEL_WIDTH, LayoutConstants.DEVICES_HEIGHT));
89         Font font = new Font(Font.DIALOG, Font.PLAIN, LayoutConstants.FONT_SIZE);
90         leftTab.setFont(font);
91         leftTab.setBounds(LayoutConstants.RECORD_BORDER_SPACE, LayoutConstants.NUM_2,
92             LayoutConstants.RECORD_TABBED_BOUNDS_WIDTH, LayoutConstants.NUM_20);
93         // TAB
94         JBTabbedPane jbTabbedPane = new JBTabbedPane();
95         jbTabbedPane.setBorder(
96             BorderFactory.createEmptyBorder(LayoutConstants.NUM_2, LayoutConstants.NUM_20, LayoutConstants.NUM_2, 0));
97         // tableTab
98         JBPanel tableTab = createTableTab(memoryItemView, sessionId, chartName);
99         tableTab.setBorder(BorderFactory.createEmptyBorder(NUM_8, 0, NUM_8, 0));
100         // Custom jbTabbedPane
101         jbTabbedPane.addTab("", tableTab);
102         jbTabbedPane.setTabComponentAt(jbTabbedPane.indexOfComponent(tableTab), leftTab);
103         // rightTab
104         JBLabel rightTab = new JBLabel("Visualization");
105         rightTab.setBorder(BorderFactory
106             .createEmptyBorder(LayoutConstants.NUM_2, LayoutConstants.RECORD_TABBED_BORDER, LayoutConstants.NUM_2, 0));
107         rightTab.setOpaque(false);
108         rightTab.setPreferredSize(new Dimension(LayoutConstants.JPA_LABEL_WIDTH, LayoutConstants.DEVICES_HEIGHT));
109         rightTab.setFont(font);
110         rightTab.setBounds(LayoutConstants.RECORD_TABBED_BOUNDS_POINT, LayoutConstants.NUM_2,
111             LayoutConstants.RECORD_TABBED_BOUNDS_WIDTH, LayoutConstants.NUM_20);
112         // viewTab
113         JBPanel viewTab = createViewTab();
114         viewTab.setBorder(BorderFactory.createEmptyBorder(NUM_8, 0, NUM_8, 0));
115         // Custom jbTabbedPane
116         if (IS_DEVELOP_MODE) {
117             jbTabbedPane.addTab("", viewTab);
118             jbTabbedPane.setTabComponentAt(jbTabbedPane.indexOfComponent(viewTab), rightTab);
119         }
120         this.add(jbTabbedPane, BorderLayout.CENTER);
121         // Set the label panel changeListener
122         jbTabbedPane.addChangeListener(new ChangeListener() {
123             @Override
124             public void stateChanged(ChangeEvent event) {
125             }
126         });
127     }
128 
createTableTab(MemoryItemView memoryItemView, long sessionId, String chartName)129     private JBPanel createTableTab(MemoryItemView memoryItemView, long sessionId, String chartName) {
130         if (ProfilerLogManager.isInfoEnabled()) {
131             LOGGER.info("createTableTab");
132         }
133         JBPanel tablePanel = new JBPanel(new MigLayout("insets 0"));
134         tablePanel.setBorder(BorderFactory.createEmptyBorder(NUM_5, 0, NUM_5, 0));
135         tablePanel.setOpaque(true);
136 
137         // itemViewBox
138         List<String> itemViewBox = new ArrayList<>();
139         itemViewBox.add("View app heaps");
140 
141         // itemViewBox
142         List<String> itemArraysBox = new ArrayList<>();
143         itemArraysBox.add("Arrange by class");
144 
145         // Reserved Tree Table panel
146         memoryAgentHeapInfoPanel = new MemoryAgentHeapInfoPanel(memoryItemView, sessionId, chartName);
147         memoryAgentHeapInfoPanel.setOpaque(true);
148         memoryAgentHeapInfoPanel.setBackground(JBColor.background().brighter());
149 
150         // add to table Tab Options panel
151         tablePanel.add(createHeapFeatures(itemViewBox, itemArraysBox), "wrap");
152         tablePanel.add(memoryAgentHeapInfoPanel, "dock south");
153 
154         return tablePanel;
155     }
156 
createViewTab()157     private JBPanel createViewTab() {
158         if (ProfilerLogManager.isInfoEnabled()) {
159             LOGGER.info("createViewTab");
160         }
161         JBPanel viewPanel = new JBPanel(new BorderLayout());
162         viewPanel.setBorder(BorderFactory.createEmptyBorder(NUM_5, 0, NUM_5, 0));
163         viewPanel.setOpaque(true);
164 
165         List<String> itemBox = new ArrayList<>();
166         itemBox.add("View all heaps");
167         itemBox.add("View app heaps");
168         itemBox.add("View zygote heaps");
169         itemBox.add("View image heaps");
170         itemBox.add("View JNI heaps");
171 
172         // Reserved Tree Table panel
173         JBPanel recordTable = new JBPanel();
174         recordTable.setOpaque(true);
175         recordTable.setBorder(BorderFactory.createEmptyBorder(NUM_5, 0, 0, 0));
176 
177         // add to table Tab Options panel
178         viewPanel.add(createHeapFeatures(itemBox, itemBox), BorderLayout.NORTH);
179         viewPanel.add(recordTable, BorderLayout.CENTER);
180 
181         return viewPanel;
182     }
183 
createHeapFeatures(List<String> itemViewBox, List<String> itemArrangeBox)184     private JBPanel createHeapFeatures(List<String> itemViewBox, List<String> itemArrangeBox) {
185         if (ProfilerLogManager.isInfoEnabled()) {
186             LOGGER.info("createHeapFeatures");
187         }
188         // tableFeatures
189         JBPanel tableFeatures = new JBPanel();
190         tableFeatures.setOpaque(false);
191         tableFeatures.setPreferredSize(new Dimension(FEATURES_WIDTH, LayoutConstants.RECORD_FEATURES_HEIGHT));
192         tableFeatures.setBackground(JBColor.background().darker());
193         tableFeatures.setBorder(BorderFactory.createEmptyBorder(NUM_8, 0, NUM_8, 0));
194         tableFeatures.setLayout(new MigLayout("insets 0"));
195         tableFeatures.setBorder(BorderFactory.createEmptyBorder(NUM_8, 0, NUM_8, 0));
196 
197         // tableFeatures add itemViewBox
198         CustomComboBox viewBox = new CustomComboBox();
199         viewBox.setName(UtConstant.UT_MEMORY_TREE_TABLE_VIEW);
200         viewBox.setUI(new CustomJBComboBoxUI());
201         viewBox.setBorder(BorderFactory.createLineBorder(ColorConstants.NATIVE_RECORD_BORDER, 1));
202         viewBox.setPreferredSize(
203             new Dimension(LayoutConstants.RECORD_COMBO_BOX_WIDTH, LayoutConstants.RECORD_SEARCH_HEIGHT));
204         for (String item : itemViewBox) {
205             viewBox.addItem(item);
206         }
207         viewBox.setSelectedIndex(0);
208         tableFeatures.add(viewBox);
209 
210         // tableFeatures add itemArrangeBox
211         CustomComboBox arrangeBox = new CustomComboBox();
212         arrangeBox.setName(UtConstant.UT_MEMORY_TREE_TABLE_ARRANGE);
213         arrangeBox.setUI(new CustomJBComboBoxUI());
214         arrangeBox.setBorder(BorderFactory.createLineBorder(ColorConstants.NATIVE_RECORD_BORDER, 1));
215         arrangeBox.setPreferredSize(
216             new Dimension(LayoutConstants.RECORD_COMBO_BOX_WIDTH, LayoutConstants.RECORD_SEARCH_HEIGHT));
217         for (String item : itemArrangeBox) {
218             arrangeBox.addItem(item);
219         }
220         arrangeBox.setSelectedIndex(0);
221         tableFeatures.add(arrangeBox);
222 
223         JBPanel searchPanel = new JBPanel();
224         searchPanel.setOpaque(true);
225         searchPanel.setLayout(new BorderLayout());
226 
227         // tableFeatures Search
228         CustomJBTextField search = new CustomJBTextField();
229         search.setBorder(BorderFactory.createLineBorder(ColorConstants.NATIVE_RECORD_BORDER, 1));
230         search.setText("Search");
231         search
232             .setPreferredSize(new Dimension(LayoutConstants.RECORD_SEARCH_WIDTH, LayoutConstants.RECORD_SEARCH_HEIGHT));
233         addSearchListener(search);
234         searchPanel.add(search, BorderLayout.WEST);
235 
236         tableFeatures.add(searchPanel, "wrap");
237         return tableFeatures;
238     }
239 
addSearchListener(CustomJBTextField search)240     private void addSearchListener(CustomJBTextField search) {
241         search.addFocusListener(new FocusListener() {
242             @Override
243             public void focusGained(FocusEvent focusEvent) {
244                 if ("Search".equals(search.getText())) {
245                     search.setText("");
246                     memoryAgentHeapInfoPanel.getTreeTable().getVerticalScrollBar()
247                         .removeMouseMotionListener(memoryAgentHeapInfoPanel.getMouseMotionAdapter());
248                 }
249             }
250 
251             @Override
252             public void focusLost(FocusEvent focusEvent) {
253                 if (search.getText().length() < 1) {
254                     search.setText("Search");
255                     memoryAgentHeapInfoPanel.getTreeTable().getVerticalScrollBar()
256                         .addMouseMotionListener(memoryAgentHeapInfoPanel.getMouseMotionAdapter());
257                 }
258             }
259         });
260         search.getDocument().addDocumentListener(new DocumentListener() {
261             @Override
262             public void insertUpdate(DocumentEvent event) {
263                 searchInsertUpdate(search);
264             }
265 
266             @Override
267             public void removeUpdate(DocumentEvent event) {
268                 // search
269                 searchRemoveUpdate(search);
270             }
271 
272             /**
273              * Gives notification that an attribute or set of attributes changed.
274              *
275              * @param documentEvent the document event
276              */
277             @Override
278             public void changedUpdate(DocumentEvent documentEvent) {
279             }
280         });
281     }
282 
283     /**
284      * searchRemoveUpdate
285      *
286      * @param search search
287      */
searchRemoveUpdate(CustomJBTextField search)288     public void searchRemoveUpdate(CustomJBTextField search) {
289         String text = search.getText();
290         ExpandTreeTable treeTable = memoryAgentHeapInfoPanel.getTreeTable();
291         TreeTableModel model = treeTable.getModel();
292         if (model instanceof ListTreeTableModelOnColumns) {
293             SwingUtilities.invokeLater(new Runnable() {
294                 @Override
295                 public void run() {
296                     ListTreeTableModelOnColumns tableModel = (ListTreeTableModelOnColumns) model;
297                     DefaultMutableTreeNode root = null;
298                     Object tableModelRoot = tableModel.getRoot();
299                     if (tableModelRoot instanceof DefaultMutableTreeNode) {
300                         root = (DefaultMutableTreeNode) tableModelRoot;
301                         List<AgentHeapBean> datas = memoryAgentHeapInfoPanel.getAllAgentDatas().stream()
302                             .filter(agentDataNode -> agentDataNode.getAgentClazzName().contains(text))
303                             .collect(Collectors.toList());
304                         root.removeAllChildren();
305                         int totalAllocations = 0;
306                         int totalDeallocations = 0;
307                         int totalTotalCount = 0;
308                         long totalShallowSize = 0L;
309                         for (AgentHeapBean agentHeapBean : datas) {
310                             totalAllocations = totalAllocations + agentHeapBean.getAgentAllocationsCount();
311                             totalDeallocations = totalDeallocations + agentHeapBean.getAgentDeAllocationsCount();
312                             totalTotalCount = totalTotalCount + agentHeapBean.getAgentTotalInstanceCount();
313                             totalShallowSize = totalShallowSize + agentHeapBean.getAgentTotalshallowSize();
314                             root.add(new DefaultMutableTreeNode(agentHeapBean));
315                         }
316                         AgentHeapBean userObject = null;
317                         Object rootUserObject = root.getUserObject();
318                         if (rootUserObject instanceof AgentHeapBean) {
319                             userObject = (AgentHeapBean) rootUserObject;
320                             userObject.setAgentAllocationsCount(totalAllocations);
321                             userObject.setAgentDeAllocationsCount(totalDeallocations);
322                             userObject.setAgentTotalInstanceCount(totalTotalCount);
323                             userObject.setAgentTotalshallowSize(totalShallowSize);
324                             root.setUserObject(userObject);
325                         }
326                     }
327                     tableModel.reload();
328                     memoryAgentHeapInfoPanel.getTreeTable().getVerticalScrollBar().setValue(0);
329                 }
330             });
331         }
332     }
333 
334     /**
335      * searchInsertUpdate
336      *
337      * @param search search
338      */
searchInsertUpdate(CustomJBTextField search)339     public void searchInsertUpdate(CustomJBTextField search) {
340         String text = search.getText();
341         ExpandTreeTable treeTable = memoryAgentHeapInfoPanel.getTreeTable();
342         TreeTableModel model = treeTable.getModel();
343         if (model instanceof ListTreeTableModelOnColumns) {
344             SwingUtilities.invokeLater(new Runnable() {
345                 @Override
346                 public void run() {
347                     ListTreeTableModelOnColumns tableModel = (ListTreeTableModelOnColumns) model;
348                     DefaultMutableTreeNode root = null;
349                     Object tableModelRoot = tableModel.getRoot();
350                     if (tableModelRoot instanceof DefaultMutableTreeNode) {
351                         root = (DefaultMutableTreeNode) tableModelRoot;
352                         List<AgentHeapBean> datas = memoryAgentHeapInfoPanel.getAllAgentDatas().stream()
353                             .filter(agentDataNode -> agentDataNode.getAgentClazzName().contains(text))
354                             .collect(Collectors.toList());
355                         root.removeAllChildren();
356                         int totalAllocations = 0;
357                         int totalDeallocations = 0;
358                         int totalTotalCount = 0;
359                         long totalShallowSize = 0L;
360                         for (AgentHeapBean agentHeapBean : datas) {
361                             totalAllocations = totalAllocations + agentHeapBean.getAgentAllocationsCount();
362                             totalDeallocations = totalDeallocations + agentHeapBean.getAgentDeAllocationsCount();
363                             totalTotalCount = totalTotalCount + agentHeapBean.getAgentTotalInstanceCount();
364                             totalShallowSize = totalShallowSize + agentHeapBean.getAgentTotalshallowSize();
365                             root.add(new DefaultMutableTreeNode(agentHeapBean));
366                         }
367                         AgentHeapBean userObject = null;
368                         Object rootUserObject = root.getUserObject();
369                         if (rootUserObject instanceof AgentHeapBean) {
370                             userObject = (AgentHeapBean) rootUserObject;
371                             userObject.setAgentAllocationsCount(totalAllocations);
372                             userObject.setAgentDeAllocationsCount(totalDeallocations);
373                             userObject.setAgentTotalInstanceCount(totalTotalCount);
374                             userObject.setAgentTotalshallowSize(totalShallowSize);
375                             root.setUserObject(userObject);
376                         }
377                     }
378                     tableModel.reload();
379                     memoryAgentHeapInfoPanel.getTreeTable().getVerticalScrollBar().setValue(0);
380                 }
381             });
382         }
383     }
384 
getMemoryAgentHeapInfoPanel()385     public MemoryAgentHeapInfoPanel getMemoryAgentHeapInfoPanel() {
386         return memoryAgentHeapInfoPanel;
387     }
388 }
389