From 4a9e686816507c36ec80b1a133a981089d7cca70 Mon Sep 17 00:00:00 2001
From: Terry Truong <terry06890@gmail.com>
Date: Mon, 27 Jun 2022 01:41:18 +1000
Subject: Clean up code in SettingsModal

Add reduced-versions of developer options
Add input-range value indicators
---
 src/components/SettingsModal.vue | 278 +++++++++++++++++++++------------------
 1 file changed, 148 insertions(+), 130 deletions(-)

(limited to 'src/components/SettingsModal.vue')

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>
-- 
cgit v1.2.3

