diff options
| author | Terry Truong <terry06890@gmail.com> | 2023-01-06 23:58:25 +1100 |
|---|---|---|
| committer | Terry Truong <terry06890@gmail.com> | 2023-01-06 23:58:25 +1100 |
| commit | 3a66879b889dce85d7498e216980a2c08288b36f (patch) | |
| tree | b6967865e64bf3d61f80feea00b6a180553331bb /src/components | |
| parent | d5b2c3d55b614914331525801ffb38ce824a5e8f (diff) | |
Keep track of a 'current' timeline
Make timeline addition and searching use the current timeline.
Add keyboard controls for timeline panning, zooming, switching, opening, and closing.
Fix zoomTimeline() bug when not centering zoom on pointer.
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/TimeLine.vue | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/src/components/TimeLine.vue b/src/components/TimeLine.vue index 1583aef..d6bb36a 100644 --- a/src/components/TimeLine.vue +++ b/src/components/TimeLine.vue @@ -58,7 +58,7 @@ </div> </div> <!-- Timeline position label --> - <div class="absolute top-2 left-2 z-20 text-lg text-stone-50"> + <div class="absolute top-2 left-2 z-20 text-lg" :class="[current ? 'text-yellow-300' : 'text-stone-50']"> {{timelinePosStr}} </div> <!-- Buttons --> @@ -71,7 +71,7 @@ </template> <script setup lang="ts"> -import {ref, onMounted, computed, watch, watchEffect, PropType, Ref, shallowRef, ShallowRef} from 'vue'; +import {ref, onMounted, onUnmounted, computed, watch, watchEffect, PropType, Ref, shallowRef, ShallowRef} from 'vue'; // Components import IconButton from './IconButton.vue'; // Icons @@ -98,6 +98,7 @@ const props = defineProps({ initialState: {type: Object as PropType<TimelineState>, required: true}, eventTree: {type: Object as PropType<RBTree<HistEvent>>, required: true}, unitCountMaps: {type: Object as PropType<Map<number, number>[]>, required: true}, + current: {type: Boolean, required: true}, searchTarget: {type: Object as PropType<[null | HistEvent, boolean]>, required: true}, }); const emit = defineEmits(['close', 'state-chg', 'event-display', 'info-click']); @@ -820,7 +821,7 @@ function panTimeline(scrollRatio: number){ startOffset.value = newStartOffset; endOffset.value = newEndOffset; } -function zoomTimeline(zoomRatio: number){ +function zoomTimeline(zoomRatio: number, ignorePointer=false){ if (zoomRatio > 1 && startDate.value.equals(MIN_DATE, scale.value) && endDate.value.equals(MAX_DATE, scale.value)){ @@ -833,9 +834,9 @@ function zoomTimeline(zoomRatio: number){ let startChg: number; let endChg: number; let ptrOffset = props.vert ? pointerY : pointerX; - if (ptrOffset == null){ + if (ptrOffset == null || ignorePointer){ let unitChg = newNumUnits - numUnits; - startChg = unitChg / 2; + startChg = -unitChg / 2; endChg = unitChg / 2; } else { // Pointer-centered zoom // Get element-relative ptrOffset @@ -1122,7 +1123,7 @@ function onStateChg(){ ID, startDate.value, endDate.value, startOffset.value, endOffset.value, scaleIdx.value )); } -watch(firstDate, onStateChg); +watch(startDate, onStateChg); // For jumping to search result const searchEvent = ref(null as null | HistEvent); // Holds most recent search result @@ -1163,6 +1164,40 @@ watch(() => props.searchTarget, () => { searchEvent.value = event; }); +// For keyboard shortcuts +function onKeyDown(evt: KeyboardEvent){ + if (!props.current || store.disableShortcuts){ + return; + } + if (evt.key == 'ArrowUp'){ + if (evt.shiftKey){ + zoomTimeline(1/store.zoomRatio, true); + } else if (props.vert){ + panTimeline(-store.scrollRatio); + } + } else if (evt.key == 'ArrowDown'){ + if (evt.shiftKey){ + zoomTimeline(store.zoomRatio, true); + } else if (props.vert){ + panTimeline(store.scrollRatio); + } + } else if (evt.key == 'ArrowLeft'){ + if (!props.vert){ + panTimeline(-store.scrollRatio); + } + } else if (evt.key == 'ArrowRight'){ + if (!props.vert){ + panTimeline(store.scrollRatio); + } + } +} +onMounted(() => { + window.addEventListener('keydown', onKeyDown); +}); +onUnmounted(() => { + window.removeEventListener('keydown', onKeyDown); +}); + // For skipping transitions on startup (and on horz/vert swap) const skipTransition = ref(true); onMounted(() => setTimeout(() => {skipTransition.value = false}, 100)); |
