• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import {TransformMatrix} from 'common/geometry/transform_matrix';
18import {UiRectBuilder} from 'viewers/components/rects/ui_rect_builder';
19import {RectFilter} from './rect_filter';
20import {RectShowState} from './rect_show_state';
21
22describe('RectFilter', () => {
23  let rectFilter: RectFilter;
24  const nonVisibleNoContentRect = makeRect(
25    'nonVisibleNoContentRect',
26    false,
27    false,
28  );
29  const nonVisibleContentRect = makeRect('nonVisibleContentRect', false, true);
30  const visibleContentRect = makeRect('visibleContentRect', true, true);
31  const visibleNoContentRect = makeRect('visibleNoContentRect', true, false);
32  const displayRect = makeRect('displayRect', false, false, true);
33  const allRects = [
34    visibleContentRect,
35    visibleNoContentRect,
36    nonVisibleContentRect,
37    nonVisibleNoContentRect,
38    displayRect,
39  ];
40  const preFilteredRects = [
41    visibleContentRect,
42    visibleNoContentRect,
43    nonVisibleContentRect,
44    nonVisibleNoContentRect,
45  ];
46  let expectedRectIdToShowState: Map<string, RectShowState>;
47
48  beforeEach(() => {
49    rectFilter = new RectFilter((id: string) => id);
50    expectedRectIdToShowState = new Map([
51      [visibleContentRect.id, RectShowState.SHOW],
52      [visibleNoContentRect.id, RectShowState.SHOW],
53      [nonVisibleContentRect.id, RectShowState.SHOW],
54      [nonVisibleNoContentRect.id, RectShowState.SHOW],
55      [displayRect.id, RectShowState.SHOW],
56    ]);
57  });
58
59  it('creates rect id to show state map', () => {
60    expect(rectFilter.getRectIdToShowState(allRects, allRects)).toEqual(
61      expectedRectIdToShowState,
62    );
63
64    // sets hide state for rect that is not present in filtered rects
65    expectedRectIdToShowState.set(displayRect.id, RectShowState.HIDE);
66    expect(rectFilter.getRectIdToShowState(allRects, preFilteredRects)).toEqual(
67      expectedRectIdToShowState,
68    );
69
70    // keeps rect that is not present in drawn rects but has force-show state
71    rectFilter.updateRectShowState(displayRect.id, RectShowState.SHOW);
72    expectedRectIdToShowState.set(displayRect.id, RectShowState.SHOW);
73    expect(rectFilter.getRectIdToShowState(allRects, preFilteredRects)).toEqual(
74      expectedRectIdToShowState,
75    );
76  });
77
78  it('updates rect forced show state', () => {
79    expect(isShown(visibleContentRect.id)).toBeTrue();
80
81    // robust to same state (RectShowState.SHOW)
82    rectFilter.updateRectShowState(visibleContentRect.id, RectShowState.SHOW);
83    expect(isShown(visibleContentRect.id)).toBeTrue();
84
85    rectFilter.updateRectShowState(visibleContentRect.id, RectShowState.HIDE);
86    expect(isShown(visibleContentRect.id)).toBeFalse();
87
88    // robust to same state (RectShowState.HIDE)
89    rectFilter.updateRectShowState(visibleContentRect.id, RectShowState.HIDE);
90    expect(isShown(visibleContentRect.id)).toBeFalse();
91
92    rectFilter.updateRectShowState(visibleContentRect.id, RectShowState.SHOW);
93    expect(isShown(visibleContentRect.id)).toBeTrue();
94
95    expect(isShown(displayRect.id)).toBeFalse();
96    rectFilter.updateRectShowState(displayRect.id, RectShowState.SHOW);
97    expect(isShown(displayRect.id)).toBeTrue();
98  });
99
100  it('does not filter rects if applicable', () => {
101    expect(rectFilter.filterRects(allRects, false, true, false)).toEqual(
102      allRects,
103    );
104  });
105
106  it('filters non visible rects', () => {
107    const filteredRects = rectFilter.filterRects(allRects, true, true, false);
108    expect(filteredRects).toEqual([
109      visibleContentRect,
110      visibleNoContentRect,
111      displayRect,
112    ]);
113
114    // robust to all visible rects
115    expect(rectFilter.filterRects(filteredRects, true, true, false)).toEqual(
116      filteredRects,
117    );
118
119    // does not apply force-hide state
120    rectFilter.updateRectShowState(visibleContentRect.id, RectShowState.HIDE);
121    expect(rectFilter.filterRects(allRects, true, true, false)).toEqual(
122      filteredRects,
123    );
124
125    // does not apply force-show state
126    rectFilter.updateRectShowState(
127      nonVisibleContentRect.id,
128      RectShowState.SHOW,
129    );
130    expect(rectFilter.filterRects(allRects, true, true, false)).toEqual(
131      filteredRects,
132    );
133  });
134
135  it('applies show/hide states', () => {
136    rectFilter.updateRectShowState(visibleContentRect.id, RectShowState.HIDE);
137    const filteredRects = rectFilter.filterRects(allRects, false, false, false);
138    expect(filteredRects).toEqual([
139      visibleNoContentRect,
140      nonVisibleContentRect,
141      nonVisibleNoContentRect,
142      displayRect,
143    ]);
144
145    // robust to no change in show/hide states
146    expect(rectFilter.filterRects(filteredRects, false, false, false)).toEqual(
147      filteredRects,
148    );
149
150    rectFilter.updateRectShowState(visibleContentRect.id, RectShowState.SHOW);
151    expect(rectFilter.filterRects(allRects, false, false, false)).toEqual(
152      allRects,
153    );
154  });
155
156  it('filters non visible rects and applies show/hide states', () => {
157    // does not remove force-shown non-visible rect
158    rectFilter.updateRectShowState(
159      nonVisibleContentRect.id,
160      RectShowState.SHOW,
161    );
162    rectFilter.updateRectShowState(
163      nonVisibleNoContentRect.id,
164      RectShowState.SHOW,
165    );
166    expect(rectFilter.filterRects(allRects, true, false, false)).toEqual(
167      allRects,
168    );
169
170    // removes force-hidden visible rect
171    rectFilter.updateRectShowState(visibleContentRect.id, RectShowState.HIDE);
172    const filteredRects = rectFilter.filterRects(allRects, true, false, false);
173    expect(filteredRects).toEqual([
174      visibleNoContentRect,
175      nonVisibleContentRect,
176      nonVisibleNoContentRect,
177      displayRect,
178    ]);
179
180    // removes non-visible rect but keeps visible rect that has not had hide/show state applied
181    rectFilter.updateRectShowState(
182      nonVisibleNoContentRect.id,
183      RectShowState.HIDE,
184    );
185    expect(rectFilter.filterRects(allRects, true, false, false)).toEqual([
186      visibleNoContentRect,
187      nonVisibleContentRect,
188      displayRect,
189    ]);
190  });
191
192  it('filters rects without content', () => {
193    const filteredRects = rectFilter.filterRects(allRects, false, true, true);
194    expect(filteredRects).toEqual([
195      visibleContentRect,
196      nonVisibleContentRect,
197      displayRect,
198    ]);
199
200    // robust to all rects with content
201    expect(rectFilter.filterRects(filteredRects, false, true, true)).toEqual(
202      filteredRects,
203    );
204  });
205
206  it('filters rects without content by show state and visibility', () => {
207    const filteredRects = rectFilter.filterRects(allRects, true, false, true);
208    expect(filteredRects).toEqual([visibleContentRect, displayRect]);
209
210    // does not apply force-hide state
211    rectFilter.updateRectShowState(visibleContentRect.id, RectShowState.HIDE);
212    expect(rectFilter.filterRects(allRects, true, true, true)).toEqual(
213      filteredRects,
214    );
215
216    // does not apply force-show state
217    rectFilter.updateRectShowState(
218      nonVisibleNoContentRect.id,
219      RectShowState.SHOW,
220    );
221    expect(rectFilter.filterRects(allRects, true, true, true)).toEqual(
222      filteredRects,
223    );
224  });
225
226  it('applies forced state key callback', () => {
227    const relaxedRectFilter = new RectFilter((id) =>
228      id.slice(id.length - 5, id.length - 1),
229    );
230    relaxedRectFilter.updateRectShowState('TestRect', RectShowState.HIDE);
231    expect(
232      relaxedRectFilter.filterRects(allRects, false, false, false),
233    ).toEqual([displayRect]);
234  });
235
236  function isShown(rectId: string) {
237    const nonHiddenRectIds = rectFilter.getRectIdToShowState(
238      allRects,
239      preFilteredRects,
240    );
241    return nonHiddenRectIds.get(rectId) === RectShowState.SHOW;
242  }
243
244  function makeRect(
245    id: string,
246    isVisible: boolean,
247    hasContent: boolean,
248    isDisplay = false,
249  ) {
250    return new UiRectBuilder()
251      .setX(0)
252      .setY(0)
253      .setWidth(1)
254      .setHeight(1)
255      .setLabel(id)
256      .setTransform(
257        TransformMatrix.from({
258          dsdx: 1,
259          dsdy: 0,
260          dtdx: 0,
261          dtdy: 1,
262          tx: 0,
263          ty: 0,
264        }),
265      )
266      .setIsVisible(isVisible)
267      .setIsDisplay(isDisplay)
268      .setIsActiveDisplay(false)
269      .setId(id)
270      .setGroupId(0)
271      .setIsClickable(false)
272      .setCornerRadius(0)
273      .setDepth(0)
274      .setOpacity(0.5)
275      .setHasContent(hasContent)
276      .build();
277  }
278});
279