diff --git a/src/charts/chart.js b/src/charts/chart.js index f850013..34abab5 100644 --- a/src/charts/chart.js +++ b/src/charts/chart.js @@ -1,7 +1,7 @@ import {useChartOrderStore} from "@/orderbuild.js"; import {invokeCallbacks, prototype} from "@/common.js"; import {DataFeed, initFeeDropdown, lookupSymbol} from "@/charts/datafeed.js"; -import {intervalToSeconds} from "@/misc.js"; +import {intervalToSeconds, SingletonCoroutine} from "@/misc.js"; export let widget = null export let chart = null @@ -123,14 +123,15 @@ export const VerboseCallback = prototype(ShapeCallback, { let drawingTool = null let previousDrawingTool = null +let drawingCallbacks = null export function drawShape(shapeType, ...callbacks) { // puts the chart into a line-drawing mode for a new shape console.log('drawShape', callbacks, shapeType.name, shapeType.code) const co = useChartOrderStore() - if( co.drawingCallbacks ) - invokeCallbacks(co.drawingCallbacks, 'onUndraw') - co.drawingCallbacks = callbacks + if( drawingCallbacks ) + invokeCallbacks(drawingCallbacks, 'onUndraw') + drawingCallbacks = callbacks drawingTool = null previousDrawingTool = widget.selectedLineTool() co.drawing = true @@ -140,8 +141,9 @@ export function drawShape(shapeType, ...callbacks) { export function createShape(shapeType, points, options={}, ...callbacks) { + console.log('tvShape creating') const co = useChartOrderStore() - co.drawingCallbacks = null + drawingCallbacks = null co.drawing = false options.shape = shapeType.code // programatically adds a shape to the chart @@ -155,26 +157,60 @@ export function createShape(shapeType, points, options={}, ...callbacks) { shapeId = chart.createMultipointShape(points, options) } catch (e) { - console.error('Could not create shape', shapeType, points, options, e) + console.error('tvShape could not create', shapeType, points, options, e) return null } + allShapeIds.push(shapeId) if( callbacks.length ) shapeCallbacks[shapeId] = callbacks - // console.log(`created ${shapeType.name}`, shapeId) const shape = chart.getShapeById(shapeId) + console.log('tvShape created', shape) // todo debug shape.bringToFront() const props = shape.getProperties() invokeCallbacks(callbacks, 'onCreate', shapeId, shape, points, props) + + stub(shape) + return shapeId } +let stubbed = true +// todo debug +function stub(shape) { + if(stubbed||shape===null) return + function stubFunc(funcName) { + const obj = shape._model + console.log('stubbing', funcName, obj) + const func = obj[funcName] + obj[funcName] = function () { + console.error(shapeId, funcName+'()', [...arguments]) + func(...arguments) + } + } + + stubFunc('start') + stubFunc('stop') + stubFunc('startChanging') + stubFunc('endChanging') + stubFunc('startMoving') + stubFunc('endMoving') + stubFunc('startMovingPoint') + stubFunc('move') + stubFunc('restart') + stubFunc('restorePoints') + stubbed = true +} + + +export let allShapeIds = [] + export function cancelDrawing() { const co = useChartOrderStore() if (co.drawing) { co.drawing = false widget.selectLineTool(previousDrawingTool) - invokeCallbacks(co.drawingCallbacks, 'onUndraw') + invokeCallbacks(drawingCallbacks, 'onUndraw') } } @@ -192,12 +228,14 @@ function onSelectedLineToolChanged() { export let dragging = false function mouseDown() { - // console.log('mouseDown') + console.log('mouseDown') + dump() dragging = true } function mouseUp() { - // console.log('mouseUp') + console.log('mouseUp') + dump() dragging = false draggingShapeIds = [] } @@ -205,15 +243,40 @@ function mouseUp() { export let draggingShapeIds = [] +function dump() { + return + console.log('all', allShapeIds) + for (const shapeId of allShapeIds) { + const shape = chart.getShapeById(shapeId) + console.log('shape', shape) + console.log('_linePointBeingChanged', shape._model._linePointBeingChanged) + // console.log('_lineBeingEdited', shape._model._lineBeingEdited) + // console.log('_lineBeingCreated', shape._model._lineBeingCreated) + // console.log('_linePointBeingEdited', shape._model._linePointBeingEdited) + // console.log('_lastHoveredHittestData', shape._model._lastHoveredHittestData) + // console.log('_lastSelectedHittestData', shape._model._lastSelectedHittestData) + } + +} function handleCrosshairMovement(point) { + crosshairHandler.invoke(point) // delayed invocation to await selection to register later in the tv loop +} + + +const crosshairHandler = new SingletonCoroutine(doHandleCrosshairMovement, 0) + + +function doHandleCrosshairMovement(point) { // console.log('crosshair moved') crosshairPoint = point const co = useChartOrderStore() if (co.drawing) - invokeCallbacks(co.drawingCallbacks, 'onRedraw') + invokeCallbacks(drawingCallbacks, 'onRedraw') else if (dragging) { - draggingShapeIds = chart.selection().allSources(); + const selection = chart.selection().allSources(); + if (selection.length) + draggingShapeIds = selection // console.log('dragging selected', draggingShapeIds) for (const shapeId of draggingShapeIds) { let shape @@ -224,7 +287,8 @@ function handleCrosshairMovement(point) { continue } const points = shape.getPoints(); - // console.log(`dragging ${shapeId}`, shape, points1, points2, points3) + + // console.log('dragging', shapeId) // invokeCallbacks(shapeCallbacks[shapeId], 'onDrag', shapeId, shape, points) // console.log('calling onPoints') invokeCallbacks(shapeCallbacks[shapeId], 'onPoints', shapeId, shape, points) @@ -288,8 +352,12 @@ function doHandleDrawingEvent(id, event) { } } if (event === 'create') { + console.log('created tvShape', id, shape) // todo remove debug + stub(shape) // todo debug + allShapeIds.push(id) + const co = useChartOrderStore(); - const callbacks = co.drawingCallbacks + const callbacks = drawingCallbacks // console.log('drawing callbacks', callbacks) if (callbacks !== null) { shapeCallbacks[id] = callbacks @@ -301,6 +369,7 @@ function doHandleDrawingEvent(id, event) { invokeCallbacks(shapeCallbacks[id], 'onProps', id, shape, props) } } else if (event === 'points_changed') { + if (dragging) return if (id in shapeCallbacks) { const points = shape.getPoints() // console.log('points', points) @@ -318,6 +387,7 @@ function doHandleDrawingEvent(id, event) { invokeCallbacks(shapeCallbacks[id], 'onMove', id, shape) } } else if (event === 'remove') { + allShapeIds = allShapeIds.filter((v)=>v!==id) if (id in shapeCallbacks) { invokeCallbacks(shapeCallbacks[id], 'onDelete', id) } diff --git a/src/charts/shape.js b/src/charts/shape.js index f433081..445c918 100644 --- a/src/charts/shape.js +++ b/src/charts/shape.js @@ -64,7 +64,7 @@ export class Shape { this.tvCallbacks = null this.ourPoints = null this.tvPoints = null - this.creationOptions = {disableSave:true, disableUndo:false, disableSelection:false} + this.creationOptions = {disableSave:true, disableUndo:true, disableSelection:false} this.ourProps = {} if (props !== null) this.ourProps = mixin(props, this.ourProps) @@ -131,9 +131,8 @@ export class Shape { newProps.linecolor = color // text label - const text = - // `${this.id} ` + - allocationText(this.model.allocation, this.model.amount, this.model.amountSymbol) + let text = allocationText(this.model.allocation, this.model.amount, this.model.amountSymbol) + if (this.debug) text = `${this.id} ` + text if (!text.length) newProps.showLabel = false else { @@ -206,10 +205,18 @@ export class Shape { options['overrides'] = props this.tvPoints = [...points] this.tvCallbacks = new ShapeTVCallbacks(this); - createShape(this.type, points, options, this.tvCallbacks) - if (this.debug) console.log('created', this.type.name, points, this.id) + const id = createShape(this.type, points, options, this.tvCallbacks) + // todo set id? + if (this.debug) console.log('created', this.type.name, points, id) } + onCreate(points, props) { + // the user has finished creating all the control points. drawing mode is exited and the initial shape is created. + this.tvPoints = points + this.tvProps = props + } + + createOrDraw() { if(this.id) return if(this.ourPoints && this.ourPoints.length) @@ -243,50 +250,14 @@ export class Shape { this.create() else if (dirtyPoints(this.tvPoints, points)) { const s = this.tvShape(); - let sbm = false - if( draggingShapeIds.length ) { - let dragShape - try { - dragShape = chart.getShapeById(draggingShapeIds[0]) - const sbms = [...dragShape._model._sourcesBeingMoved] - // console.log('shape setPoints', this.id, dragShape, sbm) - sbm = !sbms.length - // if (!sbms.length) { - // console.log('shape setPoints SBM return') - // return - // } - } - catch (e) { - console.error(`could not get drag shape ${draggingShapeIds[0]}`) - } - } - if (this.debug) console.log('adjusting tv points', this.tvPoints, points, dragging, this.beingDragged()) - // if ( dragging && !this.beingDragged()) - // s.setSelectionEnabled(false) - // s.setPoints(points) - // if ( dragging && !this.beingDragged()) - // s.setSelectionEnabled(true) - - // best so far - if (sbm && this.type === ShapeType.VLine) { - // console.log('sbm: re-create shape') - this.delete() - this.ourPoints = points - this.create() - } else - if (!dragging || this.type !== ShapeType.HLine) { - if (this.debug) console.log('not dragging. use setPoints.') - s.setPoints(points) - } - else { - if (this.debug) console.log('dragging. use QUIET setPoints.') - // quiet setPoints doesn't disturb tool editing mode - const i = s._pointsConverter.apiPointsToDataSource(points) - // s._model.startChangingLinetool(this._source) - s._model.changeLinePoints(s._source, i) - // s._model.endChangingLinetool(!0) - s._source.createServerPoints() - } + const lbe = s._model._lineBeingEdited + const lpbc = s._model._linePointBeingChanged + const lpbe = s._model._linePointBeingEdited + if (lpbc!==null) + s._model.endChangingLinetool(lbe, lpbc) + s.setPoints(points) + if (lpbc!==null) + s._model.startChangingLinetool(lbe, lpbc, lpbe) } } } @@ -341,10 +312,6 @@ export class Shape { onRedraw() {} // the mouse moved while in drawing mode onUndraw() {} // drawing was canceled by clicking on a different tool onAddPoint() {} // the user clicked a point while drawing (that point is added to the points list) - onCreate(points, props) { - this.tvPoints = points - this.tvProps = props - } // the user has finished creating all the control points. drawing mode is exited and the initial shape is created. onMove(points) {} // the shape was moved by dragging a drawing element not the control point onDrag(points) {} onHide(props) {} @@ -354,6 +321,9 @@ export class Shape { } + +let lineChangeInfo = null + function dirtyPoints(pointsA, pointsB) { if (pointsB===null) return pointsA !== null @@ -394,13 +364,11 @@ class ShapeTVCallbacks { constructor(shape) { this.shape = shape - this.creating = false this.enabled = true // gets disabled when the shape is deleted, squelching any further callbacks } onCreate(shapeId, _tvShape, points, props) { if (!this.enabled) return // possible when shape is deleted and re-created - this.creating = true this.shape.id = shapeId invokeCallback(this.shape, 'onCreate', points, props) } @@ -415,10 +383,6 @@ class ShapeTVCallbacks { onProps(shapeId, _tvShape, props) { if (!this.enabled) return // possible when shape is deleted and re-created if (this.shape.debug) console.log('tvOnProps', props) - if (this.creating) { // todo still useful? - this.creating = false - return - } this.shape.tvProps = props this.shape.onProps(props) } @@ -538,6 +502,7 @@ export class VLine extends Line { constructor(model, onModel=null, onDelete=null, props=null) { super(ShapeType.VLine, onModel, onDelete, props) + this.debug = true // todo debug // Model this.model.time = null @@ -551,6 +516,7 @@ export class VLine extends Line { doCreate(points, props, options = {}) { this.shapeTime = nearestOhlcStart(points[0].time); points = [{time: this.shapeTime, price:0}] + if (this.debug) console.log('VLine.doCreate', this.shapeTime, points) super.doCreate(points, props, options); } @@ -562,7 +528,7 @@ export class VLine extends Line { setModel(model) { - // console.log('VLine setModel', this.id, {...this.model}, model) + // if (this.debug) console.error('VLine setModel', this.id, {...this.model}, model) super.setModel(model) if (model.time === null) this.delete() @@ -573,7 +539,7 @@ export class VLine extends Line { } setPoints(points) { - if (this.debug) console.error('VLine setPoints...', points) + // if (this.debug) console.error('VLine setPoints...', points) if (points !== null && points.length) { // adjust shape to ohlc boundry const time = nearestOhlcStart(points[0].time); @@ -586,7 +552,7 @@ export class VLine extends Line { this.shapeTime = null super.setPoints(points); } - if (this.debug) console.error('VLine setPoints', points) + // if (this.debug) console.error('VLine setPoints', points) } onPoints(points) { diff --git a/src/components/AbsoluteTimeEntry.vue b/src/components/AbsoluteTimeEntry.vue index c66201b..1b81cbc 100644 --- a/src/components/AbsoluteTimeEntry.vue +++ b/src/components/AbsoluteTimeEntry.vue @@ -262,11 +262,13 @@ let newValue = null .month { width: 10em; max-width: 10em; - min-width: 5em; + min-width: 6em; } .day { - + width: 2em; + max-width: 4em; + min-width: 2em; } .picker { diff --git a/src/components/chart/DCABuilder.vue b/src/components/chart/DCABuilder.vue index 86b1c86..d15b974 100644 --- a/src/components/chart/DCABuilder.vue +++ b/src/components/chart/DCABuilder.vue @@ -57,7 +57,6 @@ import RungBuilder from "@/components/chart/RungBuilder.vue"; import {computed, ref, watchEffect} from "vue"; import {chart, dragging} from "@/charts/chart.js"; import AbsoluteTimeEntry from "@/components/AbsoluteTimeEntry.vue"; -import TimeEntry from "@/components/TimeEntry.vue"; const s = useStore() const os = useOrderStore() @@ -135,31 +134,22 @@ const absTimeA = computed({ }, set(v) { console.error('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 - }, + get() {return props.builder.timeB}, set(v) { console.error('set absTimeB', props.builder.timeB, v) - // if ( v !== null && props.builder.relative ) - // v -= s.clock props.builder.timeB = v - const maxA = v - minWidth.value; - if (props.builder.timeA > maxA) { - console.log('scootching A to', maxA) - props.builder.timeA = maxA + if (v !== null) { + const maxA = v - minWidth.value; + if (props.builder.timeA > maxA) { + console.log('scootching A to', maxA) + props.builder.timeA = maxA + } } - console.log('absTimeB=',props.builder.timeB) } }) diff --git a/src/orderbuild.js b/src/orderbuild.js index f69999b..eafea54 100644 --- a/src/orderbuild.js +++ b/src/orderbuild.js @@ -66,7 +66,6 @@ export const useChartOrderStore = defineStore('chart_orders', () => { const drawing = ref(false) - const drawingCallbacks = ref(null) // only during draw mode function newOrder() { const order = newDefaultOrder() @@ -96,7 +95,7 @@ export const useChartOrderStore = defineStore('chart_orders', () => { return { chartReady, selectedSymbol, selectedPool, intervalSecs, baseToken, quoteToken, price, - orders, drawing, drawingCallbacks, newOrder, removeOrder, resetOrders, + orders, drawing, newOrder, removeOrder, resetOrders, } })