Merge "Allow 3 strategies for selecting the overview timeline."
diff --git a/ui/src/frontend/drag/border_drag_strategy.ts b/ui/src/frontend/drag/border_drag_strategy.ts
new file mode 100644
index 0000000..b91169d
--- /dev/null
+++ b/ui/src/frontend/drag/border_drag_strategy.ts
@@ -0,0 +1,43 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+import {TimeScale} from '../time_scale';
+
+import {DragStrategy} from './drag_strategy';
+
+export class BorderDragStrategy extends DragStrategy {
+ private pixelBounds: [number, number];
+ private moveStart = false;
+
+ constructor(timeScale: TimeScale, pixelBounds: [number, number]) {
+ super(timeScale);
+ this.pixelBounds = pixelBounds;
+ }
+
+ onDrag(x: number) {
+ let tStart =
+ this.timeScale.pxToTime(this.moveStart ? x : this.pixelBounds[0]);
+ let tEnd =
+ this.timeScale.pxToTime(!this.moveStart ? x : this.pixelBounds[1]);
+ if (tStart > tEnd) {
+ [tStart, tEnd] = [tEnd, tStart];
+ this.moveStart = !this.moveStart;
+ }
+ super.updateGlobals(tStart, tEnd);
+ }
+
+ onDragStart(x: number) {
+ this.moveStart =
+ Math.abs(x - this.pixelBounds[0]) < Math.abs(x - this.pixelBounds[1]);
+ }
+}
\ No newline at end of file
diff --git a/ui/src/frontend/drag/drag_strategy.ts b/ui/src/frontend/drag/drag_strategy.ts
new file mode 100644
index 0000000..1d272d7
--- /dev/null
+++ b/ui/src/frontend/drag/drag_strategy.ts
@@ -0,0 +1,34 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+import {TimeSpan} from '../../common/time';
+import {globals} from '../globals';
+import {TimeScale} from '../time_scale';
+
+export abstract class DragStrategy {
+ protected timeScale: TimeScale;
+
+ constructor(timeScale: TimeScale) {
+ this.timeScale = timeScale;
+ }
+
+ abstract onDrag(x: number): void;
+
+ abstract onDragStart(x: number): void;
+
+ protected updateGlobals(tStart: number, tEnd: number) {
+ const vizTime = new TimeSpan(tStart, tEnd);
+ globals.frontendLocalState.updateVisibleTime(vizTime);
+ globals.rafScheduler.scheduleRedraw();
+ }
+}
diff --git a/ui/src/frontend/drag/inner_drag_strategy.ts b/ui/src/frontend/drag/inner_drag_strategy.ts
new file mode 100644
index 0000000..a4a0d44
--- /dev/null
+++ b/ui/src/frontend/drag/inner_drag_strategy.ts
@@ -0,0 +1,36 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+import {TimeScale} from '../time_scale';
+import {DragStrategy} from './drag_strategy';
+
+export class InnerDragStrategy extends DragStrategy {
+ private dragStartPx = 0;
+ private pixelBounds: [number, number];
+
+ constructor(timeScale: TimeScale, pixelBounds: [number, number]) {
+ super(timeScale);
+ this.pixelBounds = pixelBounds;
+ }
+
+ onDrag(x: number) {
+ const move = x - this.dragStartPx;
+ const tStart = this.timeScale.pxToTime(this.pixelBounds[0] + move);
+ const tEnd = this.timeScale.pxToTime(this.pixelBounds[1] + move);
+ super.updateGlobals(tStart, tEnd);
+ }
+
+ onDragStart(x: number) {
+ this.dragStartPx = x;
+ }
+}
diff --git a/ui/src/frontend/drag/outer_drag_strategy.ts b/ui/src/frontend/drag/outer_drag_strategy.ts
new file mode 100644
index 0000000..bde417c
--- /dev/null
+++ b/ui/src/frontend/drag/outer_drag_strategy.ts
@@ -0,0 +1,29 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+import {DragStrategy} from './drag_strategy';
+
+export class OuterDragStrategy extends DragStrategy {
+ private dragStartPx = 0;
+
+ onDrag(x: number) {
+ let tStart = this.timeScale.pxToTime(this.dragStartPx);
+ let tEnd = this.timeScale.pxToTime(x);
+ if (tStart > tEnd) [tStart, tEnd] = [tEnd, tStart];
+ super.updateGlobals(tStart, tEnd);
+ }
+
+ onDragStart(x: number) {
+ this.dragStartPx = x;
+ }
+}
\ No newline at end of file
diff --git a/ui/src/frontend/frontend_local_state.ts b/ui/src/frontend/frontend_local_state.ts
index 9e51317..4349f81 100644
--- a/ui/src/frontend/frontend_local_state.ts
+++ b/ui/src/frontend/frontend_local_state.ts
@@ -267,6 +267,10 @@
this.ratelimitedUpdateVisible();
}
+ getVisibleStateBounds(): [number, number] {
+ return [this.visibleWindowTime.start, this.visibleWindowTime.end];
+ }
+
// Whenever start/end px of the timeScale is changed, update
// the resolution.
updateLocalLimits(pxStart: number, pxEnd: number) {
diff --git a/ui/src/frontend/overview_timeline_panel.ts b/ui/src/frontend/overview_timeline_panel.ts
index 23507ee..37fd1a9 100644
--- a/ui/src/frontend/overview_timeline_panel.ts
+++ b/ui/src/frontend/overview_timeline_panel.ts
@@ -19,6 +19,10 @@
import {TimeSpan, timeToString} from '../common/time';
import {TRACK_SHELL_WIDTH} from './css_constants';
+import {BorderDragStrategy} from './drag/border_drag_strategy';
+import {DragStrategy} from './drag/drag_strategy';
+import {InnerDragStrategy} from './drag/inner_drag_strategy';
+import {OuterDragStrategy} from './drag/outer_drag_strategy';
import {DragGestureHandler} from './drag_gesture_handler';
import {globals} from './globals';
import {Panel, PanelSize} from './panel';
@@ -26,10 +30,11 @@
export class OverviewTimelinePanel extends Panel {
private width = 0;
- private dragStartPx = 0;
private gesture?: DragGestureHandler;
private timeScale?: TimeScale;
private totTime = new TimeSpan(0, 0);
+ private static BORDER_PIXEL_DELTA = 30;
+ private dragStrategy?: DragStrategy;
// Must explicitly type now; arguments types are no longer auto-inferred.
// https://github.com/Microsoft/TypeScript/issues/1373
@@ -123,21 +128,33 @@
}
onDrag(x: number) {
- // Set visible time limits from selection.
- if (this.timeScale === undefined) return;
- let tStart = this.timeScale.pxToTime(this.dragStartPx);
- let tEnd = this.timeScale.pxToTime(x);
- if (tStart > tEnd) [tStart, tEnd] = [tEnd, tStart];
- const vizTime = new TimeSpan(tStart, tEnd);
- globals.frontendLocalState.updateVisibleTime(vizTime);
- globals.rafScheduler.scheduleRedraw();
+ if (this.dragStrategy === undefined) return;
+ this.dragStrategy.onDrag(x);
}
onDragStart(x: number) {
- this.dragStartPx = x;
+ if (this.timeScale === undefined) return;
+ const timeSpan = globals.frontendLocalState.getVisibleStateBounds();
+ const pixelBounds: [number, number] = [
+ this.timeScale.timeToPx(timeSpan[0]),
+ this.timeScale.timeToPx(timeSpan[1])
+ ];
+ if (OverviewTimelinePanel.inBorderRange(x, pixelBounds[0]) ||
+ OverviewTimelinePanel.inBorderRange(x, pixelBounds[1])) {
+ this.dragStrategy = new BorderDragStrategy(this.timeScale, pixelBounds);
+ } else if (x < pixelBounds[0] || pixelBounds[1] < x) {
+ this.dragStrategy = new OuterDragStrategy(this.timeScale);
+ } else {
+ this.dragStrategy = new InnerDragStrategy(this.timeScale, pixelBounds);
+ }
+ this.dragStrategy.onDragStart(x);
}
onDragEnd() {
- this.dragStartPx = 0;
+ this.dragStrategy = undefined;
+ }
+
+ private static inBorderRange(a: number, b: number): boolean {
+ return Math.abs(a - b) < this.BORDER_PIXEL_DELTA;
}
}