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();
        }
Exemple #5
0
 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;
                    }
                }
            }
        }