/// <summary> /// Enumerates through all descendant with the ability to filter them. /// </summary> /// <param name="me"><see cref="ISpatialBinding"/></param> /// <param name="filter">A filter function that take a descendant as a <see cref="IWindowElement"/>, and the <see cref="BindingPosition"/>.</param> /// <returns>An enumeration of all descendants</returns> public static IEnumerable<ISpatialBinding> AllDescendants( this ISpatialBinding me, BindingPosition excludes = BindingPosition.None ) { //List<IWindowElement> toExclude = new List<IWindowElement>(); //if( excludes.HasFlag( BindingPosition.Top ) ) // foreach( var e in me.Top.Descendants( me.Window ) ) toExclude.Add( e ); //if( excludes.HasFlag( BindingPosition.Bottom ) ) //{ // foreach( var e in me.Bottom.Descendants( me.Window ) ) toExclude.Add( e ); //} //if( excludes.HasFlag( BindingPosition.Left ) ) // foreach( var e in me.Left.Descendants( me.Window ) ) toExclude.Add( e ); //if( excludes.HasFlag( BindingPosition.Right ) ) // foreach( var e in me.Right.Descendants( me.Window ) ) toExclude.Add( e ); //return me.AllDescendants().Except( toExclude ); var v = new List<ISpatialBinding>(); BrowseExclude( me, v, excludes ); return v.Except( new[] { me } ); }
void FillContainers( IWindowElement master, IWindowElement slave, BindingPosition position ) { UnbindButtonContainer masterContainer; UnbindButtonContainer slaveContainer; if( !_unbindButtonContainers.TryGetValue( slave, out slaveContainer ) ) { slaveContainer = new UnbindButtonContainer( slave ); _unbindButtonContainers.Add( slave, slaveContainer ); } if( !_unbindButtonContainers.TryGetValue( master, out masterContainer ) ) { masterContainer = new UnbindButtonContainer( master ); _unbindButtonContainers.Add( master, masterContainer ); } Debug.Assert( masterContainer.GetUnbindFromPosition( position ) == null ); Debug.Assert( slaveContainer.GetUnbindFromPosition( GetOppositePosition( position ) ) == null ); IWindowElement button = InitializeButton( master, slave, position ); masterContainer.SetButton( button, position ); slaveContainer.SetButton( button, GetOppositePosition( position ) ); button.Show(); EnableUnbindButtons(); }
void DoPlaceButtons( IWindowElement button, IWindowElement window, BindingPosition position ) { Debug.Assert( Dispatcher.CurrentDispatcher == NoFocusManager.Default.ExternalDispatcher, "This method should only be called by the ExternalThread." ); double top = window.Top; double height = window.Height; double width = window.Width; double left = window.Left; if( position == BindingPosition.Top ) { button.Window.Top = top - button.Height / 2; button.Window.Left = left + width / 2 - button.Width / 2; } else if( position == BindingPosition.Bottom ) { button.Window.Top = top + height - button.Height / 2; button.Window.Left = left + width / 2 - button.Width / 2; } else if( position == BindingPosition.Right ) { button.Window.Top = top + height / 2 - button.Height / 2; button.Window.Left = left + width - button.Width / 2; } else if( position == BindingPosition.Left ) { button.Window.Top = top + height / 2 - button.Width / 2; button.Window.Left = left - button.Height / 2; } }
VMUnbindButton CreateVM( IWindowElement window, IWindowElement other, BindingPosition position ) { Debug.Assert( Dispatcher.CurrentDispatcher == NoFocusManager.Default.ExternalDispatcher, "This method should only be called by the ExternalThread." ); if( position == BindingPosition.None ) return null; Action move = null; if( position == BindingPosition.Top ) { move = () => { WindowManager.Service.Move( window, window.Top + 10, window.Left ).Broadcast(); WindowManager.Service.Move( other, other.Top - 10, other.Left ).Broadcast(); }; } else if( position == BindingPosition.Bottom ) { move = () => { WindowManager.Service.Move( window, window.Top - 10, window.Left ).Broadcast(); WindowManager.Service.Move( other, other.Top + 10, other.Left ).Broadcast(); }; } else if( position == BindingPosition.Right ) { move = () => { WindowManager.Service.Move( window, window.Top, window.Left - 10 ).Broadcast(); WindowManager.Service.Move( other, other.Top, other.Left + 10 ).Broadcast(); }; } else if( position == BindingPosition.Left ) { move = () => { WindowManager.Service.Move( window, window.Top, window.Left + 10 ).Broadcast(); WindowManager.Service.Move( other, other.Top, other.Left - 10 ).Broadcast(); }; } return new VMUnbindButton( () => { WindowBinder.Service.Unbind( window, other, false ); move(); EnableUnbindButtons(); } ); }
void CreateButton( IWindowElement master, IWindowElement slave, BindingPosition position ) { FillContainers( master, slave, position ); }
internal static BindingPosition GetOppositePosition( BindingPosition position ) { if( position == BindingPosition.Bottom ) return BindingPosition.Top; if( position == BindingPosition.Top ) return BindingPosition.Bottom; if( position == BindingPosition.Left ) return BindingPosition.Right; if( position == BindingPosition.Right ) return BindingPosition.Left; return BindingPosition.None; }
public static IEnumerable<IWindowElement> SubTree( this ISpatialBinding me, BindingPosition position ) { var visited = new List<IWindowElement>(); visited.Add( me.Window ); if( me.Top != null && position.HasFlag( BindingPosition.Top ) ) Browse( me.Top, visited ); if( me.Left != null && position.HasFlag( BindingPosition.Left ) ) Browse( me.Left, visited ); if( me.Bottom != null && position.HasFlag( BindingPosition.Bottom ) ) Browse( me.Bottom, visited ); if( me.Right != null && position.HasFlag( BindingPosition.Right ) ) Browse( me.Right, visited ); return visited.Except( new[] { me.Window } ); }
public IWindowElement GetUnbindFromPosition( BindingPosition position ) { if( position == BindingPosition.Top ) return TopButton; else if( position == BindingPosition.Bottom ) return BottomButton; else if( position == BindingPosition.Left ) return LeftButton; else if( position == BindingPosition.Right ) return RightButton; return null; }
private bool CanBind( IWindowElement target, IWindowElement origin, BindingPosition position, out SpatialBinding targetSpatialBinding, out SpatialBinding originSpatialBinding ) { Debug.Assert( Dispatcher.CurrentDispatcher == Application.Current.Dispatcher, "This method should only be called by the Application Thread." ); originSpatialBinding = null; using( _logger.OpenGroup( LogLevel.Info, "Master binding..." ) ) { if( _spatialBindings.TryGetValue( target, out targetSpatialBinding ) ) { if( position == BindingPosition.Top && targetSpatialBinding.Top != null ) { _logger.Trace( "{0} is already bound to {1} at position {2}.", targetSpatialBinding.Top.Window.Name, target.Name, position ); return false; } else if( position == BindingPosition.Left && targetSpatialBinding.Left != null ) { _logger.Trace( "{0} is already bound to {1} at position {2}.", targetSpatialBinding.Left.Window.Name, target.Name, position ); return false; } else if( position == BindingPosition.Bottom && targetSpatialBinding.Bottom != null ) { _logger.Trace( "{0} is already bound to {1} at position {2}.", targetSpatialBinding.Bottom.Window.Name, target.Name, position ); return false; } else if( position == BindingPosition.Right && targetSpatialBinding.Right != null ) { _logger.Trace( "{0} is already bound to {1} at position {2}.", targetSpatialBinding.Right.Window.Name, target.Name, position ); return false; } else _logger.Trace( "{0} already exists in bindings but no window attached at position {1}.", target.Name, position ); } else { _logger.Trace( "Fresh new window" ); } } using( _logger.OpenGroup( LogLevel.Info, "Slave binding..." ) ) { if( _spatialBindings.TryGetValue( origin, out originSpatialBinding ) ) { if( position == BindingPosition.Top && originSpatialBinding.Bottom != null ) { _logger.Trace( "{0} is already bound to {1} at position {2}.", originSpatialBinding.Bottom.Window.Name, target.Name, position ); return false; } else if( position == BindingPosition.Left && originSpatialBinding.Right != null ) { _logger.Trace( "{0} is already bound to {1} at position {2}.", originSpatialBinding.Right.Window.Name, target.Name, position ); return false; } else if( position == BindingPosition.Bottom && originSpatialBinding.Top != null ) { _logger.Trace( "{0} is already bound to {1} at position {2}.", originSpatialBinding.Top.Window.Name, target.Name, position ); return false; } else if( position == BindingPosition.Right && originSpatialBinding.Left != null ) { _logger.Trace( "{0} is already bound to {1} at position {2}.", originSpatialBinding.Left.Window.Name, target.Name, position ); return false; } else _logger.Trace( "{0} already exists in bindings but no window attached at position {1}.", origin.Name, position ); } else { _logger.Trace( "Fresh new window" ); //spatialBinding = new SpatialBinding( slave ); } } return true; }
public IBindResult PreviewBind( IWindowElement target, IWindowElement origin, BindingPosition position ) { if( Dispatcher.CurrentDispatcher != Application.Current.Dispatcher ) throw new InvalidOperationException( "This method should only be called by the Application Thread." ); if( target == null ) throw new ArgumentNullException( "master" ); if( origin == null ) throw new ArgumentNullException( "slave" ); SpatialBinding targetSpatialBinding = null; SpatialBinding originSpatialBinding = null; if( CanBind( target, origin, position, out targetSpatialBinding, out originSpatialBinding ) ) { var binding = new SimpleBinding { Target = target, Origin = origin, Position = position }; var evt = new WindowBindedEventArgs { Binding = binding, BindingType = BindingEventType.Attach }; if( PreviewBinding != null ) PreviewBinding( this, evt ); return new BindResult( this, binding ); } return NullResult.Default; }
public void Bind( IWindowElement master, IWindowElement slave, BindingPosition position, bool saveBinding = false ) { if( Dispatcher.CurrentDispatcher != Application.Current.Dispatcher ) throw new InvalidOperationException( "This method should only be called by the Application Thread." ); if( master == null ) throw new ArgumentNullException( "master" ); if( slave == null ) throw new ArgumentNullException( "slave" ); //Console.WriteLine( "BIND thread id: {0} TimeSpan : {1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.Ticks ); // Spatial binding point of view using( _logger.OpenGroup( LogLevel.Info, "Attaching {0} on {1} at {2}", master.Name, slave.Name, position.ToString() ) ) { SpatialBinding spatialBinding = null; SpatialBinding slaveSpatialBinding = null; if( CanBind( master, slave, position, out spatialBinding, out slaveSpatialBinding ) ) { _logger.Trace( "Before binding..." ); var binding = new SimpleBinding { Target = master, Origin = slave, Position = position }; var evt = new WindowBindingEventArgs { Binding = binding, BindingType = BindingEventType.Attach }; if( BeforeBinding != null ) BeforeBinding( this, evt ); if( evt.Canceled == true ) { _logger.Trace( "...canceled. The reason was {0}.", evt.CancelReason ?? "No Reason" ); } else { if( spatialBinding == null ) { spatialBinding = new SpatialBinding( master ); _spatialBindings.Add( master, spatialBinding ); } if( slaveSpatialBinding == null ) { slaveSpatialBinding = new SpatialBinding( slave ); _spatialBindings.Add( slave, slaveSpatialBinding ); } Debug.Assert( spatialBinding != null ); Debug.Assert( slaveSpatialBinding != null ); //TODO : FIXWITHDOCKING if( position == BindingPosition.Top ) { spatialBinding.Top = slaveSpatialBinding; slaveSpatialBinding.Bottom = spatialBinding; } if( position == BindingPosition.Left ) { spatialBinding.Left = slaveSpatialBinding; slaveSpatialBinding.Right = spatialBinding; } if( position == BindingPosition.Bottom ) { spatialBinding.Bottom = slaveSpatialBinding; slaveSpatialBinding.Top = spatialBinding; } if( position == BindingPosition.Right ) { spatialBinding.Right = slaveSpatialBinding; slaveSpatialBinding.Left = spatialBinding; } if( saveBinding ) _persistantBindings.Add( binding ); var evtAfter = new WindowBindedEventArgs { Binding = binding, BindingType = BindingEventType.Attach }; _logger.Trace( "After binding..." ); if( AfterBinding != null ) AfterBinding( this, evtAfter ); } } } }
//public HitTestResult( IWindowElement windowElement, IWindowElement matchedWindow, Rect enlargedRectangle, Rect overlapRectangle ) //{ // Target = windowElement; // Origin = matchedWindow; // if( overlapRectangle.Bottom == enlargedRectangle.Bottom && overlapRectangle.Height != enlargedRectangle.Height ) Position = BindingPosition.Top; // else if( overlapRectangle.Top == enlargedRectangle.Top && overlapRectangle.Height != enlargedRectangle.Height ) Position = BindingPosition.Bottom; // else if( overlapRectangle.Right == enlargedRectangle.Right && overlapRectangle.Width != enlargedRectangle.Width ) Position = BindingPosition.Left; // else if( overlapRectangle.Left == enlargedRectangle.Left && overlapRectangle.Width != enlargedRectangle.Width ) Position = BindingPosition.Right; // else Position = BindingPosition.None; //} public HitTestResult( IWindowElement origin, IWindowElement target, BindingPosition position ) { Target = target; Origin = origin; Position = position; }
private static void BrowseExclude( this ISpatialBinding me, IList<ISpatialBinding> visited, BindingPosition excludes ) { if( !visited.Contains( me ) ) { visited.Add( me ); if( me.Top != null && !excludes.HasFlag( BindingPosition.Top ) ) BrowseExclude( me.Top, visited, excludes ); if( me.Left != null && !excludes.HasFlag( BindingPosition.Left ) ) BrowseExclude( me.Left, visited, excludes ); if( me.Bottom != null && !excludes.HasFlag( BindingPosition.Bottom ) ) BrowseExclude( me.Bottom, visited, excludes ); if( me.Right != null && !excludes.HasFlag( BindingPosition.Right ) ) BrowseExclude( me.Right, visited, excludes ); } }
WindowElement InitializeButton( IWindowElement window, IWindowElement other, BindingPosition position ) { Debug.Assert( Dispatcher.CurrentDispatcher == NoFocusManager.Default.ExternalDispatcher, "This method should only be called by the ExternalThread." ); WindowElement button = null; button = new WindowElement( new UnbindButtonView() { DataContext = CreateVM( window, other, position ) }, "UnbindButton" ); DoPlaceButtons( button, window, position ); TopMostService.Service.RegisterTopMostElement( "30", button.Window ); return button; }
public void Add( string target, string origin, BindingPosition position ) { Bindings.Add( new SerializableBinding( target, origin, position ) ); }
public IWindowElement this[BindingPosition p] { get { return GetUnbindFromPosition( p ); } set { SetButton( value, p ); } }
internal SerializableBinding( string target, string origin, BindingPosition position ) { Target = target; Origin = origin; Position = position; }
public void SetButton( IWindowElement button, BindingPosition position ) { Debug.Assert( position != BindingPosition.None ); if( position == BindingPosition.Top ) TopButton = button; else if( position == BindingPosition.Bottom ) BottomButton = button; else if( position == BindingPosition.Left ) LeftButton = button; else if( position == BindingPosition.Right ) RightButton = button; }
void ResizingWindow( ISpatialBinding binding, BindingPosition masterPosition = BindingPosition.None ) { Debug.Assert( Dispatcher.CurrentDispatcher == Application.Current.Dispatcher, "This method should only be called by the ExternalThread." ); IWindowElement reference = binding.Window; IWindowElement slave = null; if( masterPosition != BindingPosition.Top && binding.Top != null ) { slave = binding.Top.Window; if( reference.Height != slave.Height ) { WindowManager.Resize( slave, reference.Width, slave.Height ); ResizingWindow( binding.Top, BindingPosition.Bottom ); } WindowManager.Move( slave, reference.Top - slave.Height, reference.Left ); } if( masterPosition != BindingPosition.Bottom && binding.Bottom != null ) { slave = binding.Bottom.Window; if( reference.Height != slave.Height ) { WindowManager.Resize( slave, reference.Width, slave.Height ); ResizingWindow( binding.Bottom, BindingPosition.Top ); } WindowManager.Move( slave, reference.Top + reference.Height, reference.Left ); } if( masterPosition != BindingPosition.Left && binding.Left != null ) { slave = binding.Left.Window; if( reference.Width != slave.Width ) { WindowManager.Resize( slave, slave.Width, reference.Height ); ResizingWindow( binding.Left, BindingPosition.Right ); } WindowManager.Move( slave, reference.Top, reference.Left - slave.Width ); } if( masterPosition != BindingPosition.Right && binding.Right != null ) { slave = binding.Right.Window; if( reference.Width != slave.Width ) { WindowManager.Resize( slave, slave.Width, reference.Height ); ResizingWindow( binding.Right, BindingPosition.Left ); } WindowManager.Move( slave, reference.Top, reference.Left + reference.Width ); } }