aboutsummaryrefslogtreecommitdiff
path: root/src/components/SettingsModal.vue
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/SettingsModal.vue')
-rw-r--r--src/components/SettingsModal.vue278
1 files changed, 148 insertions, 130 deletions
diff --git a/src/components/SettingsModal.vue b/src/components/SettingsModal.vue
index a54fa58..83b42af 100644
--- a/src/components/SettingsModal.vue
+++ b/src/components/SettingsModal.vue
@@ -1,164 +1,182 @@
<script lang="ts">
+
import {defineComponent, PropType} from 'vue';
-import CloseIcon from './icon/CloseIcon.vue';
import RButton from './RButton.vue';
+import CloseIcon from './icon/CloseIcon.vue';
import {UiOptions} from '../lib';
import {LayoutOptions} from '../layout';
-// Displays configurable options, and sends option-change requests
export default defineComponent({
props: {
lytOpts: {type: Object as PropType<LayoutOptions>, required: true},
uiOpts: {type: Object as PropType<UiOptions>, required: true},
},
+ data(){
+ // For making subsets of various options' values available for user selection
+ let userLayoutTypeVals = [ // Holds pairs of labels with option values
+ ['Yes', 'sweep'],
+ ['No', 'rect']
+ ];
+ let userTileSpacingVals = [
+ ['Small', 6],
+ ['Medium', 10],
+ ['Large', 20]
+ ];
+ let userTileSizeVals = [
+ ['Default', 50, 200],
+ ['Small', 50, 50],
+ ['Medium', 100, 100],
+ ['Large', 200, 200],
+ ['Flexible', 0, 400],
+ ];
+ // Warn if user-available values don't include the active option value (indicates a developer mistake)
+ let layoutTypeIdx = userLayoutTypeVals.findIndex(([, optVal]) => optVal == this.lytOpts.layoutType);
+ if (layoutTypeIdx == -1){
+ console.log("WARNING: Initial layoutType option value not included in user setting values");
+ }
+ let tileSpacingIdx = userTileSpacingVals.findIndex(([, optVal]) => optVal == this.lytOpts.tileSpacing);
+ if (tileSpacingIdx == -1){
+ console.log("WARNING: Initial tileSpacing option value not included in user setting values");
+ }
+ let tileSizeValIdx = userTileSizeVals.findIndex(
+ ([, min, max]) => min == this.lytOpts.minTileSz && max == this.lytOpts.maxTileSz
+ );
+ if (tileSizeValIdx == -1){
+ console.log("WARNING: Initial minTileSz/maxTileSz option value not included in user setting values");
+ }
+ //
+ return {
+ userLayoutTypeVals,
+ userLayoutType: userLayoutTypeVals[layoutTypeIdx != -1 ? layoutTypeIdx : 0][0],
+ userTileSpacingVals,
+ userTileSpacing: userTileSpacingVals[tileSpacingIdx != -1 ? tileSpacingIdx : 0][0],
+ userTileSizeVals,
+ userTileSize: userTileSizeVals[tileSizeValIdx != -1 ? tileSizeValIdx : 0][0],
+ };
+ },
+ computed: {
+ styles(): Record<string,string> {
+ return {
+ backgroundColor: this.uiOpts.bgColorAlt,
+ borderRadius: this.uiOpts.borderRadius + 'px',
+ boxShadow: this.uiOpts.shadowNormal,
+ };
+ },
+ },
methods: {
- onCloseClick(evt: Event){
+ onClose(evt: Event){
if (evt.target == this.$el || (this.$refs.closeIcon as typeof CloseIcon).$el.contains(evt.target)){
this.$emit('close');
}
},
onSettingChg(setting: string){
- if (setting == 'minTileSz'){
- let minInput = this.$refs.minTileSzInput as HTMLInputElement;
- let maxInput = this.$refs.maxTileSzInput as HTMLInputElement;
- if (Number(minInput.value) > Number(maxInput.value)){
- this.lytOpts.maxTileSz = this.lytOpts.minTileSz;
- }
- } else if (setting == 'maxTileSz'){
- let minInput = this.$refs.minTileSzInput as HTMLInputElement;
- let maxInput = this.$refs.maxTileSzInput as HTMLInputElement;
- if (Number(maxInput.value) < Number(minInput.value)){
- this.lytOpts.minTileSz = this.lytOpts.maxTileSz;
- }
- }
this.$emit('setting-chg', setting);
},
- onReset(){
- this.$emit('reset');
+ },
+ watch: {
+ // Propagate option-subsetting user-settings to options
+ userLayoutType(newVal, oldVal){
+ let [,optVal] = this.userLayoutTypeVals.find(([val,]) => val == newVal)!;
+ this.lytOpts.layoutType = optVal as LayoutOptions['layoutType'];
+ },
+ userTileSpacing(newVal, oldVal){
+ let [,optVal] = this.userTileSpacingVals.find(([val,]) => val == newVal)!;
+ this.lytOpts.tileSpacing = optVal as LayoutOptions['tileSpacing'];
+ },
+ userTileSize(newVal, oldVal){
+ let [,min,max] = this.userTileSizeVals.find(([val,,]) => val == newVal)!;
+ this.lytOpts.minTileSz = min as LayoutOptions['minTileSz'];
+ this.lytOpts.maxTileSz = max as LayoutOptions['maxTileSz'];
},
},
- components: {CloseIcon, RButton, },
+ components: {RButton, CloseIcon, },
emits: ['close', 'setting-chg', 'reset', ],
});
</script>
<template>
-<div class="fixed left-0 top-0 w-full h-full bg-black/40" @click="onCloseClick">
- <div class="absolute left-1/2 -translate-x-1/2 w-4/5 top-1/2 -translate-y-1/2 max-h-[80%]
- p-3 bg-stone-50 visible rounded-md shadow shadow-black">
- <close-icon @click.stop="onCloseClick" ref="closeIcon"
+<div class="fixed left-0 top-0 w-full h-full bg-black/40" @click="onClose">
+ <div class="absolute left-1/2 -translate-x-1/2 top-1/2 -translate-y-1/2
+ min-w-[8cm] max-h-[80%] overflow-auto p-3" :style="styles">
+ <close-icon @click.stop="onClose" ref="closeIcon"
class="block absolute top-2 right-2 w-6 h-6 hover:cursor-pointer" />
<h1 class="text-xl font-bold mb-2">Settings</h1>
- <hr class="border-stone-400"/>
- <div>
- <label>Tile Spacing <input type="range" min="0" max="20" class="mx-2 w-[3cm]"
- v-model.number="lytOpts.tileSpacing" @input="onSettingChg('tileSpacing')"/></label>
- </div>
- <hr class="border-stone-400"/>
- <div>
- <label>
- <span class="inline-block w-[3cm]">Min Tile Size</span>
- <input type="range" min="0" max="400" v-model.number="lytOpts.minTileSz" class="w-[3cm]"
- @input="onSettingChg('minTileSz')" ref="minTileSzInput"/>
- </label>
- </div>
- <div>
- <label>
- <span class="inline-block w-[3cm]">Max Tile Size</span>
- <input type="range" min="0" max="400" v-model.number="lytOpts.maxTileSz" class="w-[3cm]"
- @input="onSettingChg('maxTileSz')" ref="maxTileSzInput"/>
- </label>
- </div>
- <hr class="border-stone-400"/>
- <div>
- Layout Method
- <ul>
- <li>
- <label> <input type="radio" v-model="lytOpts.layoutType" value="sqr"
- @change="onSettingChg('layoutType')"/> Squares </label>
- </li>
- <li>
- <label> <input type="radio" v-model="lytOpts.layoutType" value="rect"
- @change="onSettingChg('layoutType')"/> Rectangles </label>
- </li>
- <li>
- <label> <input type="radio" v-model="lytOpts.layoutType" value="sweep"
- @change="onSettingChg('layoutType')"/> Sweep to side </label>
- </li>
- </ul>
- </div>
- <hr class="border-stone-400"/>
- <div>
- Sweep to parent
- <ul>
- <li>
- <label> <input type="radio" v-model="lytOpts.sweepToParent" value="none"
- @change="onSettingChg('sweepToParent')"/> None </label>
- </li>
- <li>
- <label> <input type="radio" v-model="lytOpts.sweepToParent" value="prefer"
- @change="onSettingChg('sweepToParent')"/> Prefer </label>
- </li>
- <li>
- <label> <input type="radio" v-model="lytOpts.sweepToParent" value="fallback"
- @change="onSettingChg('sweepToParent')"/> Fallback </label>
- </li>
- </ul>
- </div>
- <hr class="border-stone-400"/>
- <div>
- Sweep Mode
- <ul>
- <li>
- <label> <input type="radio" v-model="lytOpts.sweepMode" value="left"
- @change="onSettingChg('sweepMode')"/> To left </label>
- </li>
- <li>
- <label> <input type="radio" v-model="lytOpts.sweepMode" value="top"
- @change="onSettingChg('sweepMode')"/> To top </label>
- </li>
- <li>
- <label> <input type="radio" v-model="lytOpts.sweepMode" value="shorter"
- @change="onSettingChg('sweepMode')"/> To shorter </label>
- </li>
- <li>
- <label> <input type="radio" v-model="lytOpts.sweepMode" value="auto"
- @change="onSettingChg('sweepMode')"/> Auto </label>
- </li>
- </ul>
- </div>
- <hr class="border-stone-400"/>
- <div>
- <label>Animation Duration <input type="range" min="0" max="3000" class="mx-2 w-[3cm]"
- v-model.number="uiOpts.transitionDuration" @change="onSettingChg('transitionDuration')"/></label>
- </div>
- <hr class="border-stone-400"/>
- <div>
- <label>
- <input type="checkbox" v-model="uiOpts.searchJumpMode" @change="onSettingChg('searchJumpMode')"/>
- Jump to search result
- </label>
+ <div class="border rounded">
+ <h2 class="text-center">Layout</h2>
+ <div class="grid grid-cols-2 gap-2">
+ <div>
+ Sweep leaves to side
+ <ul>
+ <li v-for="[val,] in userLayoutTypeVals">
+ <label> <input type="radio" v-model="userLayoutType" :value="val"
+ @change="onSettingChg('layoutType')"/> {{val}} </label>
+ </li>
+ </ul>
+ </div>
+ <div>
+ Sweep into parent
+ <ul>
+ <li> <label> <input type="radio" :disabled="lytOpts.layoutType != 'sweep'"
+ v-model="lytOpts.sweepToParent" value="none"
+ @change="onSettingChg('sweepToParent')"/> Never </label> </li>
+ <li> <label> <input type="radio" :disabled="lytOpts.layoutType != 'sweep'"
+ v-model="lytOpts.sweepToParent" value="prefer"
+ @change="onSettingChg('sweepToParent')"/> Always </label> </li>
+ <li> <label> <input type="radio" :disabled="lytOpts.layoutType != 'sweep'"
+ v-model="lytOpts.sweepToParent" value="fallback"
+ @change="onSettingChg('sweepToParent')"/> If needed </label> </li>
+ </ul>
+ </div>
+ <div>
+ Tile Spacing
+ <ul>
+ <li v-for="[val,] in userTileSpacingVals">
+ <label> <input type="radio" v-model="userTileSpacing" :value="val"
+ @change="onSettingChg('tileSpacing')"/> {{val}} </label>
+ </li>
+ </ul>
+ </div>
+ <div>
+ Tile Size
+ <ul>
+ <li v-for="[val,,] in userTileSizeVals">
+ <label> <input type="radio" v-model="userTileSize" :value="val"
+ @change="onSettingChg('minTileSz'), onSettingChg('maxTileSz')"/> {{val}} </label>
+ </li>
+ </ul>
+ </div>
+ </div>
</div>
- <hr class="border-stone-400"/>
- <div>
- Tree
- <ul>
- <li>
- <label> <input type="radio" v-model="uiOpts.useReducedTree" :value="false"
- @change="onSettingChg('useReducedTree')"/> Default </label>
- </li>
- <li>
- <label> <input type="radio" v-model="uiOpts.useReducedTree" :value="true"
- @change="onSettingChg('useReducedTree')"/> Reduced </label>
- </li>
- </ul>
+ <div class="border rounded">
+ <h2 class="text-center">Timing</h2>
+ <div class="grid grid-cols-3">
+ <!-- Row 1 -->
+ <label for="animationTimeInput">Animation Time</label>
+ <input type="range" min="0" max="3000" class="my-auto" name="animationTimeInput"
+ v-model.number="uiOpts.transitionDuration" @change="onSettingChg('transitionDuration')"/>
+ <div class="my-auto">{{uiOpts.transitionDuration}} ms</div>
+ <!-- Row 2 -->
+ <label for="autoModeDelayInput">Auo-mode Delay</label>
+ <input type="range" min="0" max="3000" class="my-auto" name="autoModeDelayInput"
+ v-model.number="uiOpts.autoActionDelay" @change="onSettingChg('autoActionDelay')"/>
+ <div class="my-auto">{{uiOpts.autoActionDelay}} ms</div>
+ </div>
</div>
- <hr class="border-stone-400"/>
- <div class="flex justify-around mt-2">
- <r-button class="bg-stone-800 text-white" @click="onReset">
- Reset
- </r-button>
+ <div class="border rounded">
+ <h2 class="text-center">Other</h2>
+ <div>
+ <label> <input type="checkbox" v-model="uiOpts.useReducedTree"
+ @change="onSettingChg('useReducedTree')"/> Use simplified tree </label>
+ </div>
+ <div>
+ <label> <input type="checkbox" v-model="uiOpts.searchJumpMode"
+ @change="onSettingChg('searchJumpMode')"/> Skip search animation </label>
+ </div>
</div>
+ <r-button class="mx-auto mt-2" :style="{color: uiOpts.textColor, backgroundColor: uiOpts.bgColor}"
+ @click="$emit('reset')">
+ Reset
+ </r-button>
</div>
</div>
</template>