diff --git a/js/ui/drawing-tools.js b/js/ui/drawing-tools.js index cb29727..d0d116a 100644 --- a/js/ui/drawing-tools.js +++ b/js/ui/drawing-tools.js @@ -221,7 +221,8 @@ export class DrawingManager { type: 'measure', p1: { time: pos.time, price: pos.price }, p2: { time: pos.time, price: pos.price }, - color: '#26a69a' + color: '#26a69a', + labelOffset: { x: 0, y: 0 } }; this.update(); return; @@ -285,11 +286,18 @@ export class DrawingManager { handleMouseMove(e) { const pos = this.getMousePos(e); + + // Hover cursor logic if (!this.isMouseDown && !this.activeTool) { const hit = this.findHit(pos.x, pos.y); - this.container.style.cursor = hit ? 'pointer' : 'default'; + if (hit) { + this.container.style.cursor = hit.part === 'label' ? 'move' : 'pointer'; + } else { + this.container.style.cursor = 'default'; + } } + // Track measurement even if mouse is up (Click-Move-Click) if (this.currentDrawing && this.currentDrawing.type === 'measure') { if (pos.time !== null) { this.currentDrawing.p2 = { time: pos.time, price: pos.price }; @@ -303,6 +311,18 @@ export class DrawingManager { if (this.selectedDrawing && this.dragMode) { if (pos.time === null || pos.price === null) return; const d = this.selectedDrawing; + + if (this.dragMode === 'label') { + // Free movement of ONLY the label field + const dx = pos.x - this.dragStartPos.x; + const dy = pos.y - this.dragStartPos.y; + d.labelOffset.x += dx; + d.labelOffset.y += dy; + this.dragStartPos = pos; + this.update(); + return; // Critical: exit here so we don't move measurement points + } + if (this.dragMode === 'p1') { d.p1 = { time: pos.time, price: pos.price }; } else if (this.dragMode === 'p2') { @@ -361,6 +381,15 @@ export class DrawingManager { const threshold = 10; for (let i = this.drawings.length - 1; i >= 0; i--) { const d = this.drawings[i]; + + // Check for label hit first (highest z-order) + if (d.type === 'measure' && d.labelPos) { + if (x >= d.labelPos.x && x <= d.labelPos.x + d.labelPos.width && + y >= d.labelPos.y && y <= d.labelPos.y + d.labelPos.height) { + return { drawing: d, part: 'label' }; + } + } + if (d.p1 && d.p2) { const x1 = this.chart.timeScale().timeToCoordinate(d.p1.time); const y1 = this.series.priceToCoordinate(d.p1.price); @@ -645,8 +674,14 @@ export class DrawingManager { ctx.font = '500 12px Inter'; const labelWidth = Math.max(...labelLines.map(l => ctx.measureText(l).width)) + 24; const labelHeight = 65; - const labelX = x2 - labelWidth / 2; - const labelY = isUp ? y2 - labelHeight - 10 : y2 + 10; + const defaultLabelX = x2 - labelWidth / 2; + const defaultLabelY = isUp ? y2 - labelHeight - 10 : y2 + 10; + + const labelX = defaultLabelX + (d.labelOffset?.x || 0); + const labelY = defaultLabelY + (d.labelOffset?.y || 0); + + // Store label position for hit detection + d.labelPos = { x: labelX, y: labelY, width: labelWidth, height: labelHeight }; // Solid Box ctx.fillStyle = color;