ToolboxItemSnapLineBehavior.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / Designer / WinForms / System / WinForms / Design / Behavior / ToolboxItemSnapLineBehavior.cs / 1 / ToolboxItemSnapLineBehavior.cs

                            namespace System.Windows.Forms.Design.Behavior { 
    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.ComponentModel.Design; 
    using System.Design;
    using System.Diagnostics; 
    using System.Drawing; 
    using System.Drawing.Design;
    using System.Windows.Forms.Design; 

    /// 
    /// 
    ///     This class implements the behavior provided by DocumentDesigner 
    ///     when the user is dragging a valid toolbox item.  Here, we'll render a
    ///     default 'box' beneath the cursor that snaps to edges of other 
    ///     components on the designer's surface. 
    /// 
    internal class ToolboxItemSnapLineBehavior : Behavior { 

        private IServiceProvider        serviceProvider;//used for snaplines
        private BehaviorService         behaviorService;//pointer to our big & bad service
        private ControlDesigner         designer;//used for snaplines as well 
        private bool                    isPushed;//used to track if this is currently on the stack or not
        private Graphics                graphics;//graphics object for the adornerwindow 
        private Rectangle               lastRectangle;//cache the last mouse loc - so we can ignore when mouse doesn't move 
        private Point                   lastOffset;//cache the last snap so we know where to create our control if dropped
        private DragAssistanceManager   dragManager; //used to apply snaplines when dragging a new tool rect on the designer's surface 
        private bool                    targetAllowsSnapLines;//indicates if the drop target allows snaplines (flowpanels don't for ex)
        private StatusCommandUI         statusCommandUI; //used to update the StatusBar Information.
        private bool                    targetAllowsDragBox;    //indicates if the drop target allows the generic drag box to be drawn
 
        /// 
        ///  
        ///     Constructor that caches the designer (which invoked us) and a ptr 
        ///     to the BehaviorService.
        ///  
        public ToolboxItemSnapLineBehavior(IServiceProvider serviceProvider, BehaviorService behaviorService) {
            this.serviceProvider = serviceProvider;
            this.behaviorService = behaviorService;
            this.designer = null; 
            this.isPushed = false;
            this.lastRectangle= Rectangle.Empty; 
            this.lastOffset = Point.Empty; 
            statusCommandUI = new StatusCommandUI(serviceProvider);
            this.targetAllowsDragBox = true; 
            targetAllowsSnapLines = true;

        }
 
        public ToolboxItemSnapLineBehavior(IServiceProvider serviceProvider, BehaviorService behaviorService, ControlDesigner controlDesigner)
            : this(serviceProvider, behaviorService) { 
 
            this.designer = controlDesigner;
            //check to see if the current designer participate with SnapLines 
            if (controlDesigner != null && !controlDesigner.ParticipatesWithSnapLines) {
                targetAllowsSnapLines = false;
            }
        } 

        public ToolboxItemSnapLineBehavior(IServiceProvider serviceProvider, BehaviorService behaviorService, ControlDesigner controlDesigner, bool allowDragBox) 
            : this(serviceProvider, behaviorService, controlDesigner) { 

            this.designer = controlDesigner; 
            this.targetAllowsDragBox = allowDragBox;
        }

 
        /// 
        ///     Demand creates the Graphics object from the AdornerWindow. 
        ///  
        private Graphics Graphics {
            get { 
                if (graphics == null) {
                    graphics = behaviorService.AdornerWindowGraphics;
                }
                return graphics; 
            }
        } 
 
        /// 
        ///  
        ///     OnDragDrop can be overridden so that a Behavior can specify its own
        ///     Drag/Drop rules.
        ///
 
        public bool IsPushed {
            get { 
                return isPushed; 

            } 
            set {
                isPushed = value;

                if (isPushed) { 
                    if (dragManager == null) {
                        dragManager = new DragAssistanceManager(serviceProvider); 
                    } 
                }
                else { 
                    //clean up all our temp objects
                    if (!lastRectangle.IsEmpty) {
                        behaviorService.Invalidate(lastRectangle);
                    } 

                    lastOffset = Point.Empty; 
                    lastRectangle = Rectangle.Empty; 

                    //destroy the snapline engine (if we used it) 
                    if (dragManager != null) {
                        dragManager.OnMouseUp();
                        dragManager = null;
                    } 

                    //dispose graphics 
                    if (graphics != null) { 
                        graphics.Dispose();
                        graphics = null; 
                    }
                }
            }
        } 

        ///  
        ///     Called on a DragDrop - this generates our extra drag info 
        ///     to pass along to the base class.  Basically, we get the
        ///     last-rendered snaplines before the drop and attempt to 
        ////    identify to which direction the mouse was snapped.
        /// 
        private ToolboxSnapDragDropEventArgs CreateToolboxSnapArgs(DragEventArgs e, Point mouseLoc) {
 
            //we're trying to set these two vars here...
            ToolboxSnapDragDropEventArgs.SnapDirection snapDirections = ToolboxSnapDragDropEventArgs.SnapDirection.None; 
            Point offset = Point.Empty; 

            //as soon as these vars are true - we can stop looking at lines 
            bool horizontalComponentIdentified = false;
            bool verticalComponentIdentified = false;

            if (dragManager != null) { 
                DragAssistanceManager.Line[] lines = dragManager.GetRecentLines();
 
                foreach (DragAssistanceManager.Line line in lines) { 
                    if (line.LineType == DragAssistanceManager.LineType.Standard) {
                        if (!horizontalComponentIdentified && line.x1 == line.x2) { 
                            //check for vertical equality
                            if (line.x1 == lastRectangle.Left) {
                                //we had a line on the left of the box - so we must have snapped left
                                snapDirections |= ToolboxSnapDragDropEventArgs.SnapDirection.Left; 
                                offset.X = lastRectangle.Left - mouseLoc.X;
                            } 
                            else {//MUST BE RIGHT?  if (lines.x1 == lastRectangle.Right) { 
                                //we had a line on the right of the box - so we must have snapped right
                                snapDirections |= ToolboxSnapDragDropEventArgs.SnapDirection.Right; 
                                offset.X = lastRectangle.Right - mouseLoc.X;
                            }
                            horizontalComponentIdentified = true;
                        } 
                        else if (!verticalComponentIdentified && line.y1 == line.y2) {
                            //check for vertical equality 
                            if (line.y1 == lastRectangle.Top) { 
                                //we had a line on the top of the box - so we must have snapped top
                                snapDirections |= ToolboxSnapDragDropEventArgs.SnapDirection.Top; 
                                offset.Y = lastRectangle.Top - mouseLoc.Y;
                            }
                            else if (line.y1 == lastRectangle.Bottom) {
                                //we had a line on the bottom of the box - so we must have snapped bottom 
                                snapDirections |= ToolboxSnapDragDropEventArgs.SnapDirection.Bottom;
                                offset.Y = lastRectangle.Bottom - mouseLoc.Y; 
                            } 
                            verticalComponentIdentified = true;
                        } 
                    }
                    else if ((line.LineType == DragAssistanceManager.LineType.Margin) ||
                                (line.LineType == DragAssistanceManager.LineType.Padding)) {
                        if (!verticalComponentIdentified && line.x1 == line.x2) { 
                            //now, we're looking at a vertical margin line - is it above?
                            if (Math.Max(line.y1, line.y2) <= lastRectangle.Top) { 
                                //aha - we had a margin line at the top of the box 
                                snapDirections |= ToolboxSnapDragDropEventArgs.SnapDirection.Top;
                                offset.Y = lastRectangle.Top - mouseLoc.Y; 
                            }
                            else {
                                //aha - we had a margin line at the bottom of the box
                                snapDirections |= ToolboxSnapDragDropEventArgs.SnapDirection.Bottom; 
                                offset.Y = lastRectangle.Bottom - mouseLoc.Y;
                            } 
                            verticalComponentIdentified = true; 
                        }
                        else if (!horizontalComponentIdentified && line.y1 == line.y2) { 
                            //now, we're looking at a horz margin line - is it left?
                            if (Math.Max(line.x1, line.x2) <= lastRectangle.Left) {
                                //aha - we had a margin line at the left of the box
                                snapDirections |= ToolboxSnapDragDropEventArgs.SnapDirection.Left; 
                                offset.X = lastRectangle.Left - mouseLoc.X;
                            } 
                            else { 
                                //aha - we had a margin line at the right of the box
                                snapDirections |= ToolboxSnapDragDropEventArgs.SnapDirection.Right; 
                                offset.X = lastRectangle.Right - mouseLoc.X;
                            }
                            horizontalComponentIdentified = true;
                        } 
                    }
 
                    if (horizontalComponentIdentified && verticalComponentIdentified) { 
                        //we've found both components - stop looping
                        break; 
                    }
                }
            }
 
            //set default values is we haven't identified any 'snaps'
            if (!horizontalComponentIdentified) { 
                snapDirections |= ToolboxSnapDragDropEventArgs.SnapDirection.Left; 
                offset.X = lastRectangle.Left - mouseLoc.X;
            } 
            if (!verticalComponentIdentified) {
                snapDirections |= ToolboxSnapDragDropEventArgs.SnapDirection.Top;
                offset.Y = lastRectangle.Top - mouseLoc.Y;
            } 

            //create our arg and pass it back 
            return new ToolboxSnapDragDropEventArgs(snapDirections, offset, e); 
        }
 
        /// 
        /// 
        ///     Used when dragging a new tool rect on the designer's surface -
        ///     this will return some generic snaplines Allowing the rect to 
        ///     snap to existing control edges on the surface.
        ///  
        private SnapLine[] GenerateNewToolSnapLines(Rectangle r) { 
            return new SnapLine[] {new SnapLine(SnapLineType.Left, r.Left),
                               new SnapLine(SnapLineType.Right, r.Right), 
                               new SnapLine(SnapLineType.Bottom, r.Bottom),
                               new SnapLine(SnapLineType.Top, r.Top),
                               new SnapLine(SnapLineType.Horizontal, r.Top -4, SnapLine.MarginTop, SnapLinePriority.Always),
                               new SnapLine(SnapLineType.Horizontal, r.Bottom + 3, SnapLine.MarginBottom, SnapLinePriority.Always), 
                               new SnapLine(SnapLineType.Vertical, r.Left -4, SnapLine.MarginLeft, SnapLinePriority.Always),
                               new SnapLine(SnapLineType.Vertical, r.Right + 3, SnapLine.MarginRight, SnapLinePriority.Always)}; 
 
        }
 
        /// 
        /// 
        ///     OnDragDrop can be overridden so that a Behavior can specify its own
        ///     Drag/Drop rules. 
        /// 
        public override void OnDragDrop(Glyph g, DragEventArgs e) { 
 
            behaviorService.PopBehavior(this);
 
            try {
                //offset the mouse loc to screen coords for calculations on drops
                Point screenOffset = behaviorService.AdornerWindowToScreen();
 
                //build up our extra-special event args
                ToolboxSnapDragDropEventArgs se = CreateToolboxSnapArgs(e, new Point(e.X - screenOffset.X, e.Y - screenOffset.Y)); 
 
                base.OnDragDrop(g, se);
            } 
            finally {
                //clear everything up
                IsPushed = false;
            } 
        }
 
        // When we begin a drag we need to remove the glyphs that do not allow drops. 
        // VSWhidbey #487816
        public void OnBeginDrag() { 

            Adorner bodyAdorner = null;
            SelectionManager selMgr = (SelectionManager)serviceProvider.GetService(typeof(SelectionManager));
            if (selMgr != null) { 
                bodyAdorner = selMgr.BodyGlyphAdorner;
            } 
 
            ArrayList glyphsToRemove = new ArrayList();
            foreach (ControlBodyGlyph body in bodyAdorner.Glyphs) { 
                Control ctl = body.RelatedComponent as Control;
                if (ctl != null)
                {
                    if (!ctl.AllowDrop) { 
                        glyphsToRemove.Add(body);
                    } 
                } 
            }
 
            foreach (Glyph glyph in glyphsToRemove) {
                bodyAdorner.Glyphs.Remove(glyph);
            }
 
        }
 
        public override bool OnMouseMove(Glyph g, MouseButtons button, Point mouseLoc) { 

            bool altKeyPressed = Control.ModifierKeys == Keys.Alt; 

            if (altKeyPressed && dragManager != null) {
                //erase any snaplines (if we had any)
                dragManager.EraseSnapLines(); 
            }
 
            //call base 
            bool retValue = base.OnMouseMove(g, button, mouseLoc);
 
            //identify where the new box should be...
            Rectangle newRectangle = new Rectangle(mouseLoc.X- DesignerUtils.BOXIMAGESIZE /2, mouseLoc.Y- DesignerUtils.BOXIMAGESIZE /2,
                                              DesignerUtils.BOXIMAGESIZE ,DesignerUtils.BOXIMAGESIZE );
 
            //don't do anything if the loc is the same
            if (newRectangle != lastRectangle) { 
 
                if (dragManager != null && targetAllowsSnapLines && !altKeyPressed) {
                    lastOffset = dragManager.OnMouseMove(newRectangle, GenerateNewToolSnapLines(newRectangle)); 
                    newRectangle.Offset(lastOffset.X, lastOffset.Y);
                }

                //erase old 
                if (!lastRectangle.IsEmpty) {
                    //build up the invalid region 
                    Region invalidRegion = new Region(lastRectangle); 
                    invalidRegion.Exclude(newRectangle);
                    behaviorService.Invalidate(invalidRegion); 
                }

                if (targetAllowsDragBox) {
                    Graphics.DrawImage(DesignerUtils.BoxImage, newRectangle.Location); 
                }
 
                //offset the mouse loc to screen coords for calculations on drops 
                IDesignerHost host = (IDesignerHost)serviceProvider.GetService(typeof(IDesignerHost));
                if (host != null) 
                {
                    Control baseControl = host.RootComponent as Control;
                    if (baseControl != null)
                    { 
                        Point adornerServiceOrigin = behaviorService.MapAdornerWindowPoint(baseControl.Handle, new Point(0, 0));
                        Rectangle statusRect = new Rectangle(newRectangle.X - adornerServiceOrigin.X, newRectangle.Y - adornerServiceOrigin.Y, 0, 0); 
                        if (statusCommandUI != null) 
                        {
                            statusCommandUI.SetStatusInformation(statusRect); 
                        }
                    }
                }
 
                if (dragManager != null && targetAllowsSnapLines && !altKeyPressed) {
                    dragManager.RenderSnapLinesInternal(); 
                } 

                //store this off for the next time around 
                lastRectangle = newRectangle;
            }

            return retValue; 
        }
 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK