private void CurrentEditor_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { var position = e.GetPosition(CurrentEditor); _currentAtomVisual = CurrentEditor.GetTargetedVisual(position) as AtomVisual; if (_currentAtomVisual == null) { _angleSnapper = new Snapper(position, EditViewModel); } else { Mouse.Capture(CurrentEditor); _angleSnapper = new Snapper(_currentAtomVisual.ParentAtom.Position, EditViewModel); _lastAtomVisual = _currentAtomVisual; } IsDrawing = true; }
private object CurrentObject(MouseButtonEventArgs e) { var visual = CurrentEditor.GetTargetedVisual(e.GetPosition(CurrentEditor)); object currentObject = null; if (visual is AtomVisual av) { currentObject = av.ParentAtom; } else if (visual is BondVisual bv) { currentObject = bv.ParentBond; } else if (visual is GroupVisual gv) { currentObject = gv.ParentMolecule; } return(currentObject); }
private bool CrowdingOut(Point p) { return(CurrentEditor.GetTargetedVisual(p) is AtomVisual); }
/// <summary> /// What happens when we release the mouse button /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void CurrentEditor_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) { CurrentEditor.ReleaseMouseCapture(); CurrentStatus = ""; if (IsDrawing) { var newAtomPos = e.GetPosition(CurrentEditor); //first get the current active visuals var landedGroupVisual = CurrentEditor.GetTargetedVisual(newAtomPos) as GroupVisual; var landedAtomVisual = CurrentEditor.GetTargetedVisual(newAtomPos) as AtomVisual; var landedBondVisual = CurrentEditor.GetTargetedVisual(newAtomPos) as BondVisual; //check to see whether or not we've clicked and released on the same atom bool sameAtom = landedAtomVisual == _currentAtomVisual; //check to see whether the target is in the same molecule bool sameMolecule = landedAtomVisual?.ParentAtom.Parent == _currentAtomVisual?.ParentAtom.Parent; if (landedGroupVisual != null) { ClearTemporaries(); return; } //check bonds first - we can't connect to a bond so we need to simply do some stuff with it if (landedBondVisual != null) { //clicking on a stereo bond should just invert it var parentBond = landedBondVisual.ParentBond; if (parentBond.Stereo == BondStereo.Hatch & EditViewModel.CurrentStereo == BondStereo.Hatch | parentBond.Stereo == BondStereo.Wedge & EditViewModel.CurrentStereo == BondStereo.Wedge) { EditViewModel.SwapBondDirection(parentBond); } else { //modify the bond attribute (order, stereo, whatever's selected really) EditViewModel.SetBondAttributes(parentBond); } } else //we clicked on empty space or an atom { Atom parentAtom = _currentAtomVisual?.ParentAtom; if (landedAtomVisual == null) //no atom hit { if (parentAtom != null) { if (_currentAtomVisual != null) { //so just sprout a chain off it at two-o-clock EditViewModel.AddAtomChain( parentAtom, _angleSnapper.SnapBond(newAtomPos, e), ClockDirections.II); } else { //otherwise create a singleton EditViewModel.AddAtomChain(null, newAtomPos, ClockDirections.II); } } else { //create a singleton //otherwise create a singleton EditViewModel.AddAtomChain(null, newAtomPos, ClockDirections.II); } } else //we went mouse-up on an atom { Atom lastAtom = landedAtomVisual.ParentAtom; if (sameAtom) //both are the same atom { if (lastAtom.Element.Symbol != EditViewModel.SelectedElement.Symbol) { EditViewModel.SetElement(EditViewModel.SelectedElement, new List <Atom> { lastAtom }); } else { var atomMetrics = GetNewChainEndPos(landedAtomVisual); EditViewModel.AddAtomChain(lastAtom, atomMetrics.NewPos, atomMetrics.sproutDir); parentAtom.UpdateVisual(); } } else //we must have hit a different atom altogether { if (parentAtom != null) { //already has a bond to the target atom var existingBond = parentAtom.BondBetween(lastAtom); if (existingBond != null) //it must be in the same molecule { EditViewModel.IncreaseBondOrder(existingBond); } else //doesn't have a bond to the target atom { if (sameMolecule) { EditViewModel.AddNewBond(parentAtom, lastAtom, parentAtom.Parent); } else { EditViewModel.JoinMolecules(parentAtom, lastAtom, EditViewModel.CurrentBondOrder, EditViewModel.CurrentStereo); } parentAtom.UpdateVisual(); lastAtom.UpdateVisual(); } } } } } } ClearTemporaries(); }
private ChemicalVisual GetTargetedVisual(MouseEventArgs e) => CurrentEditor.GetTargetedVisual(e.GetPosition(CurrentEditor));
private void CurrentEditor_MouseMove(object sender, MouseEventArgs e) { Clashing = false; CurrentPoint = e.GetPosition(CurrentEditor); //check to see whether we've dragged off the target first if (MouseIsDown && IsDrawing) { CurrentStatus = "Drag along arrow to size ring: [Esc] to cancel"; double xamlBondSize = EditViewModel.Model.XamlBondLength; if (Target != null && GetTargetedVisual(e) != Target) //dragging off a bond or atom { //first, work out how far we've dragged the mouse switch (Target) { case AtomVisual av: RingSize = GetRingSize(av, CurrentPoint, xamlBondSize); IdentifyPlacements(av.ParentAtom, xamlBondSize, out _preferredPlacements, RingSize); if (_preferredPlacements != null) { Vector parallelToBV = GetProjection(av.ParentAtom.BalancingVector(), av.Position, CurrentPoint); Point endPoint = av.Position + parallelToBV; CurrentAdorner = new NRingAdorner(CurrentEditor, EditViewModel.EditBondThickness, _preferredPlacements, av.Position, endPoint); } break; case BondVisual bv: RingSize = GetRingSizeFromEdge(bv, CurrentPoint); Vector perpToBV = GetProjection(bv.ParentBond.BondVector.Perpendicular(), bv.ParentBond.MidPoint, CurrentPoint); IdentifyPlacements(bv.ParentBond, out _preferredPlacements, RingSize, perpToBV); if (_preferredPlacements != null) { Vector?perpToAV = bv.ParentBond.GetUncrowdedSideVector(); if (perpToAV != null) { var parentBondMidPoint = bv.ParentBond.MidPoint; Vector parallelToPerp = GetProjection(perpToAV.Value, parentBondMidPoint, CurrentPoint); Point endPoint = parentBondMidPoint + parallelToPerp; CurrentAdorner = new NRingAdorner(CurrentEditor, EditViewModel.EditBondThickness, _preferredPlacements, parentBondMidPoint, endPoint); } else { CurrentAdorner = null; } } else { CurrentAdorner = null; } break; } } else if (Target == null) //dragging in empty space { RingSize = GetRingSize(FirstPoint, CurrentPoint, xamlBondSize); _preferredPlacements = MarkOutAtoms(FirstPoint, CurrentPoint - FirstPoint, xamlBondSize, RingSize); //need to check whether the user is trying to fuse without //having the pencil directly over the object! foreach (Point p in _preferredPlacements) { ChemicalVisual cv = CurrentEditor.GetTargetedVisual(p); if (cv != null) { //user is trying to fuse wrongly Clashing = true; break; } } if (Clashing) { CurrentStatus = "Can't draw ring here - drag over atom or bond to draw fused ring"; } CurrentAdorner = new NRingAdorner(CurrentEditor, EditViewModel.EditBondThickness, _preferredPlacements, FirstPoint, CurrentPoint, Clashing); } else { switch (CurrentEditor.ActiveVisual) { case AtomVisual av: CurrentStatus = "Drag from atom to size ring."; break; case BondVisual bv: CurrentStatus = "Drag from bond to size ring."; break; default: CurrentStatus = DefaultStatusText; break; } } } }