diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/App.vue | 73 | ||||
| -rw-r--r-- | src/components/TutorialPane.vue | 42 | ||||
| -rw-r--r-- | src/lib.ts | 18 |
3 files changed, 49 insertions, 84 deletions
diff --git a/src/App.vue b/src/App.vue index cc106fe..a72bff2 100644 --- a/src/App.vue +++ b/src/App.vue @@ -18,18 +18,18 @@ import type {TolMap} from './tol'; import {TolNode} from './tol'; import {LayoutNode, initLayoutTree, initLayoutMap, tryLayout} from './layout'; import type {LayoutOptions, LayoutTreeChg} from './layout'; -import {EnabledFeatures, arraySum, randWeightedChoice, getScrollBarWidth} from './lib'; +import {arraySum, randWeightedChoice, getScrollBarWidth} from './lib'; +import type {Action} from './lib'; // Note: Import paths lack a .ts or .js extension because .ts makes vue-tsc complain, and .js makes vite complain // Type representing auto-mode actions -type Action = 'move across' | 'move down' | 'move up' | - 'expand' | 'collapse' | 'expand to view' | 'expand ancestry bar'; +type AutoAction = 'move across' | 'move down' | 'move up' | Action; // Used in auto-mode to help avoid action cycles -function getReverseAction(action: Action): Action | null { - let reversePairs: Action[][] = [ +function getReverseAction(action: AutoAction): AutoAction | null { + let reversePairs: AutoAction[][] = [ ['move down', 'move up'], ['expand', 'collapse'], - ['expand to view', 'expand ancestry bar'], + ['expandToView', 'unhideAncestor'], ]; let pair = reversePairs.find(pair => pair.includes(action)); if (pair != null){ @@ -110,14 +110,14 @@ export default defineComponent({ settingsOpen: false, tutorialOpen: true, tutorialFirstRun: true, - enabledFeatures: new EnabledFeatures(), - tutTriggerFeature: null as string | null, - tutTrigger: false, + disabledActions: new Set(), + tutTriggerAction: null as Action | null, + tutTriggerFlag: false, // For search and auto-mode modeRunning: false, lastFocused: null as LayoutNode | null, // For auto-mode - autoPrevAction: null as Action | null, // Used to help prevent action cycles + autoPrevAction: null as AutoAction | null, // Used to help prevent action cycles autoPrevActionFail: false, // Used to avoid re-trying a failed expand/collapse // Options lytOpts: {...defaultLytOpts}, @@ -367,7 +367,7 @@ export default defineComponent({ }, // For tile-info events onInfoIconClick(nodeName: string){ - if (this.tutorialOpen && !this.handleActionForTutorial('infoIcon')){ + if (this.tutorialOpen && !this.handleActionForTutorial('tileInfo')){ return; } if (!this.searchOpen){ @@ -471,7 +471,7 @@ export default defineComponent({ setTimeout(this.autoAction, this.uiOpts.autoWaitTime); } else { // Determine available actions - let action: Action | null; + let action: AutoAction | null; let actionWeights: {[key: string]: number}; // Maps actions to choice weights let node: LayoutNode = this.lastFocused; if (node.children.length == 0){ @@ -489,7 +489,7 @@ export default defineComponent({ } else { actionWeights = { 'move across': 1, 'move down': 2, 'move up': 1, - 'collapse': 1, 'expand to view': 1, 'expand ancestry bar': 1 + 'collapse': 1, 'expandToView': 1, 'unhideAncestor': 1 }; // Zero weights for disallowed actions if (node == this.activeRoot || node.parent!.children.length == 1){ @@ -502,10 +502,10 @@ export default defineComponent({ actionWeights['collapse'] = 0; // Only collapse if all children are leaves } if (node.parent != this.activeRoot){ - actionWeights['expand to view'] = 0; // Only expand-to-view if direct child of activeRoot + actionWeights['expandToView'] = 0; // Only expand-to-view if direct child of activeRoot } if (this.activeRoot.parent == null || node != this.activeRoot){ - actionWeights['expand ancestry bar'] = 0; // Only expand ancestry-bar if able and activeRoot + actionWeights['unhideAncestor'] = 0; // Only expand ancestry-bar if able and activeRoot } } if (this.autoPrevAction != null){ // Avoid undoing previous action @@ -523,7 +523,7 @@ export default defineComponent({ if (arraySum(weightList) == 0){ action = null; } else { - action = actionList[randWeightedChoice(weightList)!] as Action; + action = actionList[randWeightedChoice(weightList)!] as AutoAction; } // Perform action this.autoPrevActionFail = false; @@ -548,10 +548,10 @@ export default defineComponent({ case 'collapse': this.autoPrevActionFail = !this.onNonleafClick(node); break; - case 'expand to view': + case 'expandToView': this.onNonleafClickHeld(node); break; - case 'expand ancestry bar': + case 'unhideAncestor': this.onDetachedAncestorClick(node.parent!); break; } @@ -599,13 +599,21 @@ export default defineComponent({ onTutorialClose(){ this.tutorialOpen = false; this.tutorialFirstRun = false; - this.enabledFeatures = new EnabledFeatures(); + this.disabledActions.clear(); tryLayout(this.activeRoot, this.tileAreaPos, this.tileAreaDims, this.lytOpts, {allowCollapse: true, layoutMap: this.layoutMap}); }, - onTutStageChg(data: {enabledFeatures: EnabledFeatures, tutTriggerFeature: string}){ - this.enabledFeatures = data.enabledFeatures; - this.tutTriggerFeature = data.tutTriggerFeature; + onTutStageChg(disabledActions: Set<Action>, triggerAction: Action | null){ + this.disabledActions = disabledActions; + this.tutTriggerAction = triggerAction; + }, + handleActionForTutorial(action: Action): boolean { + // Tell TutorialPane if trigger-action was done + if (this.tutTriggerAction == action){ + this.tutTriggerFlag = !this.tutTriggerFlag; + } + // Indicate whether the action is allowed + return !this.disabledActions.has(action); }, // For other events onResize(){ @@ -668,23 +676,6 @@ export default defineComponent({ node.hasFocus = true; } }, - handleActionForTutorial(action: string): boolean { - if (this.tutTriggerFeature == action){ - this.tutTrigger = !this.tutTrigger; - } - switch (action){ - case 'expand': return this.enabledFeatures.expand; - case 'collapse': return this.enabledFeatures.collapse; - case 'expandToView': return this.enabledFeatures.expandToView; - case 'unhideAncestor': return this.enabledFeatures.unhideAncestor; - case 'infoIcon': return this.enabledFeatures.infoIcon; - case 'search': return this.enabledFeatures.search; - case 'autoMode': return this.enabledFeatures.autoMode; - case 'settings': return this.enabledFeatures.settings; - case 'help': return this.enabledFeatures.help; - } - return false; - }, }, created(){ window.addEventListener('resize', this.onResize); @@ -718,8 +709,8 @@ export default defineComponent({ :tolMap="tolMap" :lytOpts="lytOpts" :uiOpts="uiOpts" @detached-ancestor-click="onDetachedAncestorClick" @info-icon-click="onInfoIconClick"/> <tutorial-pane v-if="tutorialOpen" - :skipWelcome="!tutorialFirstRun" :pos="[0,0]" :dims="tutorialPaneDims" :uiOpts="uiOpts" :triggerFlag="tutTrigger" - @tutorial-close="onTutorialClose" @tutorial-stage-chg="onTutStageChg"/> + :pos="[0,0]" :dims="tutorialPaneDims" :uiOpts="uiOpts" :triggerFlag="tutTriggerFlag" + :skipWelcome="!tutorialFirstRun" @tutorial-close="onTutorialClose" @tutorial-stage-chg="onTutStageChg"/> <!-- Icons --> <search-icon @click="onSearchIconClick" class="absolute bottom-[6px] right-[78px] w-[18px] h-[18px] diff --git a/src/components/TutorialPane.vue b/src/components/TutorialPane.vue index c837d5f..c04aeee 100644 --- a/src/components/TutorialPane.vue +++ b/src/components/TutorialPane.vue @@ -1,15 +1,15 @@ <script lang="ts"> import {defineComponent, PropType} from 'vue'; import CloseIcon from './icon/CloseIcon.vue'; -import {EnabledFeatures} from '../lib'; +import {Action} from '../lib'; export default defineComponent({ props: { - skipWelcome: {type: Boolean, default: false}, pos: {type: Array as unknown as PropType<[number,number]>, required: true}, dims: {type: Array as unknown as PropType<[number,number]>, required: true}, uiOpts: {type: Object, required: true}, triggerFlag: {type: Boolean, required: true}, + skipWelcome: {type: Boolean, default: false}, }, data(){ return { @@ -70,37 +70,21 @@ export default defineComponent({ this.sendEnabledFeatures(); }, onClose(){ - this.$emit('tutorial-stage-chg', {enabledFeatures: new EnabledFeatures(), tutTriggerFeature: null}); this.$emit('tutorial-close'); }, sendEnabledFeatures(){ - let ef = new EnabledFeatures(); - switch (this.stage){ - case 1: - case 2: ef.collapse = false; - case 3: ef.expandToView = false; - case 4: ef.unhideAncestor = false; - case 5: ef.infoIcon = false; - case 6: ef.search = false; - case 7: ef.autoMode = false; - case 8: ef.settings = false; - case 9: ef.help = false; - case 10: - } - let tf = null; - switch (this.stage){ - case 1: - case 2: tf = 'expand'; break; - case 3: tf = 'collapse'; break; - case 4: tf = 'expandToView'; break; - case 5: tf = 'unhideAncestor'; break; - case 6: tf = 'infoIcon'; break; - case 7: tf = 'search'; break; - case 8: tf = 'autoMode'; break; - case 9: tf = 'settings'; break; - case 10: tf = 'help'; break; + const stageActions = [ + null, + 'expand', 'expand', 'collapse', 'expandToView', 'unhideAncestor', + 'tileInfo', 'search', 'autoMode', 'settings', 'help' + ] as (Action | null)[]; + let disabledActions = new Set() as Set<Action>; + for (let i = this.stage + 1; i < this.maxStage; i++){ + disabledActions.add(stageActions[i] as Action); } - this.$emit('tutorial-stage-chg', {enabledFeatures: ef, tutTriggerFeature: tf}); + disabledActions.delete(stageActions[this.stage] as Action); + let triggerAction = stageActions[this.stage] as Action; + this.$emit('tutorial-stage-chg', disabledActions, triggerAction); }, }, created(){ @@ -2,20 +2,10 @@ /* * Types */ -export class EnabledFeatures { - // Expand/collapse - expand = true; - collapse = true; - // AncestorBar related - expandToView = true; - unhideAncestor = true; - // Other - infoIcon = true; - search = true; - autoMode = true; - settings = true; - help = true; -}; +// Used by auto-mode and tutorial +export type Action = + 'expand' | 'collapse' | 'expandToView' | 'unhideAncestor' | + 'tileInfo' | 'search' | 'autoMode' | 'settings' | 'help'; /* * General utility functions |
