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

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- StateMachineExecutionState.cs
- MouseButton.cs
- BorderSidesEditor.cs
- DrawingAttributes.cs
- odbcmetadatacolumnnames.cs
- printdlgexmarshaler.cs
- PackagingUtilities.cs
- Int32CAMarshaler.cs
- RegexGroup.cs
- TargetException.cs
- VersionValidator.cs
- DateTime.cs
- ButtonAutomationPeer.cs
- WindowsGraphicsCacheManager.cs
- DynamicField.cs
- smtpconnection.cs
- NavigationPropertySingletonExpression.cs
- ResourceContainer.cs
- ArcSegment.cs
- TextTreeUndoUnit.cs
- AnnotationAdorner.cs
- DynamicDataExtensions.cs
- WebEvents.cs
- BaseTemplateCodeDomTreeGenerator.cs
- PrefixQName.cs
- ToolStripDropDown.cs
- WebPartRestoreVerb.cs
- ConfigXmlSignificantWhitespace.cs
- PackWebResponse.cs
- ClientSponsor.cs
- QueryComponents.cs
- CacheMemory.cs
- FileDialog_Vista.cs
- ControlAdapter.cs
- TraceListeners.cs
- ObjectHelper.cs
- RuleSettingsCollection.cs
- ContentOnlyMessage.cs
- XmlEntity.cs
- FormsAuthenticationConfiguration.cs
- AppDomain.cs
- WriteFileContext.cs
- DataRelationPropertyDescriptor.cs
- HttpRequest.cs
- MenuItemBinding.cs
- SoapCodeExporter.cs
- ListChunk.cs
- MultipleFilterMatchesException.cs
- Camera.cs
- FillBehavior.cs
- MeshGeometry3D.cs
- ShapeTypeface.cs
- FullTrustAssembly.cs
- FileRecordSequenceCompletedAsyncResult.cs
- HttpConfigurationContext.cs
- PointHitTestResult.cs
- ClientApiGenerator.cs
- QilUnary.cs
- SynchronizedDisposablePool.cs
- HostingEnvironment.cs
- TextAutomationPeer.cs
- RegistryPermission.cs
- BrowserCapabilitiesCodeGenerator.cs
- DataGridViewCellCancelEventArgs.cs
- SqlConnectionPoolProviderInfo.cs
- ClientRoleProvider.cs
- XmlSerializationWriter.cs
- CopyOnWriteList.cs
- ObjectSet.cs
- StringUtil.cs
- ProviderMetadataCachedInformation.cs
- SqlClientWrapperSmiStream.cs
- WindowVisualStateTracker.cs
- FolderLevelBuildProvider.cs
- XmlSchemaSimpleType.cs
- OracleTransaction.cs
- TimeStampChecker.cs
- XmlJsonWriter.cs
- DynamicRenderer.cs
- ToolboxItem.cs
- PointKeyFrameCollection.cs
- TreeViewImageIndexConverter.cs
- AtomicFile.cs
- WebMethodAttribute.cs
- ContentFilePart.cs
- NativeMethods.cs
- Polyline.cs
- SoapExtensionTypeElementCollection.cs
- XmlDataDocument.cs
- Codec.cs
- PlaceHolder.cs
- AutoCompleteStringCollection.cs
- XmlQueryContext.cs
- Brush.cs
- CAGDesigner.cs
- KeySplineConverter.cs
- KeyedCollection.cs
- CustomErrorCollection.cs
- PersonalizationStateQuery.cs
- TagPrefixAttribute.cs