• 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 com.intellij.ui.components.JBViewport;
19 import ohos.devtools.views.trace.fragment.AbstractDataFragment;
20 import ohos.devtools.views.trace.fragment.CpuDataFragment;
21 import ohos.devtools.views.trace.fragment.ruler.CpuFragment;
22 import ohos.devtools.views.trace.fragment.ruler.LeftFragment;
23 import ohos.devtools.views.trace.fragment.ruler.RulerFragment;
24 import ohos.devtools.views.trace.fragment.ruler.TopFragment;
25 import ohos.devtools.views.trace.util.Final;
26 import ohos.devtools.views.trace.util.Utils;
27 
28 import javax.swing.JComponent;
29 import java.awt.Graphics;
30 import java.awt.Graphics2D;
31 import java.awt.event.MouseEvent;
32 import java.util.List;
33 import java.util.concurrent.CopyOnWriteArrayList;
34 
35 /**
36  * Timeline component
37  *
38  * @since 2021/04/20 12:24
39  */
40 public final class TimeViewPort extends JBViewport {
41     /**
42      * Initial height of the time axis
43      */
44     protected static int height = 140;
45 
46     /**
47      * Favorite fragment list
48      */
49     protected final List<AbstractDataFragment> favoriteFragments = new CopyOnWriteArrayList<>();
50 
51     /**
52      * Fragment above
53      */
54     protected TopFragment topFragment;
55 
56     /**
57      * Fragment on the left
58      */
59     protected LeftFragment leftFragment;
60 
61     /**
62      * Cpu fragment
63      */
64     protected CpuFragment cpuFragment;
65 
66     /**
67      * Rule fragment
68      */
69     protected RulerFragment rulerFragment;
70 
71     private final IRangeChangeListener rangeChangeListener;
72     private final IHeightChangeListener heightChangeListener;
73 
74     /**
75      * Constructor。
76      *
77      * @param heightChangeListener Altitude change monitoring
78      * @param rangeChangeListener Altitude change monitoring
79      */
TimeViewPort(IHeightChangeListener heightChangeListener, IRangeChangeListener rangeChangeListener)80     public TimeViewPort(IHeightChangeListener heightChangeListener, IRangeChangeListener rangeChangeListener) {
81         this.rangeChangeListener = rangeChangeListener;
82         this.heightChangeListener = heightChangeListener;
83         this.topFragment = new TopFragment(this);
84         this.leftFragment = new LeftFragment(this);
85         this.cpuFragment = new CpuFragment(this, (leftX, rightX, leftNS, rightNS, centerNS) -> {
86             leftFragment.setStartTime(leftNS);
87             rulerFragment.setRange(leftNS, rightNS, centerNS);
88         });
89         this.rulerFragment = new RulerFragment(this, (startNS, endNS) -> {
90             if (rangeChangeListener != null) {
91                 rangeChangeListener.change(startNS, endNS);
92             }
93         });
94         this.setOpaque(true);
95         setFont(Final.NORMAL_FONT);
96     }
97 
98     /**
99      * mouse clicked handler
100      *
101      * @param event event
102      */
mouseClicked(MouseEvent event)103     public void mouseClicked(MouseEvent event) {
104         for (AbstractDataFragment favoriteFragment : favoriteFragments) {
105             favoriteFragment.mouseClicked(event);
106         }
107         rulerFragment.mouseClicked(event);
108     }
109 
110     /**
111      * set root height
112      *
113      * @param rootHeight root height
114      */
setRootHeight(int rootHeight)115     public void setRootHeight(int rootHeight) {
116         rulerFragment.setExtendHeight(rootHeight - height);
117         leftFragment.setExtendHeight(rootHeight - height);
118     }
119 
120     /**
121      * collect fragment
122      *
123      * @param dataFragment fragment
124      */
favorite(AbstractDataFragment dataFragment)125     public void favorite(AbstractDataFragment dataFragment) {
126         dataFragment.setVisible(false);
127         dataFragment.favoriteGraph.favorite(true);
128         Utils.setY(dataFragment.getRect(), height);
129         height += dataFragment.getRect().height;
130         favoriteFragments.add(dataFragment);
131         if (heightChangeListener != null) {
132             heightChangeListener.change(height);
133             repaint();
134         }
135     }
136 
137     /**
138      * cancel collect fragment
139      *
140      * @param dataFragment fragment
141      */
cancel(AbstractDataFragment dataFragment)142     public void cancel(AbstractDataFragment dataFragment) {
143         if (favoriteFragments.contains(dataFragment)) {
144             dataFragment.setVisible(true);
145             dataFragment.favoriteGraph.favorite(false);
146             height -= dataFragment.getRect().height;
147             favoriteFragments.remove(dataFragment);
148             if (heightChangeListener != null) {
149                 heightChangeListener.change(height);
150                 repaint();
151             }
152         }
153     }
154 
155     @Override
paintComponent(Graphics graphics)156     protected void paintComponent(Graphics graphics) {
157         super.paintComponent(graphics);
158     }
159 
160     @Override
paint(Graphics graphics)161     public void paint(Graphics graphics) {
162         super.paint(graphics);
163         if (graphics instanceof Graphics2D) {
164             Graphics2D g2 = (Graphics2D) graphics;
165             graphics.setColor(getBackground());
166             graphics.fillRect(0, 0, getWidth(), height);
167             leftFragment.draw(g2);
168             topFragment.draw(g2);
169             cpuFragment.draw(g2);
170             rulerFragment.draw(g2);
171             for (int index = favoriteFragments.size() - 1; index >= 0; index--) {
172                 AbstractDataFragment frg = favoriteFragments.get(index);
173                 if (index == favoriteFragments.size() - 1) {
174                     Utils.setY(frg.getRect(), height - frg.getRect().height);
175                     Utils.setY(frg.getDescRect(), height - frg.getRect().height);
176                     Utils.setY(frg.getDataRect(), height - frg.getRect().height);
177                 } else {
178                     Utils.setY(frg.getRect(),
179                         Utils.getY(favoriteFragments.get(index + 1).getRect()) - frg.getRect().height);
180                     Utils.setY(frg.getDescRect(),
181                         Utils.getY(favoriteFragments.get(index + 1).getRect()) - frg.getRect().height);
182                     Utils.setY(frg.getDataRect(),
183                         Utils.getY(favoriteFragments.get(index + 1).getRect()) - frg.getRect().height);
184                 }
185                 frg.draw(g2);
186             }
187         }
188     }
189 
190     /**
191      * custom mouse event pressed
192      *
193      * @param event mouse event
194      */
mousePressed(final MouseEvent event)195     public void mousePressed(final MouseEvent event) {
196         Object eventSource = event.getSource();
197         if (eventSource instanceof JComponent) {
198             JComponent jComponent = (JComponent) eventSource;
199             int scrollY = event.getY() + jComponent
200                 .getY(); // subtract the scroll height of the parent node. After scrolling down, y is a negative number.
201             cpuFragment.setSelectX(
202                 event.getX() < Utils.getX(cpuFragment.getRect()) ? Utils.getX(cpuFragment.getRect()) : event.getX());
203             cpuFragment.setSelectY(scrollY);
204             rulerFragment.setSelectX(
205                 event.getX() < Utils.getX(rulerFragment.getRect()) ? Utils.getX(rulerFragment.getRect())
206                     : event.getX());
207             rulerFragment.setSelectY(scrollY);
208         }
209     }
210 
211     /**
212      * custom mouse event dragged
213      *
214      * @param event mouse event
215      */
216     public void mouseDragged(final MouseEvent event) {
217         cpuFragment.mouseDragged(event);
218     }
219 
220     /**
221      * custom mouse event moved
222      *
223      * @param event mouse event
224      */
225     public void mouseMoved(final MouseEvent event) {
226         Object eventSource = event.getSource();
227         if (eventSource instanceof JComponent) {
228             JComponent jComponent = (JComponent) eventSource;
229             int scrollY = event.getY() + jComponent
230                 .getY(); // Subtract the scroll height of the parent node. After scrolling down, y is a negative number.
231             cpuFragment.setSelectX(
232                 event.getX() < Utils.getX(cpuFragment.getRect()) ? Utils.getX(cpuFragment.getRect()) : event.getX());
233             cpuFragment.setSelectY(scrollY);
234             rulerFragment.setSelectX(
235                 event.getX() < Utils.getX(rulerFragment.getRect()) ? Utils.getX(rulerFragment.getRect())
236                     : event.getX());
237             rulerFragment.setSelectY(scrollY);
238             CpuDataFragment.focusCpuData = null;
239             rulerFragment.mouseMoved(event);
240             favoriteFragments.forEach(fragment -> fragment.mouseMoved(event));
241         }
242     }
243 
244     /**
245      * recycle all fragments
246      */
247     public void recycle() {
248         TimeViewPort.height = 140;
249         if (favoriteFragments != null) {
250             favoriteFragments.forEach(AbstractDataFragment::recycle);
251             favoriteFragments.clear();
252         }
253     }
254 
255     /**
256      * Timeline interval change listener
257      */
258     @FunctionalInterface
259     public interface IRangeChangeListener {
260         /**
261          * change callback
262          *
263          * @param startNS start time
264          * @param endNS end time
265          */
266         void change(long startNS, long endNS);
267     }
268 
269     /**
270      * Height change listener
271      */
272     @FunctionalInterface
273     public interface IHeightChangeListener {
274         /**
275          * change callback
276          *
277          * @param height height change
278          */
279         void change(int height);
280     }
281 }
282