UNPKG

cirsim

Version:

Cirsim Circuit Simulator

187 lines (154 loc) 5.32 kB
import {Rect} from './Utility/Rect'; /** * The Selection object keeps track of what is currently * selected in a view. * @param view The view this selection object is associated with * @constructor */ export const Selection = function(view) { /// Maintains a list of the currently selected components this.selection = []; let down = false; let firstMove = false; /// Rectangle for selection let rect = null; this.mouseDown = function(x, y, event) { down = true; firstMove = true; const touched = view.circuit.touch(x, y); if(touched !== null) { // Some selectables are singles, meaning we can // only select one at a time. if(touched.single()) { this.selection = [touched]; } else { // If we touched something that was not // previously selected, it becomes the selection if(!this.isSelected(touched)) { if(!event.shiftKey) { this.selection = []; } this.selection.push(touched); } } } else { // If we touch outside, we are clearing the selection if // shift is not selected and we start a selection rectangle if(!event.shiftKey) { this.selection = []; } rect = new Rect(x, y, x, y); } for(let i=0; i<this.selection.length; i++) { this.selection[i].grab(); } }; this.mouseMove = function(x, y, dx, dy) { if(down) { if(firstMove) { // If we move the mouse the first time on any // selection, we need to create an undo backup if(rect === null && this.selection.length > 0) { view.model.backup(); } // This is the first movement of the mouse // after we clicked. If there is one and only // one item selected, check to see if it is // something that might spawn a new child that // we drag. This is how bending points are implemented. if(this.selection.length === 1) { const spawned = this.selection[0].spawn(x, y); if(spawned !== null) { this.selection = [spawned]; } } firstMove = false; } if(rect !== null) { rect.setRightBottom(x, y); } else { for(let i=0; i<this.selection.length; i++) { this.selection[i].move(dx, dy); } } view.model.update(view.circuit); } }; this.mouseUp = function(x, y) { if(down) { var clear = false; for(var i=0; i<this.selection.length; i++) { if(this.selection[i].single()) { clear = true; } this.selection[i].drop(); } if(clear) { this.selection = []; } } down = false; if(rect !== null) { selectRect(); rect = null; } view.circuit.mouseUp(); }; const selectRect = () => { rect.normalize(); if(!rect.isEmpty()) { const inRect = view.circuit.inRect(rect); if(inRect.length > 0) { const newSelection = this.selection.slice(); for (let i = 0; i < inRect.length; i++) { if (!this.isSelected(inRect[i])) { newSelection.push(inRect[i]); } } this.selection = newSelection; } } } /** * Is this component currently selected? * @param component Component to test * @returns {boolean} true if selected. */ this.isSelected = function(component) { for(let i=0; i<this.selection.length; i++) { if(component === this.selection[i]) { return true; } } return false; }; this.draw = function(context) { if(rect !== null) { if (!context.setLineDash) { context.setLineDash = function () {} } context.strokeStyle = "#888888"; context.setLineDash([2, 3]); context.beginPath(); context.rect(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); context.stroke(); context.setLineDash([]); } }; this.getSelection = function() { return this.selection; }; this.clear = function() { this.selection = []; } }; /** * Delete everything that is selected. */ Selection.prototype.delete = function() { this.selection.forEach(function(selectable) { selectable.delete(); }); this.clear(); }; export default Selection;