private void SetActiveAdorner(ChemicalVisual value)
        {
            switch (value)
            {
            case GroupVisual gv:
                _highlightAdorner = new GroupHoverAdorner(this, gv);
                break;

            case FunctionalGroupVisual fv:
                _highlightAdorner = new AtomHoverAdorner(this, fv);
                break;

            case AtomVisual av:
                _highlightAdorner = new AtomHoverAdorner(this, av);
                break;

            case BondVisual bv:
                _highlightAdorner = new BondHoverAdorner(this, bv);
                break;

            default:
                _highlightAdorner = null;
                break;
            }
        }
        public ChemicalVisual GetTargetedVisual(Point p)
        {
            _visuals.Clear();

            // Re-Populate _visuals via ResultCallback with *ALL* ChemicalVisual's which are under the mouse cursor
            // GroupVisual's seem to be added first (with outermost first) one for each Group
            // Next are any BondVisual's one for each Bond
            // Next is the AtomVisual for the Atom
            VisualTreeHelper.HitTest(this, null, ResultCallback, new PointHitTestParameters(p));

            // First try to get a GroupVisual
            // HACK: What guarantees that the first one found is the "top level" group?
            ChemicalVisual result = _visuals.FirstOrDefault(v => v is GroupVisual);

            // If not successful try to get an AtomVisual (should only ever be one!)
            if (result == null)
            {
                result = _visuals.FirstOrDefault(v => v is AtomVisual | v is FunctionalGroupVisual);
            }

            // Finally get first ChemicalVisual which ought to be a BondVisual
            if (result == null)
            {
                result = _visuals.FirstOrDefault();
            }

            return(result);
        }
        private HitTestResultBehavior ResultCallback(HitTestResult result)
        {
            _visualHit = result.VisualHit as ChemicalVisual;

            if (_visualHit != null)
            {
                _visuals.Add(_visualHit);
            }

            return(HitTestResultBehavior.Continue);
        }
Example #4
0
        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;
                    }
                }
            }
        }