• 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;
17 
18 import com.intellij.icons.AllIcons;
19 import com.intellij.ui.JBColor;
20 import com.intellij.ui.components.JBLabel;
21 import com.intellij.ui.components.JBPanel;
22 import com.intellij.util.Consumer;
23 import net.miginfocom.swing.MigLayout;
24 import ohos.devtools.views.applicationtrace.bean.Cpu;
25 import ohos.devtools.views.applicationtrace.bean.CpuFreq;
26 import ohos.devtools.views.applicationtrace.bean.Frame;
27 import ohos.devtools.views.applicationtrace.bean.Func;
28 import ohos.devtools.views.applicationtrace.bean.Thread;
29 import ohos.devtools.views.applicationtrace.bean.VsyncAppBean;
30 import ohos.devtools.views.applicationtrace.util.TimeUtils;
31 import ohos.devtools.views.distributed.bean.DistributedFuncBean;
32 import ohos.devtools.views.distributed.util.DistributedCommon;
33 import ohos.devtools.views.perftrace.bean.PrefFunc;
34 
35 import javax.swing.Icon;
36 import javax.swing.JButton;
37 import java.awt.Color;
38 import java.awt.Dimension;
39 import java.awt.Graphics;
40 import java.awt.Point;
41 import java.awt.Rectangle;
42 import java.awt.event.ComponentAdapter;
43 import java.awt.event.ComponentEvent;
44 import java.awt.event.MouseEvent;
45 import java.util.Objects;
46 import java.util.concurrent.atomic.AtomicBoolean;
47 
48 /**
49  * AbstractRow
50  *
51  * @since 2021/5/20 15:50
52  */
53 public abstract class AbstractRow extends JBPanel {
54     /**
55      * current row content JBPanel
56      */
57     public JBPanel content;
58 
59     /**
60      * current row startNS
61      */
62     protected long startNS;
63 
64     /**
65      * current row endNS
66      */
67     protected long endNS;
68 
69     /**
70      * current row isLoading
71      */
72     protected AtomicBoolean isLoading = new AtomicBoolean(false);
73 
74     /**
75      * current row MigLayout layout
76      */
77     protected MigLayout layout = new MigLayout("inset 0", "0[110!,left]0[grow,fill]0", "0[grow,fill,center]0");
78 
79     /**
80      * current row JBLabel nameLabel
81      */
82     protected JBLabel nameLabel = new JBLabel();
83 
84     /**
85      * current row MouseEvent Consumer nameLabelClickConsumer
86      */
87     protected Consumer<MouseEvent> nameLabelClickConsumer;
88 
89     /**
90      * current row JButton expandBtn
91      */
92     protected JButton expandBtn = new JButton();
93 
94     private Icon myExpandIcon = AllIcons.General.ArrowRight;
95     private Icon myCollapseIcon = AllIcons.General.ArrowDown;
96     private boolean myIsInitialized;
97     private boolean myIsCollapsed;
98     private int threadHeight = 14;
99     private int funcHeight = 20;
100     private int maxDept = 1;
101     private final String rowName;
102     private final int collapsedNodeHeight = 1;
103 
104     /**
105      * fresh the Notify data by startNS and endNS
106      *
107      * @param name name
108      * @param hasExpand hasExpand
109      * @param defaultExpand defaultExpand
110      */
AbstractRow(String name, boolean hasExpand, boolean defaultExpand)111     public AbstractRow(String name, boolean hasExpand, boolean defaultExpand) {
112         this.rowName = name;
113         setLayout(layout);
114         expandBtn.setBorderPainted(false);
115         expandBtn.setContentAreaFilled(false);
116         expandBtn.setBackground(new Color(0, 0, 0, 0));
117         expandBtn.setMaximumSize(new Dimension(myExpandIcon.getIconWidth(), myExpandIcon.getIconHeight()));
118         expandBtn.setFocusable(true);
119         nameLabel.setText(name);
120         if (hasExpand) {
121             add(expandBtn, "split 2,w 5!,gapleft 15,gapright 5");
122             add(nameLabel, "gapleft 10,w 80!");
123         } else {
124             add(nameLabel, "gapleft 15,w 90!");
125         }
126         content = new JBPanel() {
127             @Override
128             protected void paintComponent(Graphics graphics) {
129                 super.paintComponent(graphics);
130                 contentPaint(graphics);
131             }
132         };
133         content.setBackground(JBColor.background().darker());
134         add(content, "growx,pushx");
135         setCollapsed(!defaultExpand);
136         expandBtn.addActionListener(event -> setCollapsed(!myIsCollapsed));
137     }
138 
139     /**
140      * isCollapsed
141      *
142      * @return isCollapsed
143      */
isCollapsed()144     public boolean isCollapsed() {
145         return myIsCollapsed;
146     }
147 
148     /**
149      * getStartNS
150      *
151      * @return long startNS
152      */
getStartNS()153     public long getStartNS() {
154         return startNS;
155     }
156 
157     /**
158      * getEndNS
159      *
160      * @return long endNS
161      */
getEndNS()162     public long getEndNS() {
163         return endNS;
164     }
165 
166     /**
167      * get Row Name
168      *
169      * @return String rowName
170      */
getRowName()171     public String getRowName() {
172         return rowName;
173     }
174 
175     /**
176      * fresh the row data by startNS and endNS
177      *
178      * @param startNS startNS
179      * @param endNS endNS
180      */
refresh(long startNS, long endNS)181     public void refresh(long startNS, long endNS) {
182         this.startNS = startNS;
183         this.endNS = endNS;
184         content.repaint();
185         refreshNotify();
186     }
187 
188     /**
189      * fresh the Notify data by startNS and endNS
190      */
refreshNotify()191     public void refreshNotify() {
192         long time = endNS + startNS;
193     }
194 
195     /**
196      * fresh the Notify data by startNS and endNS
197      *
198      * @return return the Rectangle from the content
199      */
getContentBounds()200     public Rectangle getContentBounds() {
201         return content.getBounds();
202     }
203 
204     /**
205      * get the max height
206      *
207      * @return return the max height
208      */
evalHeight()209     protected int evalHeight() {
210         int maxHeight = maxDept * getFuncHeight() + getFuncHeight();
211         if (maxHeight < 30) {
212             maxHeight = 30;
213         }
214         return maxHeight;
215     }
216 
217     /**
218      * Set whether to expand
219      *
220      * @param isCollapsed isCollapsed
221      */
setCollapsed(boolean isCollapsed)222     public void setCollapsed(boolean isCollapsed) {
223         setCollapsed(isCollapsed, null);
224     }
225 
226     /**
227      * Set whether to expand
228      *
229      * @param isCollapsed isCollapsed
230      * @param finish null
231      */
setCollapsed(boolean isCollapsed, Consumer<Rectangle> finish)232     public void setCollapsed(boolean isCollapsed, Consumer<Rectangle> finish) {
233         int defHeight = getBounds().height;
234         if (Objects.nonNull(finish)) {
235             addComponentListener(new ComponentAdapter() {
236                 @Override
237                 public void componentResized(ComponentEvent event) {
238                     super.componentResized(event);
239                     if (defHeight != event.getComponent().getBounds().height) {
240                         finish.consume(event.getComponent().getBounds());
241                     }
242                 }
243             });
244         }
245         try {
246             if (isCollapsed) {
247                 setFuncHeight(collapsedNodeHeight);
248                 setThreadHeight(collapsedNodeHeight);
249             } else {
250                 setFuncHeight(20);
251                 setThreadHeight(14);
252             }
253             if (getParent() != null && getParent().getLayout() instanceof MigLayout) {
254                 MigLayout migLayout = (MigLayout) getParent().getLayout();
255                 migLayout.setComponentConstraints(this, "growx,pushx,h " + evalHeight() + "!");
256             }
257             myIsCollapsed = isCollapsed;
258             Icon icon = myIsCollapsed ? myExpandIcon : myCollapseIcon;
259             if (icon != null) {
260                 expandBtn.setIcon(icon);
261                 expandBtn.setBorder(null);
262                 expandBtn.setBorderPainted(false);
263             }
264             if (isCollapsed) {
265                 expandBtn.requestFocusInWindow();
266                 expandBtn.setSelected(true);
267             } else {
268                 content.requestFocusInWindow();
269             }
270             revalidate();
271             repaint();
272         } finally {
273             myIsInitialized = true;
274         }
275     }
276 
277     /**
278      * get the threadHeight
279      *
280      * @return return the current threadHeight
281      */
getThreadHeight()282     public int getThreadHeight() {
283         return threadHeight;
284     }
285 
286     /**
287      * set the threadHeight
288      *
289      * @param threadHeight threadHeight
290      */
setThreadHeight(int threadHeight)291     public void setThreadHeight(int threadHeight) {
292         this.threadHeight = threadHeight;
293     }
294 
295     /**
296      * get the FuncHeight
297      *
298      * @return return the current FuncHeight
299      */
getFuncHeight()300     public int getFuncHeight() {
301         return funcHeight;
302     }
303 
304     /**
305      * set the FuncHeight
306      *
307      * @param funcHeight funcHeight
308      */
setFuncHeight(int funcHeight)309     public void setFuncHeight(int funcHeight) {
310         this.funcHeight = funcHeight;
311     }
312 
313     /**
314      * get the Name
315      *
316      * @return return the current nameLabel text
317      */
getName()318     public String getName() {
319         return nameLabel.getText();
320     }
321 
322     /**
323      * contentPaint paint content
324      *
325      * @param graphics graphics
326      */
contentPaint(Graphics graphics)327     public abstract void contentPaint(Graphics graphics);
328 
329     /**
330      * load data
331      */
loadData()332     public abstract void loadData();
333 
334     /**
335      * set the Point
336      *
337      * @param point point
338      */
mouseMoveHandler(Point point)339     public void mouseMoveHandler(Point point) {
340         super.getName();
341     }
342 
343     /**
344      * get the time by x Coordinates
345      *
346      * @param xCoordinates xCoordinates
347      * @return time string
348      */
getTimeByX(int xCoordinates)349     public String getTimeByX(int xCoordinates) {
350         double width = (getEndNS() - getStartNS()) * xCoordinates * 1.0 / getContentBounds().getWidth();
351         return TimeUtils.getTimeFormatString((long) width + getStartNS());
352     }
353 
354     /**
355      * get the func is in this row
356      *
357      * @param func func
358      * @return return the row is contains func
359      */
contains(Func func)360     public boolean contains(Func func) {
361         return func.getStartTs() + func.getDur() > getStartNS() && func.getStartTs() < getEndNS();
362     }
363 
364     /**
365      * get the threadData is in this row
366      *
367      * @param threadData threadData
368      * @return return the row is contains threadData
369      */
contains(Thread threadData)370     public boolean contains(Thread threadData) {
371         return threadData.getStartTime() + threadData.getDuration() > getStartNS()
372             && threadData.getStartTime() < getEndNS();
373     }
374 
375     /**
376      * get the cpu is in this row
377      *
378      * @param cpu cpu
379      * @return return the row is contains Cpu
380      */
contains(Cpu cpu)381     public boolean contains(Cpu cpu) {
382         return cpu.getStartTime() + cpu.getDuration() > getStartNS() && cpu.getStartTime() < getEndNS();
383     }
384 
385     /**
386      * get the CpuFreq is in this row
387      *
388      * @param item item
389      * @return return the row is contains CpuFreq
390      */
contains(CpuFreq item)391     public boolean contains(CpuFreq item) {
392         return item.getStartTime() + item.getDuration() > getStartNS() && item.getStartTime() < getEndNS();
393     }
394 
395     /**
396      * get the VsyncAppBean is in this row
397      *
398      * @param item item
399      * @return return the row is contains VsyncAppBean
400      */
contains(VsyncAppBean item)401     public boolean contains(VsyncAppBean item) {
402         return item.getStartTime() + item.getDuration() > getStartNS() && item.getStartTime() < getEndNS();
403     }
404 
405     /**
406      * get the Frame is in this row
407      *
408      * @param item item
409      * @return return the row is contains Frame
410      */
contains(Frame item)411     public boolean contains(Frame item) {
412         return item.getStartNs() + item.getDur() > getStartNS() && item.getStartNs() < getEndNS();
413     }
414 
415     /**
416      * get the PrefFunc is in this row
417      *
418      * @param func func
419      * @return return the row is contains PrefFunc
420      */
contains(PrefFunc func)421     public boolean contains(PrefFunc func) {
422         return func.getEndTs() > getStartNS() && func.getStartTs() < getEndNS();
423     }
424 
425     /**
426      * get the PrefFunc is in this row
427      *
428      * @param func func
429      * @return return the row is contains PrefFunc
430      */
contains(DistributedFuncBean func)431     public boolean contains(DistributedFuncBean func) {
432         return func.getEndTs() > getStartNS() && func.getStartTs() < getEndNS();
433     }
434 
435     /**
436      * get the Object is in this row
437      *
438      * @param obj obj
439      * @return return the row is contains obj
440      */
contains(Object obj)441     public boolean contains(Object obj) {
442         if (obj instanceof PrefFunc) {
443             return contains((PrefFunc) obj);
444         } else if (obj instanceof CpuFreq) {
445             return contains((CpuFreq) obj);
446         } else if (obj instanceof Cpu) {
447             return contains((Cpu) obj);
448         } else if (obj instanceof Thread) {
449             return contains((Thread) obj);
450         } else if (obj instanceof Func) {
451             return contains((Func) obj);
452         } else if (obj instanceof VsyncAppBean) {
453             return contains((VsyncAppBean) obj);
454         } else if (obj instanceof Frame) {
455             return contains((Frame) obj);
456         } else if (obj instanceof DistributedFuncBean) {
457             return contains((DistributedFuncBean) obj);
458         } else {
459             return false;
460         }
461     }
462 
463     /**
464      * get the Rectangle by Cpu node
465      *
466      * @param node node
467      * @param padding Rectangle padding
468      * @return return Rectangle
469      */
getRectByNode(Cpu node, int padding)470     public Rectangle getRectByNode(Cpu node, int padding) {
471         double x1;
472         double x2;
473         if (node.getStartTime() < getStartNS()) {
474             x1 = 0;
475         } else {
476             x1 = Common.ns2x(node.getStartTime(), getContentBounds());
477         }
478         if (node.getStartTime() + node.getDuration() > getEndNS()) {
479             x2 = getContentBounds().getWidth();
480         } else {
481             x2 = Common.ns2x(node.getStartTime() + node.getDuration(), getContentBounds());
482         }
483         double getV = x2 - x1 <= 1 ? 1 : x2 - x1;
484         return new Rectangle((int) x1, (int) (getContentBounds().getY() + padding), (int) getV,
485             (int) (getContentBounds().getHeight() - padding * 2));
486     }
487 
488     /**
489      * get the Rectangle by Thread node
490      *
491      * @param node node
492      * @param height Rectangle height
493      * @return return Rectangle
494      */
getRectByNode(Thread node, int height)495     public Rectangle getRectByNode(Thread node, int height) {
496         double x1;
497         double x2;
498         if (node.getStartTime() < getStartNS()) {
499             x1 = Common.ns2x(getStartNS(), getContentBounds());
500         } else {
501             x1 = Common.ns2x(node.getStartTime(), getContentBounds());
502         }
503         if (node.getStartTime() + node.getDuration() > getEndNS()) {
504             x2 = Common.ns2x(getEndNS(), getContentBounds());
505         } else {
506             x2 = Common.ns2x(node.getStartTime() + node.getDuration(), getContentBounds());
507         }
508         double getV = x2 - x1 <= 1 ? 1 : x2 - x1;
509         return new Rectangle((int) x1, (int) (getContentBounds().getY()), (int) getV, height);
510     }
511 
512     /**
513      * get the Rectangle by PrefFunc node
514      *
515      * @param node node
516      * @param height Rectangle height
517      * @param paddingTop Rectangle paddingTop
518      * @return return Rectangle
519      */
getRectByNode(PrefFunc node, int paddingTop, int height)520     public Rectangle getRectByNode(PrefFunc node, int paddingTop, int height) {
521         double x1;
522         double x2;
523         if (node.getStartTs() < getStartNS()) {
524             x1 = Common.ns2x(getStartNS(), getContentBounds());
525         } else {
526             x1 = Common.ns2x(node.getStartTs(), getContentBounds());
527         }
528         if (node.getEndTs() > getEndNS()) {
529             x2 = Common.ns2x(getEndNS(), getContentBounds());
530         } else {
531             x2 = Common.ns2x(node.getEndTs(), getContentBounds());
532         }
533         double getV = x2 - x1 <= 1 ? 1 : x2 - x1;
534         return new Rectangle((int) x1, (int) (getContentBounds().getY() + node.getDepth() * height + paddingTop),
535             (int) getV, height);
536     }
537 
538     /**
539      * get the Rectangle by Func node
540      *
541      * @param node node
542      * @param height Rectangle height
543      * @param paddingTop Rectangle paddingTop
544      * @return return Rectangle
545      */
getRectByNode(Func node, int paddingTop, int height)546     public Rectangle getRectByNode(Func node, int paddingTop, int height) {
547         double x1;
548         double x2;
549         if (node.getStartTs() < getStartNS()) {
550             x1 = Common.ns2x(getStartNS(), getContentBounds());
551         } else {
552             x1 = Common.ns2x(node.getStartTs(), getContentBounds());
553         }
554         if (node.getStartTs() + node.getDur() > getEndNS()) {
555             x2 = Common.ns2x(getEndNS(), getContentBounds());
556         } else {
557             x2 = Common.ns2x(node.getStartTs() + node.getDur(), getContentBounds());
558         }
559         double getV = x2 - x1 <= 1 ? 1 : x2 - x1;
560         return new Rectangle((int) x1, (int) (getContentBounds().getY() + node.getDepth() * height + paddingTop),
561             (int) getV, height);
562     }
563 
564     /**
565      * get the Rectangle by FuncBean node
566      *
567      * @param node node
568      * @param height Rectangle height
569      * @param paddingTop Rectangle paddingTop
570      * @return return Rectangle
571      */
getRectByNode(DistributedFuncBean node, int paddingTop, int height)572     public Rectangle getRectByNode(DistributedFuncBean node, int paddingTop, int height) {
573         double x1;
574         double x2;
575         if (node.getStartTs() < getStartNS()) {
576             x1 = DistributedCommon.ns2x(getStartNS(), getContentBounds());
577         } else {
578             x1 = DistributedCommon.ns2x(node.getStartTs(), getContentBounds());
579         }
580         if (node.getStartTs() + node.getDur() > getEndNS()) {
581             x2 = DistributedCommon.ns2x(getEndNS(), getContentBounds());
582         } else {
583             x2 = DistributedCommon.ns2x(node.getStartTs() + node.getDur(), getContentBounds());
584         }
585         double getV = x2 - x1 <= 1 ? 1 : x2 - x1;
586         return new Rectangle((int) x1, (int) (getContentBounds().getY() + node.getDepth() * height + paddingTop),
587             (int) getV, height);
588     }
589 
590     /**
591      * get the Rectangle by CpuFreq node
592      *
593      * @param node node
594      * @return return Rectangle
595      */
getRectByNode(CpuFreq node)596     public Rectangle getRectByNode(CpuFreq node) {
597         double x1;
598         double x2;
599         if (node.getStartTime() < getStartNS()) {
600             x1 = Common.ns2x(getStartNS(), getContentBounds());
601         } else {
602             x1 = Common.ns2x(node.getStartTime(), getContentBounds());
603         }
604         if (node.getStartTime() + node.getDuration() > getEndNS()) {
605             x2 = Common.ns2x(getEndNS(), getContentBounds());
606         } else {
607             x2 = Common.ns2x(node.getStartTime() + node.getDuration(), getContentBounds());
608         }
609         double getV = x2 - x1 <= 1 ? 1 : x2 - x1;
610         return new Rectangle((int) x1, (int) (getContentBounds().getY()), (int) getV, getContentBounds().height);
611     }
612 
613     /**
614      * get the Rectangle by VsyncAppBean node
615      *
616      * @param node node
617      * @return return Rectangle
618      */
getRectByNode(VsyncAppBean node)619     public Rectangle getRectByNode(VsyncAppBean node) {
620         double x1;
621         double x2;
622         if (node.getStartTime() < getStartNS()) {
623             x1 = Common.ns2x(getStartNS(), getContentBounds());
624         } else {
625             x1 = Common.ns2x(node.getStartTime(), getContentBounds());
626         }
627         if (node.getStartTime() + node.getDuration() > getEndNS()) {
628             x2 = Common.ns2x(getEndNS(), getContentBounds());
629         } else {
630             x2 = Common.ns2x(node.getStartTime() + node.getDuration(), getContentBounds());
631         }
632         double getV = x2 - x1 <= 1 ? 1 : x2 - x1;
633         return new Rectangle((int) x1, (int) (getContentBounds().getY()), (int) getV, getContentBounds().height);
634     }
635 
636     /**
637      * get the Rectangle by Frame node
638      *
639      * @param node node
640      * @param height Rectangle height
641      * @return return Rectangle
642      */
getRectByNode(Frame node, int height)643     public Rectangle getRectByNode(Frame node, int height) {
644         double x1;
645         double x2;
646         if (node.getStartNs() < getStartNS()) {
647             x1 = Common.ns2x(getStartNS(), getContentBounds());
648         } else {
649             x1 = Common.ns2x(node.getStartNs(), getContentBounds());
650         }
651         if (node.getStartNs() + node.getDur() > getEndNS()) {
652             x2 = Common.ns2x(getEndNS(), getContentBounds());
653         } else {
654             x2 = Common.ns2x(node.getStartNs() + node.getDur(), getContentBounds());
655         }
656         double getV = x2 - x1 <= 1 ? 1 : x2 - x1;
657         return new Rectangle((int) x1, (int) (getContentBounds().getY() + 5), (int) getV, height);
658     }
659 
660     /**
661      * get the maxDept
662      *
663      * @return maxDept maxDept
664      */
getMaxDept()665     public int getMaxDept() {
666         return this.maxDept;
667     }
668 
669     /**
670      * set the maxDept
671      *
672      * @param maxDept maxDept
673      */
setMaxDept(int maxDept)674     public void setMaxDept(int maxDept) {
675         this.maxDept = maxDept;
676     }
677 }
678