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 com.intellij.ui.components.JBBox; 19 import ohos.devtools.views.trace.bean.WakeupBean; 20 import ohos.devtools.views.trace.listener.IScrollSliceLinkListener; 21 import ohos.devtools.views.trace.util.Final; 22 import ohos.devtools.views.trace.util.TimeUtils; 23 import ohos.devtools.views.trace.util.Utils; 24 25 import javax.imageio.ImageIO; 26 import java.awt.AlphaComposite; 27 import java.awt.Color; 28 import java.awt.Composite; 29 import java.awt.Cursor; 30 import java.awt.Font; 31 import java.awt.Graphics; 32 import java.awt.Graphics2D; 33 import java.awt.Image; 34 import java.awt.Rectangle; 35 import java.awt.RenderingHints; 36 import java.awt.event.MouseEvent; 37 import java.awt.event.MouseMotionAdapter; 38 import java.awt.geom.Rectangle2D; 39 import java.io.IOException; 40 import java.util.ArrayList; 41 import java.util.List; 42 43 /** 44 * bottom Slice panel 45 * 46 * @since 2021/04/20 12:24 47 */ 48 public class ScrollSlicePanel extends BottomScrollPanel { 49 private Font font = getFont(); 50 private List<LineComponent> comps = new ArrayList<>(); 51 private List<SliceData> dataSource; 52 private WakeupBean wakeupBean; 53 private IScrollSliceLinkListener listener; 54 55 /** 56 * create table line data 57 * 58 * @param key key 59 * @param value value 60 * @param linkable link 61 * @return SliceData data 62 */ createSliceData(String key, String value, boolean linkable)63 public static SliceData createSliceData(String key, String value, boolean linkable) { 64 SliceData data = new SliceData(); 65 data.key = key; 66 data.value = value; 67 data.linkable = linkable; 68 return data; 69 } 70 71 /** 72 * set component data source 73 * 74 * @param title table title 75 * @param dataSource table data source 76 * @param wakeupBean wakeup data information 77 */ setData(String title, List<SliceData> dataSource, WakeupBean wakeupBean)78 public void setData(String title, List<SliceData> dataSource, WakeupBean wakeupBean) { 79 this.dataSource = dataSource; 80 this.wakeupBean = wakeupBean; 81 box.removeAll(); 82 JBBox b1 = JBBox.createVerticalBox(); 83 b1.add(new TitlePanel(title)); 84 comps.clear(); 85 if (dataSource != null) { 86 for (SliceData sliceData : dataSource) { 87 LineComponent lc = new LineComponent(sliceData.key, sliceData.value == null ? "" : sliceData.value, 88 sliceData.linkable); 89 lc.setListener(listener); 90 comps.add(lc); 91 b1.add(lc); 92 } 93 } 94 b1.add(JBBox.createVerticalGlue()); 95 JBBox b2 = JBBox.createVerticalBox(); 96 b2.add(new RightPanel()); 97 b2.add(JBBox.createVerticalGlue()); 98 box.add(b1); 99 box.add(b2); 100 revalidate(); 101 } 102 103 /** 104 * set link click listener 105 * 106 * @param listener listener 107 */ setScrollSliceLinkListener(IScrollSliceLinkListener listener)108 public void setScrollSliceLinkListener(IScrollSliceLinkListener listener) { 109 this.listener = listener; 110 for (LineComponent comp : comps) { 111 if (comp.linkable) { 112 comp.setListener(listener); 113 } 114 } 115 } 116 117 /** 118 * SliceData 119 * 120 * @since 2021/04/20 12:24 121 */ 122 public static class SliceData { 123 /** 124 * parameter key 125 */ 126 protected String key; 127 128 /** 129 * parameter value 130 */ 131 protected String value; 132 133 /** 134 * parameter linkable 135 */ 136 protected boolean linkable; 137 } 138 139 /** 140 * RightPanel 141 * 142 * @since 2021/04/20 12:24 143 */ 144 class RightPanel extends ChildPanel { 145 private final int[][] pointX = {{11, 2, 11, 20}, {13, 13, 18, 20, 15, 20, 18}, {103, 103, 98, 96, 101, 96, 98}}; 146 private final int[][] pointY = {{50, 58, 66, 58}, {120, 124, 129, 127, 122, 117, 115}}; 147 private final int strStartX = 30; 148 private final int lineCharSize = 60; 149 150 /** 151 * RightPanel constructor 152 */ RightPanel()153 public RightPanel() { 154 super(0, 222); 155 } 156 157 /** 158 * paint 159 * 160 * @param graphics graphics 161 */ 162 @Override paint(Graphics graphics)163 public void paint(Graphics graphics) { 164 super.paint(graphics); 165 setFont(Final.NORMAL_FONT); 166 if (wakeupBean == null || wakeupBean.getWakeupProcess() == null) { 167 return; 168 } 169 graphics.setFont(font.deriveFont(13f)); 170 if (graphics instanceof Graphics2D) { 171 ((Graphics2D) graphics) 172 .setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 173 ((Graphics2D) graphics) 174 .setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 175 } 176 graphics.drawString("Scheduling Latency", 10, 20); 177 graphics.fillRect(10, 30, 3, 130); 178 graphics.fillPolygon(pointX[0], pointY[0], pointX[0].length); 179 graphics.fillPolygon(pointX[1], pointY[1], pointX[1].length); 180 graphics.fillPolygon(pointX[2], pointY[1], pointX[2].length); 181 graphics.fillRect(13, 121, 90, 3); 182 graphics.setFont(font.deriveFont(11f)); 183 graphics.drawString( 184 "Wakeup @" + TimeUtils.getTimeString(wakeupBean.getWakeupTime()) + " on CPU " + wakeupBean 185 .getWakeupCpu() + " by", strStartX, 55); 186 graphics 187 .drawString("P:" + wakeupBean.getWakeupProcess() + " [ " + wakeupBean.getWakeupPid() + " ]", strStartX, 188 75); 189 graphics 190 .drawString("T:" + wakeupBean.getWakeupThread() + " [ " + wakeupBean.getWakeupTid() + " ]", strStartX, 191 95); 192 graphics.drawString("Scheduling latency:" + TimeUtils.getTimeString(wakeupBean.getSchedulingLatency()), 115, 193 125); 194 graphics.setFont(font.deriveFont(9f)); 195 graphics.setColor(new Color(0x88, 0x88, 0x88)); 196 int lines = wakeupBean.getSchedulingDesc().length() % lineCharSize == 0 197 ? wakeupBean.getSchedulingDesc().length() / lineCharSize 198 : wakeupBean.getSchedulingDesc().length() / lineCharSize + 1; 199 for (int index = 0; index < lines; index++) { 200 String str = ""; 201 if (index == lines - 1) { 202 str = wakeupBean.getSchedulingDesc().substring(index * lineCharSize); 203 } else { 204 str = wakeupBean.getSchedulingDesc().substring(index * lineCharSize, (index + 1) * lineCharSize); 205 } 206 graphics.drawString(str, 115, 142 + index * 14); 207 } 208 setFont(Final.NORMAL_FONT); 209 } 210 } 211 212 /** 213 * TitlePanel 214 * 215 * @since 2021/04/20 12:24 216 */ 217 class TitlePanel extends ChildLineComponent { 218 private String title; 219 220 /** 221 * set title 222 * 223 * @param title title 224 */ TitlePanel(String title)225 public TitlePanel(String title) { 226 this.title = title; 227 setFont(Final.NORMAL_FONT); 228 } 229 230 /** 231 * paint 232 * 233 * @param graphics graphics 234 */ 235 @Override paint(Graphics graphics)236 public void paint(Graphics graphics) { 237 super.paint(graphics); 238 graphics.setFont(font.deriveFont(13f)); 239 graphics.drawString(title, 10, 20); 240 } 241 } 242 243 /** 244 * LineComponent 245 * 246 * @since 2021/04/20 12:24 247 */ 248 class LineComponent extends ChildLineComponent { 249 /** 250 * linkable 251 */ 252 private boolean linkable; 253 private final int leftW = 200; 254 private String key; 255 private String value; 256 private IScrollSliceLinkListener listener; 257 private Rectangle linkRect; 258 259 /** 260 * LineComponent constructor 261 * 262 * @param key key 263 * @param value value 264 * @param linkable linkable 265 */ LineComponent(String key, String value, boolean linkable)266 public LineComponent(String key, String value, boolean linkable) { 267 super(); 268 this.key = key; 269 this.value = value; 270 this.linkable = linkable; 271 addMouseMotionListener(new MouseMotionAdapter() { 272 @Override 273 public void mouseMoved(final MouseEvent event) { 274 if (Utils.pointInRect(linkRect, event.getX(), event.getY())) { 275 setCursor(new Cursor(Cursor.HAND_CURSOR)); 276 } else { 277 setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 278 } 279 } 280 }); 281 } 282 283 /** 284 * set link listener 285 * 286 * @param listener listener 287 */ setListener(IScrollSliceLinkListener listener)288 public void setListener(IScrollSliceLinkListener listener) { 289 this.listener = listener; 290 } 291 292 /** 293 * child mouse clicked 294 * 295 * @param event event 296 */ 297 @Override childMouseClicked(final MouseEvent event)298 public void childMouseClicked(final MouseEvent event) { 299 if (Utils.pointInRect(linkRect, event.getX(), event.getY())) { 300 if (listener != null) { 301 listener.linkClick(value); 302 } 303 } 304 } 305 306 /** 307 * paint 308 * 309 * @param graphics graphics 310 */ 311 @Override paint(Graphics graphics)312 public void paint(Graphics graphics) { 313 super.paint(graphics); 314 graphics.setFont(font.deriveFont(11f)); 315 if (graphics instanceof Graphics2D) { 316 ((Graphics2D) graphics) 317 .setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 318 } 319 if (mouseIn) { 320 if (graphics instanceof Graphics2D) { 321 graphics.setColor(getForeground()); 322 Composite originalComposite = ((Graphics2D) graphics).getComposite(); 323 ((Graphics2D) graphics).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.15f)); 324 graphics.fillRect(0, 0, leftW - 2, lineHeight); 325 graphics.fillRect(leftW, 0, getWidth() - leftW, lineHeight); 326 ((Graphics2D) graphics).setComposite(originalComposite); 327 } 328 } 329 graphics.setColor(getForeground()); 330 graphics.drawString(key, 10, lineHeight / 2 + 4); 331 int sw = getWidth() - (leftW + 2); 332 int chars = sw / 7; 333 if (value.length() > chars && chars > 0) { 334 String vs1 = value.substring(0, chars); 335 String vs2 = value.substring(chars, value.length() - 1); 336 graphics.drawString(vs1, leftW + 2, lineHeight / 3); 337 graphics.drawString(vs2, leftW + 2, (lineHeight * 2) / 3); 338 } else { 339 graphics.drawString(value, leftW, lineHeight / 2 + 4); 340 } 341 if (linkable) { 342 try { 343 if (value != null && value.length() > 0) { 344 Rectangle2D bounds = graphics.getFontMetrics(font).getStringBounds(value, graphics); 345 linkRect = new Rectangle((int) (202 + bounds.getWidth() + 5), (lineHeight - 20) / 2, 20, 20); 346 Image link = ImageIO.read(getClass().getResourceAsStream("/assets/link.png")); 347 graphics.drawImage(link, Utils.getX(linkRect) + 2, Utils.getY(linkRect) + 3, 15, 15, null); 348 } 349 } catch (IOException ioException) { 350 ioException.printStackTrace(); 351 } 352 } 353 } 354 } 355 } 356