massive Shape rework: keep both tvPoints/Props and ourPoints/Props; delegate model updates to subclasses; DCA/VLine working but Ladder/HLine not done.
This commit is contained in:
@@ -1,28 +1,65 @@
|
||||
<template>
|
||||
<div :key="builder.id">
|
||||
<v-card-text :color="titleColor">
|
||||
<slot name="title"><span>Unimplemented</span></slot>
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
<slot name="text">
|
||||
Unimplemented builder panel
|
||||
</slot>
|
||||
<div><v-btn variant="tonal" color="error" @click="co.removeBuilder(builder)" prepend-icon="mdi-delete">DELETE</v-btn></div>
|
||||
</v-card-text>
|
||||
</div>
|
||||
<row-bar :color="builder.color">
|
||||
<color-band :color="builder.color"/>
|
||||
<slot/>
|
||||
<div class="align-self-center">
|
||||
<v-menu>
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn variant="plain" v-bind="props" icon="mdi-dots-vertical"/>
|
||||
</template>
|
||||
<v-list>
|
||||
<!-- <v-list-subheader :title="'Limit '+ (lineAPrice?lineAPrice.toPrecision(5):'')"/>-->
|
||||
<v-list-item title="Delete" key="withdraw" value="withdraw" prepend-icon="mdi-delete" color="red"
|
||||
@click="deleteMyBuilder"/>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</div>
|
||||
</row-bar>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {useChartOrderStore} from "@/orderbuild.js";
|
||||
import {computed} from "vue";
|
||||
import {builderFuncs, deleteBuilder, useChartOrderStore} from "@/orderbuild.js";
|
||||
import ColorBand from "@/components/chart/ColorBand.vue";
|
||||
import RowBar from "@/components/chart/RowBar.vue";
|
||||
import {onBeforeUnmount, onMounted, onUnmounted, onUpdated, watchEffect} from "vue";
|
||||
|
||||
const props = defineProps(['builder', 'color', 'colorTag'])
|
||||
const props = defineProps({
|
||||
order: Object,
|
||||
builder: Object,
|
||||
buildTranches: {type: Function},
|
||||
adjustShapes: {type: Function, default: null},
|
||||
deleteShapes: {type: Function, default: null},
|
||||
})
|
||||
const emit = defineEmits(['update:builder'])
|
||||
const co = useChartOrderStore()
|
||||
|
||||
const titleColor = computed(()=>props.color ? props.color : props.colorTag ? props.builder.props[props.colorTag]?.linecolor : props.builder.props.a.linecolor )
|
||||
|
||||
let lastId = props.builder.id
|
||||
builderFuncs[props.builder.id] = props.buildTranches
|
||||
onUpdated(()=>{
|
||||
if (lastId !== props.builder.id ) {
|
||||
delete builderFuncs[lastId]
|
||||
builderFuncs[props.builder.id] = props.buildTranches
|
||||
lastId = props.builder.id
|
||||
}
|
||||
})
|
||||
onUnmounted(() => delete builderFuncs[lastId])
|
||||
|
||||
if (props.adjustShapes) {
|
||||
watchEffect(props.adjustShapes)
|
||||
onMounted(props.adjustShapes)
|
||||
}
|
||||
|
||||
if (props.deleteShapes)
|
||||
onBeforeUnmount(props.deleteShapes)
|
||||
|
||||
function deleteMyBuilder() {
|
||||
deleteBuilder(props.order, props.builder);
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<div class="my-3">
|
||||
<div v-if="order.builders.length===0"> <!--todo remove gralpha limitation of one builder-->
|
||||
<span :style="colorStyle" class="ma-3">Add condition:</span>
|
||||
<!-- <v-btn variant="flat" prepend-icon="mdi-clock-outline" @click="build('DCABuilder')">DCA</v-btn>-->
|
||||
<v-btn :color="color" variant="text" prepend-icon="mdi-clock-outline" @click="build(order,'DCABuilder')">DCA</v-btn>
|
||||
<v-btn :color="color" variant="text" prepend-icon="mdi-ray-vertex" @click="build(order,'LimitBuilder')">Limit</v-btn>
|
||||
<!-- <v-btn variant="flat" prepend-icon="mdi-vector-line">Line</v-btn>-->
|
||||
<!--
|
||||
|
||||
@@ -1,33 +1,158 @@
|
||||
<template>
|
||||
<builder-panel :builder="builder">
|
||||
<template v-slot:title>
|
||||
<span>DCA</span>
|
||||
<span v-if="!builder.points">Draw your timeframe on the chart!</span>
|
||||
</template>
|
||||
<template v-slot:text>
|
||||
<input type="number" min="1" max="2">
|
||||
</template>
|
||||
</builder-panel>
|
||||
<rung-builder name='DCA' :order="order" :builder="builder"
|
||||
v-model:value-a="absTimeA" v-model:value-b="absTimeB" :mode="1" :shape="VLine"
|
||||
:get-model-value="getModelValue" :set-model-value="setModelValue" :set-values="setValues"
|
||||
:std-width="stdWidth" :build-tranches="buildTranches">
|
||||
<v-list style="background-color: inherit">
|
||||
<v-list-item v-for="t in absoluteTimes">{{t}}</v-list-item>
|
||||
</v-list>
|
||||
</rung-builder>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import BuilderPanel from "@/components/chart/BuilderPanel.vue";
|
||||
import {drawShape, ShapeCallback, VerboseCallback} from "@/charts/chart.js";
|
||||
import {prototype} from "@/common.js";
|
||||
import {ShapeType} from "@/charts/shape.js";
|
||||
import {builderDefaults, MIN_EXECUTION_TIME, useChartOrderStore} from "@/orderbuild.js";
|
||||
import {VLine} from "@/charts/shape.js";
|
||||
import {sideColor} from "@/misc.js";
|
||||
import {useTheme} from "vuetify";
|
||||
import {useOrderStore, useStore} from "@/store/store.js";
|
||||
import {DISTANT_FUTURE, MAX_FRACTION, newTranche} from "@/blockchain/orderlib.js";
|
||||
import RungBuilder from "@/components/chart/RungBuilder.vue";
|
||||
import {computed, ref} from "vue";
|
||||
|
||||
const props = defineProps(['builder'])
|
||||
const s = useStore()
|
||||
const os = useOrderStore()
|
||||
const co = useChartOrderStore()
|
||||
const theme = useTheme().current
|
||||
const props = defineProps(['order', 'builder'])
|
||||
|
||||
const DCAArtist = prototype(VerboseCallback, {
|
||||
onDraw(widget, chart) { console.log('dca start draw') },
|
||||
onCreate(widget, chart) { console.log('dca start draw') },
|
||||
const stdWidth = computed(()=>10 * co.intervalSecs)
|
||||
|
||||
function computeDefaultColor() {
|
||||
const index = props.order.builders.indexOf(props.builder)
|
||||
return sideColor(props.order.buy, index)
|
||||
}
|
||||
|
||||
const defaultColor = computeDefaultColor()
|
||||
|
||||
// Fields must be defined in order to be reactive
|
||||
builderDefaults(props.builder, {
|
||||
timeA: s.clock, // todo 0
|
||||
timeB: null,
|
||||
// relative: true,
|
||||
relative: false, // todo
|
||||
rungs: 1,
|
||||
skew: 0,
|
||||
color: defaultColor,
|
||||
})
|
||||
|
||||
drawShape(ShapeType.VLine, prototype(DCAArtist, {}))
|
||||
const rawTimes = ref([])
|
||||
const times = computed(()=>rawTimes.value.map((t)=>Math.round(t)))
|
||||
const endTimes = computed(()=>{
|
||||
if (props.builder.rungs === 1)
|
||||
return DISTANT_FUTURE
|
||||
const ts = times.value
|
||||
const window = Math.max(MIN_EXECUTION_TIME, Math.floor((ts[ts.length-1]-ts[0])/props.builder.rungs))
|
||||
return ts.map((t)=>t+window)
|
||||
})
|
||||
const absoluteTimes = computed(()=>{
|
||||
console.log('absoluteTimes', props.builder.relative, times.value)
|
||||
if (!props.builder.relative)
|
||||
return times.value
|
||||
const now = s.clock
|
||||
return times.value.map((t)=>now+t)
|
||||
})
|
||||
|
||||
const absTimeA = computed({
|
||||
get() {
|
||||
let result = props.builder.timeA
|
||||
if (props.builder.relative)
|
||||
result += s.clock
|
||||
console.log('absTimeA', result)
|
||||
return result
|
||||
},
|
||||
set(v) {
|
||||
console.log('set absTimeA', props.builder.timeA, v)
|
||||
if (props.builder.relative)
|
||||
v -= s.clock
|
||||
props.builder.timeA = v
|
||||
console.log('absTimeA=',props.builder.timeA)
|
||||
}
|
||||
})
|
||||
const absTimeB = computed({
|
||||
get() {
|
||||
let result = props.builder.timeB
|
||||
if (props.builder.relative)
|
||||
result += s.clock
|
||||
console.log('absTimeB', result)
|
||||
return result
|
||||
},
|
||||
set(v) {
|
||||
console.log('set absTimeB', props.builder.timeB, v)
|
||||
if ( v !== null && props.builder.relative )
|
||||
v -= s.clock
|
||||
props.builder.timeB = v
|
||||
console.log('absTimeB=',props.builder.timeB)
|
||||
}
|
||||
})
|
||||
|
||||
function buildTranches() {
|
||||
const order = props.order
|
||||
const builder = props.builder
|
||||
const tranches = []
|
||||
|
||||
console.log('buildTranches', builder, order, tranches)
|
||||
const ts = times.value
|
||||
const ets = endTimes.value
|
||||
const ws = weights.value
|
||||
for(let i=0; i<ts.length; i++) {
|
||||
const t = newTranche({
|
||||
fraction: ws[i] * MAX_FRACTION,
|
||||
startTime: ts[i],
|
||||
endTime: ets[i],
|
||||
})
|
||||
tranches.push(t)
|
||||
}
|
||||
return tranches
|
||||
}
|
||||
|
||||
|
||||
function getModelValue(model) {
|
||||
if(!model) {
|
||||
console.log('getModelValue', model)
|
||||
return null
|
||||
}
|
||||
return model.time
|
||||
}
|
||||
|
||||
function setModelValue(model, value) {
|
||||
console.log('DCA set model value', model, value)
|
||||
const v = value === null ? null : props.builder.relative ? s.clock + Math.round(value) : Math.round(value)
|
||||
if (model.time !== v) {
|
||||
console.log('DCA do set time', v)
|
||||
model.time = v
|
||||
}
|
||||
}
|
||||
|
||||
function setValues(values) {
|
||||
if (!props.builder.relative)
|
||||
rawTimes.value = values
|
||||
else {
|
||||
const now = s.clock
|
||||
const vs = []
|
||||
for (let i = 0; i < values.length; i++)
|
||||
vs.push(values[i] - now)
|
||||
rawTimes.value = vs
|
||||
}
|
||||
}
|
||||
|
||||
function valueFromPoints(points) {
|
||||
const result = points[0].time;
|
||||
console.log('valueFromPoints', points, result);
|
||||
return result
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
|
||||
</style>
|
||||
@@ -75,10 +75,10 @@
|
||||
<script setup>
|
||||
import {computed, onBeforeUnmount, onMounted, onUnmounted, onUpdated, watch, watchEffect} from "vue";
|
||||
import {cancelDrawing, chart} from "@/charts/chart.js";
|
||||
import {applyLine2, builderFuncs, useChartOrderStore} from "@/orderbuild.js";
|
||||
import {applyLine2, builderDefaults, builderFuncs, useChartOrderStore} from "@/orderbuild.js";
|
||||
import Color from "color";
|
||||
import {HLine} from "@/charts/shape.js";
|
||||
import {builderDefaults, lightenColor2, lineColor} from "@/misc.js";
|
||||
import {lightenColor2, sideColor} from "@/misc.js";
|
||||
import {useTheme} from "vuetify";
|
||||
import {useOrderStore} from "@/store/store.js";
|
||||
import RowBar from "@/components/chart/RowBar.vue";
|
||||
@@ -93,15 +93,13 @@ const emit = defineEmits(['update:builder'])
|
||||
|
||||
function computeDefaultColor() {
|
||||
const index = props.order.builders.indexOf(props.builder)
|
||||
return lineColor(props.order.buy, index)
|
||||
return sideColor(props.order.buy, index)
|
||||
}
|
||||
|
||||
const defaultColor = computeDefaultColor()
|
||||
|
||||
// Fields must be defined in order to be reactive
|
||||
builderDefaults(props, emit, {
|
||||
valid: false,
|
||||
allocation: 1.0,
|
||||
builderDefaults(props.builder, {
|
||||
start: null, // todo
|
||||
end: null, // todo
|
||||
priceA: null,
|
||||
|
||||
@@ -18,11 +18,8 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {builderFuncs, useChartOrderStore} from "@/orderbuild.js";
|
||||
import {builderDefaults} from "@/misc.js";
|
||||
import {useOrderStore} from "@/store/store.js";
|
||||
import {builderDefaults, builderFuncs, useChartOrderStore} from "@/orderbuild.js";
|
||||
import {computed, onMounted, onUnmounted} from "vue";
|
||||
import RowBar from "@/components/chart/RowBar.vue";
|
||||
import {newTranche} from "@/blockchain/orderlib.js";
|
||||
|
||||
const co = useChartOrderStore()
|
||||
@@ -30,7 +27,8 @@ const props = defineProps(['order', 'builder'])
|
||||
const emit = defineEmits(['update:builder'])
|
||||
|
||||
// Fields must be defined in order to be reactive
|
||||
builderDefaults(props, emit, {valid: true, slippage: 0.10,})
|
||||
builderDefaults(props.builder, {valid: true, slippage: 0.10,})
|
||||
|
||||
const slippage = computed({
|
||||
get() {console.log('slip',props.builder,props.builder.slippage); return props.builder.slippage},
|
||||
set(v) {props.builder.slippage=v; emit('update:builder', props.builder)}
|
||||
|
||||
352
src/components/chart/RungBuilder.vue
Normal file
352
src/components/chart/RungBuilder.vue
Normal file
@@ -0,0 +1,352 @@
|
||||
<template>
|
||||
<builder-panel :order="order" :builder="builder" :build-tranches="buildTranches"
|
||||
:adjust-shapes="adjustShapes" :delete-shapes="deleteShapes">
|
||||
<div style="min-width: 3em; font-size: larger" :style="colorStyle" class="align-self-start ml-2 pt-3">{{ name }}
|
||||
</div>
|
||||
<div>
|
||||
<v-text-field type="number" v-model="rungs"
|
||||
density="compact" hide-details class="mx-1 my-2" variant="outlined"
|
||||
label="Rungs"
|
||||
:color="color" :base-color="color" min="1"
|
||||
:disabled="valueA===null"
|
||||
style="width: 4.5em;"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<slot/>
|
||||
|
||||
<div v-if="co.drawing" class="d-flex align-center pl-3">
|
||||
<v-icon icon="mdi-chat-alert-outline" color="grey" class="mr-1"/>
|
||||
Click the chart!
|
||||
</div>
|
||||
<div v-if="rungs>1" class="mx-2 d-flex align-center">
|
||||
<v-slider v-if="rungs>1" direction="vertical" min="-100" max="100" v-model="skew100"
|
||||
class="no-slider-bg ml-2 mr-4" hide-details/>
|
||||
<v-text-field type="number" v-model="skew100" min="-100" max="100"
|
||||
density="compact" hide-details variant="outlined" label="Skew" step="5"
|
||||
:color="color" :base-color="color">
|
||||
<template v-slot:prepend>
|
||||
<v-btn icon="mdi-scale-balance" variant="plain" @click="builder.skew=0" :color="color"/>
|
||||
</template>
|
||||
</v-text-field>
|
||||
</div>
|
||||
</builder-panel>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import BuilderPanel from "@/components/chart/BuilderPanel.vue";
|
||||
import {useOrderStore} from "@/store/store.js";
|
||||
import {allocationText, deleteBuilder, linearWeights, useChartOrderStore, weightColors} from "@/orderbuild.js";
|
||||
import {useTheme} from "vuetify";
|
||||
import {linspace, sideColor} from "@/misc.js";
|
||||
import {computed, watchEffect} from "vue";
|
||||
import Color from "color";
|
||||
import {cancelDrawing} from "@/charts/chart.js";
|
||||
|
||||
const os = useOrderStore()
|
||||
const co = useChartOrderStore()
|
||||
const theme = useTheme().current
|
||||
const valueA = defineModel('valueA')
|
||||
const valueB = defineModel('valueB')
|
||||
const props = defineProps({
|
||||
name: String,
|
||||
order: Object,
|
||||
builder: Object,
|
||||
buildTranches: Function,
|
||||
stdWidth: Number,
|
||||
shape: Function, // shape() -> Shape
|
||||
mode: { type: Number, default: 0 }, // rung addition mode: 0 = split, 1 = extend
|
||||
getModelValue: Function, // getModelValue(model) -> value
|
||||
setModelValue: Function, // setModelValue(model,value) -> void
|
||||
setValues: Function, // setValues(values:Array) -> void
|
||||
})
|
||||
|
||||
const skew100 = computed( {
|
||||
get() {return props.builder.skew*100},
|
||||
set(v) {props.builder.skew = v/100; }
|
||||
} )
|
||||
|
||||
// validity checks
|
||||
watchEffect(()=>{
|
||||
const order = props.order
|
||||
const builder = props.builder
|
||||
props.builder.valid &&=
|
||||
order && builder &&
|
||||
builder.rungs >= 1 && valueA.value &&
|
||||
(builder.rungs < 2 || valueB.value)
|
||||
})
|
||||
|
||||
|
||||
const rungs = computed({
|
||||
get() {
|
||||
return props.builder.rungs
|
||||
},
|
||||
set(r) {
|
||||
// todo this is subclass specific: make TWAP extend the range rather than compressing it
|
||||
if (!r) {
|
||||
props.builder.rungs = 1
|
||||
return
|
||||
}
|
||||
r = Number(r)
|
||||
props.builder.rungs = r
|
||||
const b = valueB.value
|
||||
console.log('set rungs', r, valueA.value, b)
|
||||
if ( r > 0 && b === null ) {
|
||||
// convert single shape to a range
|
||||
if (props.mode===0) {
|
||||
const width = props.stdWidth
|
||||
const mid = valueA.value
|
||||
console.log('single to range', mid - width/2, mid + width/2)
|
||||
valueA.value = mid - width/2
|
||||
valueB.value = mid + width/2
|
||||
}
|
||||
else if (props.mode===1 ) {
|
||||
valueB.value = valueA.value + props.stdWidth
|
||||
}
|
||||
else
|
||||
throw Error(`Unknown rung mode ${props.mode}`)
|
||||
}
|
||||
else if ( r === 1 && b !== null ) {
|
||||
// convert from a range to a single shape
|
||||
if (props.mode===0)
|
||||
valueA.value = (valueA.value + b) / 2
|
||||
valueB.value = null
|
||||
}
|
||||
else {
|
||||
// from multi to multi
|
||||
if (props.mode===1)
|
||||
valueB.value = valueA.value + props.stdWidth * (r-1)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
const values = computed(()=>{
|
||||
let a = valueA.value
|
||||
let b = valueB.value
|
||||
const r = props.builder.rungs
|
||||
let result
|
||||
if ( a===null || !r )
|
||||
result = [] // no data
|
||||
else if (r===1)
|
||||
result = [a] // single shape
|
||||
else
|
||||
result = linspace(a, b, r) // linear spacing
|
||||
props.setValues(result)
|
||||
return result;
|
||||
})
|
||||
|
||||
|
||||
const weights = computed(() => linearWeights(props.builder.rungs, -props.builder.skew))
|
||||
|
||||
|
||||
const amountSymbol = computed(()=>props.order.amountIsTokenA ? co.selectedSymbol.base.s : co.selectedSymbol.quote.s )
|
||||
|
||||
|
||||
// colors
|
||||
function computeDefaultColor() {
|
||||
const index = props.order.builders.indexOf(props.builder)
|
||||
return sideColor(props.order.buy, index)
|
||||
}
|
||||
const defaultColor = computeDefaultColor()
|
||||
const color = computed({
|
||||
get() {return props.builder.color},
|
||||
set(v) {
|
||||
const maxLightness = 60
|
||||
const c = new Color(v).hsl()
|
||||
props.builder.color = c.saturation <= maxLightness ? v : c.lightness(maxLightness).string()
|
||||
}
|
||||
})
|
||||
const colors = computed( ()=> {
|
||||
const color = props.builder.color !== null ? props.builder.color
|
||||
: props.buy ? theme.value.colors.success : theme.value.colors.error
|
||||
const ws = weights.value;
|
||||
return weightColors(ws, color);
|
||||
})
|
||||
const colorStyle = computed(() => {
|
||||
return {'color': color.value}
|
||||
})
|
||||
|
||||
|
||||
function allocText(weight) {
|
||||
const alloc = props.builder.allocation
|
||||
if (alloc===null) return ''
|
||||
return allocationText(props.order.amount, weight * alloc, amountSymbol.value);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// SHAPE MANAGEMENT
|
||||
//
|
||||
|
||||
// we keep two special control shapes as the edges of the range, with deletable shapes in-between
|
||||
|
||||
function createShape(value, model, onModel, onDelete) {
|
||||
console.log('createShape setModelValue', model, value)
|
||||
props.setModelValue(model, value)
|
||||
return new props.shape(model, onModel, onDelete) // props.shape is the constructor function
|
||||
}
|
||||
|
||||
|
||||
function translateOnDrag(shape) {
|
||||
const oldOnPoints = shape.onPoints
|
||||
shape.onPoints = function (points) {
|
||||
if (!this.beingDragged()) {
|
||||
oldOnPoints.call(this, points)
|
||||
return
|
||||
}
|
||||
const prev = props.getModelValue(this.model)
|
||||
oldOnPoints.call(this, points)
|
||||
const cur = props.getModelValue(this.model)
|
||||
const delta = cur - prev
|
||||
console.log('move prev/cur', prev, cur, delta)
|
||||
if (delta !== 0) {
|
||||
valueA.value += delta
|
||||
valueB.value += delta
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const shapeA = createShape(valueA.value, {color: defaultColor},
|
||||
function (model) {
|
||||
const value = props.getModelValue(model);
|
||||
if (value!==null && value!==undefined)
|
||||
valueA.value = value;
|
||||
if (model.color)
|
||||
props.builder.color = model.color;
|
||||
},
|
||||
deleteSelf)
|
||||
|
||||
if (props.mode===1)
|
||||
translateOnDrag(shapeA)
|
||||
|
||||
const shapeB = createShape(valueB.value, {color:defaultColor},
|
||||
function (model) {
|
||||
const value = props.getModelValue(model);
|
||||
if (value!==null && value!==undefined)
|
||||
valueB.value = value;
|
||||
if (model.color)
|
||||
props.builder.color = model.color;
|
||||
},
|
||||
deleteSelf)
|
||||
|
||||
function interiorOnModel(model) {
|
||||
const v = model.textColor || model.lineColor || model.color
|
||||
if (v)
|
||||
color.value = v
|
||||
}
|
||||
|
||||
let interiorShapes = []
|
||||
|
||||
function createInteriorShape(price, weight) {
|
||||
const model = {text: allocText(weight), color: props.builder.color};
|
||||
const shape = createShape(price, model, interiorOnModel, deleteSelf)
|
||||
shape.debug = true
|
||||
translateOnDrag(shape)
|
||||
interiorShapes.push(shape)
|
||||
// shape.create() // should happen automatically when a model with valid points is set
|
||||
}
|
||||
|
||||
|
||||
function removeInteriorShape() {
|
||||
if (interiorShapes.length) {
|
||||
const shape = interiorShapes.pop()
|
||||
shape.delete()
|
||||
}
|
||||
}
|
||||
|
||||
function adjustShapes() {
|
||||
// this is where all the shapes are created or adjusted
|
||||
console.log('adjustShapes()', valueA.value, valueB.value)
|
||||
const vs = values.value
|
||||
if (vs.length)
|
||||
cancelDrawing()
|
||||
const ws = weights.value
|
||||
const colorStrings = colors.value
|
||||
// shape properties
|
||||
if( vs.length === 0 ) {
|
||||
shapeA.delete()
|
||||
shapeB.delete()
|
||||
for( const shape of interiorShapes )
|
||||
shape.delete()
|
||||
interiorShapes = []
|
||||
}
|
||||
else if (vs.length === 1) {
|
||||
//
|
||||
// SINGLE SHAPE
|
||||
//
|
||||
if (!shapeA.beingDragged()) {
|
||||
const model = {text: allocText(ws[0]), color: colorStrings[0]};
|
||||
console.log('single shape A setModelValue', model, vs[0])
|
||||
props.setModelValue(model, vs[0])
|
||||
shapeA.setModel(model)
|
||||
}
|
||||
shapeB.delete()
|
||||
if (interiorShapes.length) {
|
||||
for( const shape of interiorShapes )
|
||||
shape.delete()
|
||||
interiorShapes = []
|
||||
}
|
||||
}
|
||||
else {
|
||||
//
|
||||
// VALUE RANGE
|
||||
//
|
||||
if (!shapeA.beingDragged()) {
|
||||
const model = {text: allocText(ws[0]), color: colorStrings[0]};
|
||||
console.log('shape A not dragged setModelValue', model, vs[0])
|
||||
props.setModelValue(model, vs[0])
|
||||
shapeA.setModel(model)
|
||||
}
|
||||
if (!shapeB.beingDragged()) {
|
||||
const last = colorStrings.length - 1
|
||||
const model = {text: allocText(ws[last]), color: colorStrings[last]};
|
||||
console.log('shape B not dragged setModelValue', model, vs[last])
|
||||
props.setModelValue(model, vs[last])
|
||||
shapeB.setModel(model)
|
||||
}
|
||||
const numInterior = Math.max(0,vs.length-2);
|
||||
// trim excess interior shapes
|
||||
while( interiorShapes.length > numInterior )
|
||||
removeInteriorShape()
|
||||
// adjust the interior shape values and/or add shapes
|
||||
for( let i=1; i<vs.length-1; i++ ) {
|
||||
const v = vs[i]
|
||||
const w = ws[i];
|
||||
if (i-1 === interiorShapes.length)
|
||||
createInteriorShape(v, w)
|
||||
else if (!interiorShapes[i-1].beingDragged()) {
|
||||
const model = {text: allocText(w), color: colorStrings[i]};
|
||||
console.log('interior setModelValue', model, v)
|
||||
props.setModelValue(model, v)
|
||||
interiorShapes[i-1].setModel(model)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
function deleteSelf() {
|
||||
deleteBuilder(props.order, props.builder);
|
||||
}
|
||||
|
||||
function deleteShapes() {
|
||||
shapeA.delete()
|
||||
shapeB.delete()
|
||||
for (const shape of interiorShapes)
|
||||
shape.delete()
|
||||
interiorShapes = []
|
||||
}
|
||||
|
||||
|
||||
console.log('valueA', valueA.value, shapeA)
|
||||
if (!valueA.value)
|
||||
shapeA.createOrDraw(); // initiate drawing mode
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user