• 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.trace.fragment;
17 
18 import ohos.devtools.views.trace.Sql;
19 import ohos.devtools.views.trace.bean.FunctionBean;
20 import ohos.devtools.views.trace.bean.ThreadData;
21 import ohos.devtools.views.trace.component.AnalystPanel;
22 import ohos.devtools.views.trace.component.ContentPanel;
23 import ohos.devtools.views.trace.util.Db;
24 import ohos.devtools.views.trace.util.Utils;
25 import org.jetbrains.annotations.NotNull;
26 
27 import javax.swing.JComponent;
28 import javax.swing.SwingUtilities;
29 import java.awt.Graphics2D;
30 import java.awt.event.KeyEvent;
31 import java.awt.event.MouseEvent;
32 import java.awt.geom.Rectangle2D;
33 import java.util.ArrayList;
34 import java.util.List;
35 import java.util.Objects;
36 import java.util.concurrent.CompletableFuture;
37 
38 /**
39  * Thread data row
40  *
41  * @since 2021/04/22 12:25
42  */
43 public class ThreadDataFragment extends AbstractDataFragment<ThreadData> implements ThreadData.IEventListener {
44     /**
45      * graph event callback
46      */
47     protected static ThreadData currentSelectedThreadData;
48 
49     /**
50      * Thread object
51      */
52     public ThreadData thread;
53 
54     /**
55      * delayClickStartTime
56      */
57     public Long delayClickStartTime;
58 
59     /**
60      * delayClickProcessName
61      */
62     private String delayClickProcessName;
63 
64     private int x1;
65     private int x2;
66     private Rectangle2D bounds;
67     private boolean isLoading;
68     private boolean funcLoad = false;
69 
70     /**
71      * structure
72      *
73      * @param root root
74      * @param thread thread
75      */
ThreadDataFragment(JComponent root, ThreadData thread)76     public ThreadDataFragment(JComponent root, ThreadData thread) {
77         super(root, true, false);
78         this.thread = thread;
79         this.setRoot(root);
80     }
81 
82     /**
83      * getData
84      *
85      * @return List<ThreadData>
86      */
getData()87     public List<ThreadData> getData() {
88         return this.data;
89     }
90 
91     /**
92      * Drawing method
93      *
94      * @param graphics graphics
95      */
96     @Override
draw(Graphics2D graphics)97     public void draw(Graphics2D graphics) {
98         super.draw(graphics);
99 
100         // Supplement the information on the left
101         graphics.setColor(getRoot().getForeground());
102         String name = thread.getThreadName() + " " + thread.getTid();
103         bounds = graphics.getFontMetrics().getStringBounds(name, graphics);
104         double wordWidth = bounds.getWidth() / name.length(); // Width per character
105         double wordNum = (getDescRect().getWidth() - 40) / wordWidth;
106         if (bounds.getWidth() < getDescRect().getWidth() - 40) { // Direct line display
107             graphics.drawString(name, (int) (getDescRect().getX() + 10),
108                 (int) (getDescRect().getY() + bounds.getHeight() + 10));
109         } else {
110             String substring = name.substring((int) wordNum);
111             if (substring.length() < wordNum) {
112                 graphics.drawString(name.substring(0, (int) wordNum), (int) (getDescRect().getX() + 10),
113                     (int) (getDescRect().getY() + bounds.getHeight() + 8));
114                 graphics.drawString(substring, Utils.getX(getDescRect()) + 10,
115                     (int) (getDescRect().getY() + bounds.getHeight() * 2 + 8));
116             } else {
117                 graphics.drawString(name.substring(0, (int) wordNum), (int) (getDescRect().getX() + 10),
118                     (int) (getDescRect().getY() + bounds.getHeight() + 2));
119                 graphics.drawString(substring.substring(0, (int) wordNum), (int) (getDescRect().getX() + 10),
120                     (int) (getDescRect().getY() + bounds.getHeight() * 2 + 2));
121                 graphics.drawString(substring.substring((int) wordNum), (int) (getDescRect().getX() + 10),
122                     (int) (getDescRect().getY() + bounds.getHeight() * 3 + 2));
123             }
124         }
125         drawData(graphics);
126     }
127 
drawData(Graphics2D graphics)128     private void drawData(Graphics2D graphics) {
129         if (data != null) {
130             data.stream().filter(threadData -> threadData.getStartTime() + threadData.getDuration() > startNS
131                 && threadData.getStartTime() < endNS).forEach(threadData -> {
132                 if (threadData.getStartTime() < startNS) {
133                     x1 = getX(startNS);
134                 } else {
135                     x1 = getX(threadData.getStartTime());
136                 }
137                 if (threadData.getStartTime() + threadData.getDuration() > endNS) {
138                     x2 = getX(endNS);
139                 } else {
140                     x2 = getX(threadData.getStartTime() + threadData.getDuration());
141                 }
142                 threadData
143                     .setRect(x1 + Utils.getX(getDataRect()), Utils.getY(getDataRect()) + 5, x2 - x1 <= 0 ? 1 : x2 - x1,
144                         getDataRect().height - 10);
145                 threadData.root = getRoot();
146                 threadData.setEventListener(this);
147                 threadData.draw(graphics);
148             });
149         } else {
150             graphics.setColor(getRoot().getForeground());
151             graphics.drawString("Loading...", Utils.getX(getDataRect()), Utils.getY(getDataRect()) + 12);
152             loadData();
153         }
154     }
155 
156     /**
157      * Mouse clicked event
158      *
159      * @param event event
160      */
161     @Override
mouseClicked(MouseEvent event)162     public void mouseClicked(MouseEvent event) {
163         super.mouseClicked(event);
164         if (data != null) {
165             data.stream().filter(threadData -> threadData.getStartTime() + threadData.getDuration() > startNS
166                 && threadData.getStartTime() < endNS).filter(threadData -> threadData.edgeInspect(event)).findFirst()
167                 .ifPresent(threadData -> {
168                     threadData.setProcessName(thread.getProcessName());
169                     threadData.setThreadName(thread.getThreadName());
170                     threadData.onClick(event);
171                 });
172         }
173     }
174 
175     /**
176      * Mouse pressed event
177      *
178      * @param event event
179      */
180     @Override
mousePressed(MouseEvent event)181     public void mousePressed(MouseEvent event) {
182     }
183 
184     /**
185      * Mouse exited event
186      *
187      * @param event event
188      */
189     @Override
mouseExited(MouseEvent event)190     public void mouseExited(MouseEvent event) {
191     }
192 
193     /**
194      * Mouse entered event
195      *
196      * @param event event
197      */
198     @Override
mouseEntered(MouseEvent event)199     public void mouseEntered(MouseEvent event) {
200     }
201 
202     /**
203      * Mouse moved event
204      *
205      * @param evt event
206      */
207     @Override
mouseMoved(MouseEvent evt)208     public void mouseMoved(MouseEvent evt) {
209         MouseEvent event = getRealMouseEvent(evt);
210         super.mouseMoved(event);
211         clearFocus(event);
212         if (edgeInspect(event)) {
213             if (data != null) {
214                 data.stream().filter(threadData -> threadData.getStartTime() + threadData.getDuration() > startNS
215                     && threadData.getStartTime() < endNS).filter(threadData -> threadData.edgeInspect(event))
216                     .findFirst().ifPresent(filter -> {
217                     filter.onMouseMove(event);
218                     if (filter.edgeInspect(event)) {
219                         if (!filter.flagFocus) {
220                             filter.flagFocus = true;
221                             filter.onFocus(event);
222                         }
223                     } else {
224                         if (filter.flagFocus) {
225                             filter.flagFocus = false;
226                             filter.onBlur(event);
227                         }
228                     }
229                 });
230             }
231         }
232     }
233 
234     /**
235      * Mouse released event
236      *
237      * @param event event
238      */
239     @Override
mouseReleased(MouseEvent event)240     public void mouseReleased(MouseEvent event) {
241     }
242 
243     /**
244      * key released event
245      *
246      * @param event event
247      */
248     @Override
keyReleased(KeyEvent event)249     public void keyReleased(KeyEvent event) {
250     }
251 
loadData()252     private void loadData() {
253         if (!isLoading) {
254             isLoading = true;
255             CompletableFuture.runAsync(() -> {
256                 List<ThreadData> list = new ArrayList<>() {
257                 };
258                 Db.getInstance().query(st -> addStatement(st), Sql.SYS_QUERY_THREAD_DATA, list, thread.getTid());
259                 data = list;
260                 ArrayList<FunctionBean> functionBeans = new ArrayList<>() {
261                 };
262                 Db.getInstance()
263                     .query(st -> addStatement(st), Sql.SYS_GET_FUN_DATA_BY_TID, functionBeans, thread.getTid());
264                 SwingUtilities.invokeLater(() -> {
265                     isLoading = false;
266                     if (!functionBeans.isEmpty()) {
267                         if (!funcLoad) {
268                             funcLoad = true;
269                             int maxHeight =
270                                 (functionBeans.stream().mapToInt(bean -> bean.getDepth()).max().getAsInt() + 1) * 20;
271                             FunctionDataFragment functionDataFragment =
272                                 getFunctionDataFragment(functionBeans, maxHeight);
273                             if (this.getRoot() instanceof ContentPanel) {
274                                 ContentPanel contentPanel = (ContentPanel) this.getRoot();
275                                 int index = contentPanel.fragmentList.indexOf(this) + 1;
276                                 contentPanel.addDataFragment(index, functionDataFragment);
277                                 contentPanel.refresh();
278                             }
279                         } else {
280                             repaint();
281                         }
282                     } else {
283                         repaint();
284                     }
285                     if (delayClickStartTime != null) {
286                         data.stream().filter(it -> it.getStartTime() == delayClickStartTime).findFirst()
287                             .ifPresent(it -> {
288                                 it.setProcessName(delayClickProcessName);
289                                 click(null, it);
290                                 delayClickStartTime = null;
291                                 delayClickProcessName = null;
292                             });
293                     }
294                 });
295             }, Utils.getPool()).whenComplete((unused, throwable) -> {
296                 if (Objects.nonNull(throwable)) {
297                     throwable.printStackTrace();
298                 }
299             });
300         }
301     }
302 
303     @NotNull
getFunctionDataFragment(ArrayList<FunctionBean> functionBeans, int maxHeight)304     private FunctionDataFragment getFunctionDataFragment(ArrayList<FunctionBean> functionBeans, int maxHeight) {
305         FunctionDataFragment functionDataFragment =
306             new FunctionDataFragment(this.getRoot(), functionBeans);
307         functionDataFragment.parentUuid = this.parentUuid;
308         functionDataFragment.thread = this.thread;
309         functionDataFragment.defaultHeight = maxHeight + 20;
310         functionDataFragment.visible = true;
311         return functionDataFragment;
312     }
313 
314     /**
315      * click event
316      *
317      * @param event event
318      * @param data data
319      */
320     @Override
click(MouseEvent event, ThreadData data)321     public void click(MouseEvent event, ThreadData data) {
322         clearSelected();
323         data.select(true);
324         data.repaint();
325         currentSelectedThreadData = data;
326         if (AnalystPanel.iThreadDataClick != null) {
327             AnalystPanel.iThreadDataClick.click(data);
328         }
329     }
330 
331     /**
332      * Mouse blur event
333      *
334      * @param event event
335      * @param data data
336      */
337     @Override
blur(MouseEvent event, ThreadData data)338     public void blur(MouseEvent event, ThreadData data) {
339     }
340 
341     /**
342      * Mouse focus event
343      *
344      * @param event event
345      * @param data data
346      */
347     @Override
focus(MouseEvent event, ThreadData data)348     public void focus(MouseEvent event, ThreadData data) {
349     }
350 
351     /**
352      * Mouse move event
353      *
354      * @param event event
355      * @param data data
356      */
357     @Override
mouseMove(MouseEvent event, ThreadData data)358     public void mouseMove(MouseEvent event, ThreadData data) {
359         getRoot().repaint();
360     }
361 
getDelayClickProcessName()362     public String getDelayClickProcessName() {
363         return delayClickProcessName;
364     }
365 
setDelayClickProcessName(String delayClickProcessName)366     public void setDelayClickProcessName(String delayClickProcessName) {
367         this.delayClickProcessName = delayClickProcessName;
368     }
369 }
370