• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 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
16import { RangeSelectStruct, TraceRow } from './TraceRow';
17import { Rect } from '../timer-shaft/Rect';
18import { TimerShaftElement } from '../TimerShaftElement';
19import { info } from '../../../../log/Log';
20import './Extension';
21import { SpSystemTrace } from '../../SpSystemTrace';
22import {querySearchRowFuncData} from "../../../database/sql/Func.sql";
23
24export class RangeSelect {
25  private rowsEL: HTMLDivElement | undefined | null;
26  private rowsPaneEL: HTMLDivElement | undefined | null;
27  isMouseDown: boolean = false;
28  public rangeTraceRow: Array<TraceRow<any>> | undefined;
29  public selectHandler: ((ds: Array<TraceRow<any>>, refreshCheckBox: boolean) => void) | undefined;
30  private startPageX: number = 0;
31  private startPageY: number = 0;
32  private endPageX: number = 0;
33  private endPageY: number = 0;
34  private timerShaftEL: TimerShaftElement | null | undefined;
35  private isHover: boolean = false;
36  private movingMark: string = '';
37  private mark: { startMark: number; endMark: number } = {
38    startMark: 0,
39    endMark: 0,
40  };
41  private trace: SpSystemTrace | null | undefined;
42  drag = false;
43
44  constructor(trace: SpSystemTrace | null | undefined) {
45    this.trace = trace;
46    this.timerShaftEL = trace?.timerShaftEL;
47    this.rowsEL = trace?.rowsEL;
48    this.rowsPaneEL = trace?.rowsPaneEL;
49  }
50
51  isInRowsEl(ev: MouseEvent): boolean {
52    return this.rowsPaneEL!.containPoint(ev, { left: 248 });
53  }
54
55  isInSpacerEL(ev: MouseEvent): boolean {
56    return this.trace!.favoriteChartListEL!.containPoint(ev, { left: 248 });
57  }
58
59  mouseDown(eventDown: MouseEvent): void {
60    this.startPageX = eventDown.pageX;
61    this.startPageY = eventDown.pageY;
62    if (this.isHover) {
63      this.isMouseDown = true;
64      return;
65    }
66    this.rangeTraceRow = [];
67    this.isMouseDown = true;
68    TraceRow.rangeSelectObject = undefined;
69  }
70
71  mouseUp(mouseEventUp: MouseEvent): void {
72    this.endPageX = mouseEventUp.pageX;
73    this.endPageY = mouseEventUp.pageY;
74    if (this.drag) {
75      if (this.selectHandler) {
76        this.selectHandler(this.rangeTraceRow || [], !this.isHover);
77      }
78      //如果只框选了一条泳道,查询H:RSMainThread::DoComposition数据
79      let docompositionData: Array<number> = [];
80      if (this.rangeTraceRow) {
81        this.rangeTraceRow.forEach((row) => {
82          row.docompositionList = [];
83        });
84        docompositionData = [];
85        if (
86          this.rangeTraceRow.length === 1 &&
87          this.rangeTraceRow[0]?.getAttribute('row-type') === 'func' &&
88          this.rangeTraceRow[0]?.getAttribute('name')?.startsWith('render_service')
89        ) {
90          querySearchRowFuncData(
91            'H:RSMainThread::DoComposition',
92            Number(this.rangeTraceRow[0]?.getAttribute('row-id')),
93            TraceRow.rangeSelectObject!.startNS!,
94            TraceRow.rangeSelectObject!.endNS!
95          ).then((res) => {
96            res.forEach((item) => {
97              docompositionData.push(item.startTime!);
98            });
99            this.rangeTraceRow![0].docompositionList = docompositionData;
100          });
101        }
102      }
103    }
104    this.isMouseDown = false;
105  }
106
107  isDrag(): boolean {
108    return this.startPageX !== this.endPageX;
109  }
110
111  isTouchMark(ev: MouseEvent): boolean {
112    let notTimeHeight: boolean = this.rowsPaneEL!.containPoint(ev, {
113      left: 248,
114      top: -45,
115    });
116    if (!notTimeHeight) {
117      return false;
118    }
119    if ((this.rangeTraceRow?.isEmpty() ?? false) && !this.isMouseDown) {
120      this.isHover = false;
121    }
122    return notTimeHeight && (this.rangeTraceRow?.isNotEmpty() ?? false) && !this.isMouseDown;
123  }
124
125  mouseOut(mouseEventOut: MouseEvent): void {
126    this.endPageX = mouseEventOut.pageX;
127    this.endPageY = mouseEventOut.pageY;
128    if (this.drag) {
129      if (this.selectHandler && this.isMouseDown) {
130        this.selectHandler(this.rangeTraceRow || [], !this.isHover);
131      }
132    }
133    document.getSelection()?.removeAllRanges();
134    this.isMouseDown = false;
135  }
136
137  mouseMove(rows: Array<TraceRow<any>>, ev: MouseEvent): void {
138    this.endPageX = ev.pageX;
139    this.endPageY = ev.pageY;
140    if (this.isTouchMark(ev) && TraceRow.rangeSelectObject) {
141      this.handleTouchMark(ev);
142    } else {
143      document.body.style.cursor = 'default';
144    }
145    if (this.isHover && this.isMouseDown) {
146      this.handleRangeSelectAndDraw(rows, ev);
147      return;
148    }
149    if (!this.isMouseDown) {
150      this.handleDrawForNotMouseDown();
151      return;
152    }
153    this.handleRangeSelect(rows);
154    this.timerShaftEL!.sportRuler!.isRangeSelect = this.rangeTraceRow!.length > 0;
155    this.timerShaftEL!.sportRuler!.draw();
156  }
157
158  private handleRangeSelect(rows: Array<TraceRow<any>>): void {
159    let rangeSelect: RangeSelectStruct | undefined;
160    let favoriteRect = this.trace?.favoriteChartListEL?.getBoundingClientRect();
161    let favoriteLimit = favoriteRect!.top + favoriteRect!.height;
162    this.rangeTraceRow = rows.filter((it) => {
163      let domRect = it.getBoundingClientRect();
164      let itRect = {x: domRect.x, y: domRect.y, width: domRect.width, height: domRect.height};
165      if (itRect.y < favoriteLimit && !it.collect) {
166        let offset = favoriteLimit - itRect.y;
167        itRect.y = itRect.y + offset;
168        itRect.height = itRect.height - offset;
169      }
170      if (it.sticky) {
171        itRect.y = 0;
172        itRect.height = 0;
173      }
174      if (
175        Rect.intersect(itRect as Rect, {
176          x: Math.min(this.startPageX, this.endPageX),
177          y: Math.min(this.startPageY, this.endPageY),
178          width: Math.abs(this.startPageX - this.endPageX),
179          height: Math.abs(this.startPageY - this.endPageY),
180        } as Rect)
181      ) {
182        if (!rangeSelect) {
183          it.setTipLeft(0, null);
184          rangeSelect = new RangeSelectStruct();
185          let startX = Math.min(this.startPageX, this.endPageX) - it.describeEl!.getBoundingClientRect().right;
186          let endX = Math.max(this.startPageX, this.endPageX) - it.describeEl!.getBoundingClientRect().right;
187          if (startX <= 0) startX = 0;
188          if (endX > it.frame.width) endX = it.frame.width;
189          rangeSelect.startX = startX;
190          rangeSelect.endX = endX;
191          rangeSelect.startNS = RangeSelect.SetNS(it, startX);
192          rangeSelect.endNS = RangeSelect.SetNS(it, endX);
193        }
194        TraceRow.rangeSelectObject = rangeSelect;
195        it.rangeSelect = true;
196        return true;
197      } else {
198        it.rangeSelect = false;
199        return false;
200      }
201    });
202    if (this.rangeTraceRow && this.rangeTraceRow.length) {
203      this.rangeTraceRow!.forEach((row) => {
204        row.docompositionList = [];
205      });
206    }
207  }
208
209  private handleDrawForNotMouseDown(): void {
210    this.timerShaftEL!.sportRuler!.isRangeSelect = this.rangeTraceRow?.isNotEmpty() ?? false;
211    this.timerShaftEL!.sportRuler!.draw();
212  }
213
214  private handleRangeSelectAndDraw(rows: Array<TraceRow<any>>, ev: MouseEvent): void {
215    let rangeSelect: RangeSelectStruct | undefined;
216    this.rangeTraceRow = rows.filter((it) => {
217      if (it.rangeSelect) {
218        if (!rangeSelect) {
219          rangeSelect = new RangeSelectStruct();
220          let mouseX = ev.pageX - this.rowsEL!.getBoundingClientRect().left - 248;
221          mouseX = mouseX < 0 ? 0 : mouseX;
222          let markA = this.movingMark == 'markA' ? mouseX : this.mark.startMark;
223          let markB = this.movingMark == 'markB' ? mouseX : this.mark.endMark;
224          let startX = markA < markB ? markA : markB;
225          let endX = markB < markA ? markA : markB;
226          rangeSelect.startX = startX;
227          rangeSelect.endX = endX;
228          rangeSelect.startNS = RangeSelect.SetNS(it, startX);
229          rangeSelect.endNS = RangeSelect.SetNS(it, endX);
230          if (rangeSelect.startNS <= TraceRow.range!.startNS) {
231            rangeSelect.startNS = TraceRow.range!.startNS;
232          }
233          if (rangeSelect.endNS >= TraceRow.range!.endNS) {
234            rangeSelect.endNS = TraceRow.range!.endNS;
235          }
236          if (startX < 0) {
237            rangeSelect.startNS = TraceRow.rangeSelectObject!.startNS!;
238          }
239          if (endX > it.frame.width) {
240            rangeSelect.endNS = TraceRow.rangeSelectObject!.endNS!;
241          }
242        }
243        TraceRow.rangeSelectObject = rangeSelect;
244        return true;
245      }
246    });
247    this.timerShaftEL!.sportRuler!.isRangeSelect = (this.rangeTraceRow?.length || 0) > 0;
248    this.timerShaftEL!.sportRuler!.draw();
249  }
250
251  private handleTouchMark(ev: MouseEvent): void {
252    info('isTouchMark');
253    let x1 =
254      ((TraceRow.rangeSelectObject!.startNS! - TraceRow.range!.startNS) *
255        (this.timerShaftEL?.canvas?.clientWidth || 0)) /
256      (TraceRow.range!.endNS - TraceRow.range!.startNS);
257    let x2 =
258      ((TraceRow.rangeSelectObject!.endNS! - TraceRow.range!.startNS) *
259        (this.timerShaftEL?.canvas?.clientWidth || 0)) /
260      (TraceRow.range!.endNS - TraceRow.range!.startNS);
261    this.mark = {startMark: x1, endMark: x2};
262    let mouseX = ev.pageX - this.rowsPaneEL!.getBoundingClientRect().left - 248;
263    if (mouseX > x1 - 5 && mouseX < x1 + 5) {
264      this.isHover = true;
265      document.body.style.cursor = 'ew-resize';
266      this.movingMark = x1 < x2 ? 'markA' : 'markB';
267    } else if (mouseX > x2 - 5 && mouseX < x2 + 5) {
268      this.isHover = true;
269      document.body.style.cursor = 'ew-resize';
270      this.movingMark = x2 < x1 ? 'markA' : 'markB';
271    } else {
272      this.isHover = false;
273      document.body.style.cursor = 'default';
274    }
275  }
276
277  static SetNS(row: TraceRow<any>, num: number): number {
278    return Math.floor(
279      ((TraceRow.range!.endNS - TraceRow.range!.startNS) * num) / row.frame.width + TraceRow.range!.startNS!
280    );
281  }
282}
283