aboutsummaryrefslogtreecommitdiff
path: root/src/App.vue
diff options
context:
space:
mode:
authorTerry Truong <terry06890@gmail.com>2023-01-06 23:58:25 +1100
committerTerry Truong <terry06890@gmail.com>2023-01-06 23:58:25 +1100
commit3a66879b889dce85d7498e216980a2c08288b36f (patch)
treeb6967865e64bf3d61f80feea00b6a180553331bb /src/App.vue
parentd5b2c3d55b614914331525801ffb38ce824a5e8f (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/App.vue')
-rw-r--r--src/App.vue68
1 files changed, 55 insertions, 13 deletions
diff --git a/src/App.vue b/src/App.vue
index 960e648..803b53a 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -2,7 +2,7 @@
<div class="absolute left-0 top-0 w-screen h-screen overflow-hidden flex flex-col">
<!-- Title bar -->
<div class="flex gap-2 p-2" :style="{backgroundColor: store.color.bgDark2}">
- <h1 class="my-auto ml-2 text-4xl" :style="{color: store.color.altDark}">Histplorer</h1>
+ <h1 class="my-auto sm:ml-2 text-3xl sm:text-4xl" :style="{color: store.color.altDark}">Histplorer</h1>
<div class="mx-auto"/> <!-- Spacer -->
<!-- Icons -->
<icon-button :size="45" :style="buttonStyles" @click="helpOpen = true" title="Show help info">
@@ -23,10 +23,11 @@
:style="{backgroundColor: store.color.bg}" ref="contentAreaRef">
<time-line v-for="(state, idx) in timelines" :key="state.id"
:vert="vert" :initialState="state" :closeable="timelines.length > 1"
- :eventTree="eventTree" :unitCountMaps="unitCountMaps" :searchTarget="timelineTargets[idx]"
+ :eventTree="eventTree" :unitCountMaps="unitCountMaps"
+ :current="idx == currentTimelineIdx && !modalOpen" :searchTarget="timelineTargets[idx]"
class="grow basis-full min-h-0 outline outline-1"
@close="onTimelineClose(idx)" @state-chg="onTimelineChg($event, idx)" @event-display="onEventDisplay"
- @info-click="onInfoClick"/>
+ @info-click="onInfoClick" @pointerenter="currentTimelineIdx = idx"/>
<base-line :vert="vert" :timelines="timelines" class='m-1 sm:m-2'/>
</div>
<!-- Modals -->
@@ -87,23 +88,24 @@ onMounted(updateAreaDims);
// Timeline data
const timelines: Ref<TimelineState[]> = ref([]);
+const currentTimelineIdx = ref(0);
let nextTimelineId = 1;
function addTimeline(){
if (timelines.value.length == 0){
timelines.value.push(new TimelineState(nextTimelineId, store.initialStartDate, store.initialEndDate));
} else {
- let last = timelines.value[timelines.value.length - 1];
- timelines.value.push(new TimelineState(
- nextTimelineId, last.startDate,
- last.endDate, last.startOffset, last.endOffset, last.scaleIdx
- ));
+ let state = timelines.value[currentTimelineIdx.value];
+ timelines.value.splice(currentTimelineIdx.value, 0, new TimelineState(
+ nextTimelineId, state.startDate, state.endDate, state.startOffset, state.endOffset, state.scaleIdx));
}
- timelineTargets.value.push([null, false]);
- nextTimelineId++;
+ timelineTargets.value.splice(currentTimelineIdx.value, 0, [null, false]);
+ currentTimelineIdx.value += 1;
+ nextTimelineId += 1;
}
onMounted(addTimeline);
function onTimelineChg(state: TimelineState, idx: number){
timelines.value[idx] = state;
+ currentTimelineIdx.value = idx;
}
// For timeline addition/removal
@@ -123,6 +125,9 @@ function onTimelineClose(idx: number){
}
timelines.value.splice(idx, 1);
timelineTargets.value.splice(idx, 1);
+ if (currentTimelineIdx.value >= idx){
+ currentTimelineIdx.value = Math.max(0, idx - 1);
+ }
}
// For storing and looking up events
@@ -319,9 +324,8 @@ const timelineTargets = ref([] as [HistEvent | null, boolean][]); // For communi
function onSearch(event: HistEvent){
searchOpen.value = false;
// Trigger jump in endmost timeline
- let timelineIdx = timelineTargets.value.length - 1;
- let oldFlag = timelineTargets.value[timelineIdx];
- timelineTargets.value.splice(timelineIdx, 1, [event, !oldFlag[1]]);
+ let oldVal = timelineTargets.value[currentTimelineIdx.value];
+ timelineTargets.value.splice(currentTimelineIdx.value, 1, [event, !oldVal[1]]);
}
// For settings modal
@@ -330,6 +334,10 @@ const settingsOpen = ref(false);
// For help modal
const helpOpen = ref(false);
+//
+const modalOpen = computed(() =>
+ (infoModalData.value != null || searchOpen.value || settingsOpen.value || helpOpen.value));
+
// For resize handling
let lastResizeHdlrTime = 0; // Used to throttle resize handling
let afterResizeHdlr = 0; // Used to trigger handler after ending a run of resize events
@@ -366,6 +374,10 @@ function onKeyDown(evt: KeyboardEvent){
infoModalData.value = null;
} else if (searchOpen.value){
searchOpen.value = false;
+ } else if (settingsOpen.value){
+ settingsOpen.value = false;
+ } else if (helpOpen.value){
+ helpOpen.value = false;
}
} else if (evt.key == 'f' && evt.ctrlKey){
evt.preventDefault();
@@ -373,6 +385,36 @@ function onKeyDown(evt: KeyboardEvent){
if (!searchOpen.value){
searchOpen.value = true;
}
+ } else if (evt.key.startsWith('Arrow') && !modalOpen.value && !evt.shiftKey){
+ if (evt.key == 'ArrowUp'){
+ if (!vert.value){
+ if (currentTimelineIdx.value > 0){
+ currentTimelineIdx.value -= 1;
+ }
+ }
+ } else if (evt.key == 'ArrowDown'){
+ if (!vert.value){
+ if (currentTimelineIdx.value < timelines.value.length - 1){
+ currentTimelineIdx.value += 1;
+ }
+ }
+ } else if (evt.key == 'ArrowLeft'){
+ if (vert.value){
+ if (currentTimelineIdx.value > 0){
+ currentTimelineIdx.value -= 1;
+ }
+ }
+ } else if (evt.key == 'ArrowRight'){
+ if (vert.value){
+ if (currentTimelineIdx.value < timelines.value.length - 1){
+ currentTimelineIdx.value += 1;
+ }
+ }
+ }
+ } else if (evt.key == '+' && !modalOpen.value){
+ onTimelineAdd();
+ } else if (evt.key == 'Delete' && !modalOpen.value){
+ onTimelineClose(currentTimelineIdx.value);
}
}
onMounted(() => {