diff --git a/src/static/formation_overlay.js b/src/static/formation_overlay.js index 1ebdba5..22ff14e 100644 --- a/src/static/formation_overlay.js +++ b/src/static/formation_overlay.js @@ -38,6 +38,12 @@ class FormationOverlay { // Callback for saving formations this.onSaveCallback = null; + // Callback for when points change during drawing + this.onPointsChangedCallback = null; + + // Track points needed for current drawing + this._pointsNeeded = 0; + // Colors this.defaultColor = '#667eea'; this.selectedColor = '#ff9500'; @@ -57,6 +63,14 @@ class FormationOverlay { this.onSaveCallback = callback; } + /** + * Set callback for when points change during drawing. + * @param {Function} callback - Called with (currentPoints, pointsNeeded) + */ + setOnPointsChangedCallback(callback) { + this.onPointsChangedCallback = callback; + } + /** * Create the SVG overlay layer. */ @@ -361,6 +375,7 @@ class FormationOverlay { startDrawing(type) { this.drawingMode = type; this.currentPoints = []; + this._pointsNeeded = this._getPointsNeeded(type); this._clearTempElements(); // Change cursor @@ -373,7 +388,12 @@ class FormationOverlay { this.svg.style.pointerEvents = 'all'; } - console.log('FormationOverlay: Started drawing', type); + // Notify of initial state + if (this.onPointsChangedCallback) { + this.onPointsChangedCallback(0, this._pointsNeeded); + } + + console.log('FormationOverlay: Started drawing', type, 'needs', this._pointsNeeded, 'points'); } /** @@ -381,16 +401,28 @@ class FormationOverlay { * @param {Object} coords - {time, price} */ _handleDrawingClick(coords) { + // Don't accept more points than needed + if (this.currentPoints.length >= this._pointsNeeded) { + console.log('FormationOverlay: Already have enough points'); + return; + } + this.currentPoints.push(coords); // Draw anchor at click point this._drawTempAnchor(coords); - // Check if drawing is complete based on formation type - const pointsNeeded = this._getPointsNeeded(this.drawingMode); + // Notify of points change + if (this.onPointsChangedCallback) { + this.onPointsChangedCallback(this.currentPoints.length, this._pointsNeeded); + } - if (this.currentPoints.length >= pointsNeeded) { - // Drawing complete, wait for name input + // Check if drawing is complete + if (this.currentPoints.length >= this._pointsNeeded) { + // Drawing complete, change cursor back + if (this.container) { + this.container.style.cursor = 'default'; + } console.log('FormationOverlay: Points collected', this.currentPoints); } } @@ -546,6 +578,8 @@ class FormationOverlay { _exitDrawingMode() { this.drawingMode = null; this.currentPoints = []; + this._pointsNeeded = 0; + this.onPointsChangedCallback = null; this._clearTempElements(); // Reset cursor diff --git a/src/static/formations.js b/src/static/formations.js index ee706c3..32536ad 100644 --- a/src/static/formations.js +++ b/src/static/formations.js @@ -4,8 +4,11 @@ class FormationsUIManager { constructor() { this.targetEl = null; - this.drawingControlsEl = null; + this.instructionsEl = null; + this.nameControlsEl = null; this.nameInputEl = null; + this.instructionTextEl = null; + this.pointsStatusEl = null; this.onDeleteFormation = null; this.onEditFormation = null; } @@ -20,8 +23,11 @@ class FormationsUIManager { console.warn(`Formations container "${targetId}" not found.`); } - this.drawingControlsEl = document.getElementById('formation_drawing_controls'); + this.instructionsEl = document.getElementById('formation_drawing_instructions'); + this.nameControlsEl = document.getElementById('formation_name_controls'); this.nameInputEl = document.getElementById('formation_name_input'); + this.instructionTextEl = document.getElementById('formation_instruction_text'); + this.pointsStatusEl = document.getElementById('formation_points_status'); } /** @@ -41,12 +47,62 @@ class FormationsUIManager { } /** - * Show drawing controls. + * Show drawing instructions for a formation type. + * @param {string} type - Formation type + * @param {number} pointsNeeded - Number of points needed */ - showDrawingControls() { - if (this.drawingControlsEl) { - this.drawingControlsEl.style.display = 'block'; + showDrawingInstructions(type, pointsNeeded) { + // Hide name controls if visible + if (this.nameControlsEl) { + this.nameControlsEl.style.display = 'none'; } + + // Show instructions + if (this.instructionsEl) { + this.instructionsEl.style.display = 'block'; + } + + // Set instruction text based on type + const instructions = { + 'support_resistance': 'Click 2 points on the chart to draw a line', + 'channel': 'Click 3 points: first line (2 pts) + parallel offset (1 pt)' + }; + if (this.instructionTextEl) { + this.instructionTextEl.textContent = instructions[type] || 'Click on chart to place points'; + } + + // Update points status + this.updatePointsStatus(0, pointsNeeded); + } + + /** + * Update the points status display. + * @param {number} current - Current points placed + * @param {number} needed - Points needed + */ + updatePointsStatus(current, needed) { + if (this.pointsStatusEl) { + this.pointsStatusEl.textContent = `Points: ${current} / ${needed}`; + // Change color when complete + this.pointsStatusEl.style.color = current >= needed ? '#28a745' : '#667eea'; + } + } + + /** + * Show name input after points are placed. + */ + showNameInput() { + // Hide instructions + if (this.instructionsEl) { + this.instructionsEl.style.display = 'none'; + } + + // Show name controls + if (this.nameControlsEl) { + this.nameControlsEl.style.display = 'block'; + } + + // Focus and clear input if (this.nameInputEl) { this.nameInputEl.value = ''; this.nameInputEl.focus(); @@ -54,12 +110,29 @@ class FormationsUIManager { } /** - * Hide drawing controls. + * Hide all drawing-related UI. + */ + hideAllDrawingUI() { + if (this.instructionsEl) { + this.instructionsEl.style.display = 'none'; + } + if (this.nameControlsEl) { + this.nameControlsEl.style.display = 'none'; + } + } + + /** + * Legacy method - kept for compatibility + */ + showDrawingControls() { + // Now handled by showDrawingInstructions and showNameInput + } + + /** + * Legacy method - kept for compatibility */ hideDrawingControls() { - if (this.drawingControlsEl) { - this.drawingControlsEl.style.display = 'none'; - } + this.hideAllDrawingUI(); } /** @@ -386,7 +459,7 @@ class Formations { this.overlay.renderFormation(data.formation); } - this.uiManager.hideDrawingControls(); + this.uiManager.hideAllDrawingUI(); this.drawingMode = null; } else { alert(`Failed to create formation: ${data.message}`); @@ -438,6 +511,19 @@ class Formations { // ================ Drawing Methods ================ + /** + * Get points needed for a formation type. + * @param {string} type - Formation type + * @returns {number} + */ + _getPointsNeeded(type) { + const pointsMap = { + 'support_resistance': 2, + 'channel': 3 + }; + return pointsMap[type] || 2; + } + /** * Start drawing a new formation. * @param {string} type - Formation type ('support_resistance', 'channel') @@ -446,15 +532,33 @@ class Formations { console.log("Starting drawing mode:", type); this.drawingMode = type; - // Show drawing controls - this.uiManager.showDrawingControls(); + const pointsNeeded = this._getPointsNeeded(type); - // Tell overlay to start drawing + // Show drawing instructions (not name input yet) + this.uiManager.showDrawingInstructions(type, pointsNeeded); + + // Tell overlay to start drawing, with callback for point updates if (this.overlay) { + this.overlay.setOnPointsChangedCallback(this._onPointsChanged.bind(this)); this.overlay.startDrawing(type); } } + /** + * Called when points are added/changed during drawing. + * @param {number} currentPoints - Current number of points + * @param {number} pointsNeeded - Points needed for completion + */ + _onPointsChanged(currentPoints, pointsNeeded) { + // Update the UI status + this.uiManager.updatePointsStatus(currentPoints, pointsNeeded); + + // If we have enough points, show the name input + if (currentPoints >= pointsNeeded) { + this.uiManager.showNameInput(); + } + } + /** * Complete the current drawing. */ @@ -475,7 +579,7 @@ class Formations { */ cancelDrawing() { this.drawingMode = null; - this.uiManager.hideDrawingControls(); + this.uiManager.hideAllDrawingUI(); if (this.overlay) { this.overlay.cancelDrawing(); diff --git a/src/templates/formations_hud.html b/src/templates/formations_hud.html index cb0a917..9963cb2 100644 --- a/src/templates/formations_hud.html +++ b/src/templates/formations_hud.html @@ -9,8 +9,20 @@ - -