• 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.component;
17 
18 import ohos.devtools.views.trace.bean.TabThreadStatesBean;
19 import ohos.devtools.views.trace.util.Final;
20 import ohos.devtools.views.trace.util.Utils;
21 
22 import javax.swing.JPanel;
23 import java.awt.Color;
24 import java.awt.Graphics;
25 import java.awt.Graphics2D;
26 import java.awt.Rectangle;
27 import java.awt.RenderingHints;
28 import java.awt.event.MouseAdapter;
29 import java.awt.event.MouseEvent;
30 import java.awt.event.MouseMotionListener;
31 import java.math.BigDecimal;
32 import java.util.ArrayList;
33 import java.util.Comparator;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.stream.Collectors;
37 
38 /**
39  * StackBar
40  *
41  * @since 2021/5/27 12:03
42  */
43 public class StackBar extends JPanel {
44     private List<StateValue> source = new ArrayList<>();
45     private long totalWallDuration;
46     private StateValue current;
47     private BigDecimal charW = BigDecimal.valueOf(getFontMetrics(getFont().deriveFont(11.0f)).charWidth('a') - 0.2);
48     private int drawX = 0;
49 
50     /**
51      * structure function
52      */
StackBar()53     public StackBar() {
54         addMouseMotionListener(new MouseMotionListener() {
55             @Override
56             public void mouseDragged(final MouseEvent event) {
57             }
58 
59             @Override
60             public void mouseMoved(final MouseEvent event) {
61                 for (int index = 0, size = source.size(); index < size; index++) {
62                     if (Utils.pointInRect(source.get(index).drawRect, event.getX(), event.getY())) {
63                         if (current != source.get(index)) {
64                             current = source.get(index);
65                             repaint();
66                         }
67                         break;
68                     }
69                 }
70             }
71         });
72         addMouseListener(new MouseAdapter() {
73             @Override
74             public void mouseExited(final MouseEvent event) {
75                 super.mouseMoved(event);
76                 current = null;
77             }
78         });
79     }
80 
81     /**
82      * set data source
83      *
84      * @param data data
85      */
setSource(final List<TabThreadStatesBean> data)86     public void setSource(final List<TabThreadStatesBean> data) {
87         source.clear();
88         if (data != null) {
89             Map<String, List<TabThreadStatesBean>> collect =
90                 data.stream().collect(Collectors.groupingBy(TabThreadStatesBean::getState));
91             for (String state : collect.keySet()) {
92                 long sum = 0L;
93                 for (TabThreadStatesBean bean : collect.get(state)) {
94                     sum += bean.getWallDuration();
95                 }
96                 if ("".equals(state)) {
97                     totalWallDuration = sum;
98                 } else {
99                     StateValue sv = new StateValue();
100                     sv.color = getStateColor(state);
101                     sv.state = Utils.getEndState(state) + " : " + Utils.transformTimeToMs(sum) + "ms";
102                     sv.value = sum;
103                     source.add(sv);
104                 }
105             }
106             source = source.stream().sorted(Comparator.comparing(StateValue::getValue)).collect(Collectors.toList());
107         }
108         repaint();
109     }
110 
111     @Override
paint(final Graphics graphics)112     public void paint(final Graphics graphics) {
113         drawX = 0;
114         if (graphics instanceof Graphics2D) {
115             ((Graphics2D) graphics)
116                 .setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
117         }
118         for (StateValue sv : source) {
119             graphics.setFont(getFont().deriveFont(11.0f));
120             graphics.setColor(sv.color);
121             int trueW;
122             if (sv == current && sv.drawRect.width < charW.doubleValue() * sv.state.length()) {
123                 trueW = (int) (charW.doubleValue() * sv.state.length() + 1);
124             } else {
125                 trueW = (int) ((sv.value * 1.0 / totalWallDuration) * getWidth() + 1);
126             }
127             if (trueW + drawX > getWidth()) {
128                 trueW = getWidth() - drawX - 5;
129             }
130             graphics.fillRect(drawX, 0, trueW, getHeight());
131             sv.drawRect = new Rectangle(drawX, 0, trueW, getHeight());
132 
133             // 计算单个字符所占宽度
134             if (sv.drawRect.width > charW.doubleValue()) {
135                 if (sv.state.startsWith("Sleeping")) {
136                     graphics.setColor(Color.gray);
137                 } else {
138                     graphics.setColor(Color.white);
139                 }
140                 int chars = (int) (sv.drawRect.width / charW.doubleValue());
141                 if (chars < sv.state.length()) {
142                     graphics.drawString(sv.state.substring(0, chars), drawX + 1, 13);
143                 } else {
144                     graphics.drawString(sv.state, drawX + 1, 13);
145                 }
146             }
147             drawX = drawX + trueW + 1;
148         }
149     }
150 
getStateColor(String state)151     private Color getStateColor(String state) {
152         switch (state) {
153             case "Running":
154                 return new Color(Final.RUNNING_COLOR);
155             case "D":
156                 return new Color(Final.UNINTERRUPTIBLE_SLEEP_COLOR);
157             case "S":
158                 return new Color(Final.S_COLOR);
159             case "R":
160             case "R+":
161             default:
162                 return new Color(Final.R_COLOR);
163         }
164     }
165 
166     private class StateValue {
167         private String state;
168         private long value;
169         private Color color;
170         private Rectangle drawRect;
171 
getValue()172         private long getValue() {
173             return value;
174         }
175     }
176 }
177