DesignerEventService.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 / Host / DesignerEventService.cs / 1 / DesignerEventService.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.ComponentModel.Design { 
 
    using System;
    using System.Collections; 
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Diagnostics;
 
    /// 
    ///     This service tracks individual designer events.  The class itself 
    ///     receives event information by direct calls from DesignerApplication. 
    ///     Those wishing to replace this service may do so but need to override
    ///     the appropriate virtual methods on DesignerApplication. 
    /// 
    internal sealed class DesignerEventService : IDesignerEventService {

        private static readonly object EventActiveDesignerChanged   = new object(); 
        private static readonly object EventDesignerCreated         = new object();
        private static readonly object EventDesignerDisposed        = new object(); 
        private static readonly object EventSelectionChanged        = new object(); 

        private ArrayList           _designerList;          // read write list used as data for the collection 
        private DesignerCollection  _designerCollection;    // public read only view of the above list
        private IDesignerHost       _activeDesigner;        // the currently active designer.  Can be null
        private EventHandlerList    _events;                // list of events.  Can be null
        private bool                _inTransaction;         // true if we are in a transaction 
        private bool                _deferredSelChange;     // true if we have a deferred selection change notification pending
 
        ///  
        ///     Internal ctor to prevent semitrust from creating us.
        ///  
        internal DesignerEventService() {
        }

        ///  
        ///     This is called by the DesignerApplication class when
        ///     a designer is activated.  The passed in designer can 
        ///     be null to signify no designer is currently active. 
        /// 
        internal void OnActivateDesigner(DesignSurface surface) { 

            IDesignerHost host = null;
            if (surface != null) {
                host = surface.GetService(typeof(IDesignerHost)) as IDesignerHost; 
                Debug.Assert(host != null, "Design surface did not provide us with a designer host");
            } 
 
            // If the designer host is not in our collection, add it.
            if (host != null && (_designerList == null || !_designerList.Contains(host))) { 
                OnCreateDesigner(surface);
            }

            if (_activeDesigner != host) { 
                IDesignerHost oldDesigner = _activeDesigner;
                _activeDesigner = host; 
 
                if (oldDesigner != null) {
                    SinkChangeEvents(oldDesigner, false); 
                }

                if (_activeDesigner != null) {
                    SinkChangeEvents(_activeDesigner, true); 
                }
 
                if (_events != null) { 
                    ActiveDesignerEventHandler eh = _events[EventActiveDesignerChanged] as ActiveDesignerEventHandler;
                    if (eh != null) { 
                        eh(this, new ActiveDesignerEventArgs(oldDesigner, host));
                    }
                }
 
                // Activating a new designer automatically pushes a new selection.
                // 
                OnSelectionChanged(this, EventArgs.Empty); 
            }
        } 

        /// 
        ///     Called when a component is added or removed from the active designer.
        ///     We raise a selection change event here. 
        /// 
        private void OnComponentAddedRemoved(object sender, ComponentEventArgs ce) { 
            IComponent comp = ce.Component as IComponent; 
            if (comp != null) {
                ISite site = comp.Site; 
                if (site != null) {
                    IDesignerHost host = site.Container as IDesignerHost;
                    if (host != null && host.Loading) {
                        _deferredSelChange = true; 
                        return;
                    } 
                } 
            }
 
            OnSelectionChanged(this, EventArgs.Empty);
        }

        ///  
        ///     Called when a component has changed on the active designer. Here
        ///     we grab the active selection service and see if the component that 
        ///     has changed is also selected.  If it is, then we raise a global 
        ///     selection changed event.
        ///  
        private void OnComponentChanged(object sender, ComponentChangedEventArgs ce) {
            IComponent comp = ce.Component as IComponent;
            if (comp != null) {
                ISite site = comp.Site; 
                if (site != null) {
                    ISelectionService ss = site.GetService(typeof(ISelectionService)) as ISelectionService; 
                    if (ss != null && ss.GetComponentSelected(comp)) { 
                        OnSelectionChanged(this, EventArgs.Empty);
                    } 
                }
            }
        }
 
        /// 
        ///     This is called by the DesignerApplication class when 
        ///     a designer is created.  Activation generally follows. 
        /// 
        internal void OnCreateDesigner(DesignSurface surface) { 

            Debug.Assert(surface != null, "DesignerApplication should not pass null here");
            IDesignerHost host = surface.GetService(typeof(IDesignerHost)) as IDesignerHost;
            Debug.Assert(host != null, "Design surface did not provide us with a designer host"); 

            if (_designerList == null) { 
                _designerList = new ArrayList(); 
            }
 
            _designerList.Add(host);

            // Hookup an object disposed handler on the design surface so we know when it's
            // gone. 
            //
            surface.Disposed += new EventHandler(this.OnDesignerDisposed); 
 
            if (_events != null) {
                DesignerEventHandler eh = _events[EventDesignerCreated] as DesignerEventHandler; 
                if (eh != null) {
                    eh(this, new DesignerEventArgs(host));
                }
            } 
        }
 
        ///  
        ///     Called by DesignSurface when it is about to be disposed.
        ///  
        private void OnDesignerDisposed(object sender, EventArgs e) {
            DesignSurface surface = (DesignSurface)sender;
            surface.Disposed -= new EventHandler(this.OnDesignerDisposed);
 
            // Detatch the selection change and add/remove events, if we were monitoring such events
            // 
            SinkChangeEvents(surface, false); 

            IDesignerHost host = surface.GetService(typeof(IDesignerHost)) as IDesignerHost; 
            Debug.Assert(host != null, "Design surface removed host too early in dispose");
            if (host != null) {

                if (_events != null) { 
                    DesignerEventHandler eh = _events[EventDesignerDisposed] as DesignerEventHandler;
                    if (eh != null) { 
                        eh(this, new DesignerEventArgs(host)); 
                    }
                } 

                if (_designerList != null) {
                    _designerList.Remove(host);
                } 
            }
        } 
 
        /// 
        ///     Called by the active designer's selection service when the selection changes. 
        ///     Also called directly by us when the active designer changes, as this is
        ///     also a change to the global selection context.
        /// 
        private void OnSelectionChanged(object sender, EventArgs e) { 

            if (_inTransaction) { 
                _deferredSelChange = true; 
            }
            else { 
                if (_events != null) {
                    EventHandler eh = _events[EventSelectionChanged] as EventHandler;
                    if (eh != null) {
                        eh(this, e); 
                    }
                } 
            } 
        }
 
        /// 
        ///     Called by the designer host when it is done loading
        ///     Here we queue up selection notification.
        ///  
        private void OnLoadComplete(object sender, EventArgs e) {
            if (_deferredSelChange) { 
                _deferredSelChange = false; 
                OnSelectionChanged(this, EventArgs.Empty);
            } 
        }

        /// 
        ///     Called by the designer host when it is entering or leaving a batch 
        ///     operation.  Here we queue up selection notification and we turn off
        ///     our UI. 
        ///  
        private void OnTransactionClosed(object sender, DesignerTransactionCloseEventArgs e) {
            if (e.LastTransaction) { 
                _inTransaction = false;
                if (_deferredSelChange) {
                    _deferredSelChange = false;
                    OnSelectionChanged(this, EventArgs.Empty); 
                }
            } 
        } 

        ///  
        ///     Called by the designer host when it is entering or leaving a batch
        ///     operation.  Here we queue up selection notification and we turn off
        ///     our UI.
        ///  
        private void OnTransactionOpened(object sender, EventArgs e) {
            _inTransaction = true; 
        } 

        ///  
        ///     Sinks or unsinks selection and component change events from the
        ///     provided service provider.  We need to raise global selection change
        ///     notifications.  A global selection change should be raised whenever
        ///     the selection of the active designer changes, whenever a component 
        ///     is added or removed from the active designer, or whenever the
        ///     active designer itself changes. 
        ///  
        private void SinkChangeEvents(IServiceProvider provider, bool sink) {
            ISelectionService ss = provider.GetService(typeof(ISelectionService)) as ISelectionService; 
            IComponentChangeService cs = provider.GetService(typeof(IComponentChangeService)) as IComponentChangeService;
            IDesignerHost host = provider.GetService(typeof(IDesignerHost)) as IDesignerHost;

            if (sink) { 
                if (ss != null) {
                    ss.SelectionChanged += new EventHandler(this.OnSelectionChanged); 
                } 
                if (cs != null) {
                    ComponentEventHandler ce = new ComponentEventHandler(this.OnComponentAddedRemoved); 
                    cs.ComponentAdded += ce;
                    cs.ComponentRemoved += ce;
                    cs.ComponentChanged += new ComponentChangedEventHandler(this.OnComponentChanged);
                } 
                if (host != null) {
                    host.TransactionOpened += new EventHandler(this.OnTransactionOpened); 
                    host.TransactionClosed += new DesignerTransactionCloseEventHandler(this.OnTransactionClosed); 
                    host.LoadComplete += new EventHandler(this.OnLoadComplete);
                    if (host.InTransaction) { 
                        OnTransactionOpened(host, EventArgs.Empty);
                    }
                }
            } 
            else {
                if (ss != null) { 
                    ss.SelectionChanged -= new EventHandler(this.OnSelectionChanged); 
                }
                if (cs != null) { 
                    ComponentEventHandler ce = new ComponentEventHandler(this.OnComponentAddedRemoved);
                    cs.ComponentAdded -= ce;
                    cs.ComponentRemoved -= ce;
                    cs.ComponentChanged -= new ComponentChangedEventHandler(this.OnComponentChanged); 
                }
                if (host != null) { 
                    host.TransactionOpened -= new EventHandler(this.OnTransactionOpened); 
                    host.TransactionClosed -= new DesignerTransactionCloseEventHandler(this.OnTransactionClosed);
                    host.LoadComplete -= new EventHandler(this.OnLoadComplete); 
                    if (host.InTransaction) {
                        OnTransactionClosed(host, new DesignerTransactionCloseEventArgs(false, true));
                    }
                } 
            }
        } 
 
        /// 
        ///     Gets the currently active designer. 
        /// 
        IDesignerHost IDesignerEventService.ActiveDesigner {
            get {
                return _activeDesigner; 
            }
        } 
 
        /// 
        ///     Gets or 
        ///     sets a collection of running design documents in the development environment.
        /// 
        DesignerCollection IDesignerEventService.Designers {
            get { 
                if (_designerList == null) {
                    _designerList = new ArrayList(); 
                } 
                if (_designerCollection == null) {
                    _designerCollection = new DesignerCollection(_designerList); 
                }
                return _designerCollection;
            }
        } 

        ///  
        ///     Adds an event that will be raised when the currently active designer 
        ///     changes.
        ///  
        event ActiveDesignerEventHandler IDesignerEventService.ActiveDesignerChanged {
            add {
                if (_events == null) {
                    _events = new EventHandlerList(); 
                }
                _events[EventActiveDesignerChanged] = Delegate.Combine((Delegate)_events[EventActiveDesignerChanged], value); 
            } 
            remove {
                if (_events != null) { 
                    _events[EventActiveDesignerChanged] = Delegate.Remove((Delegate)_events[EventActiveDesignerChanged], value);
                }
            }
        } 

        ///  
        ///     Adds an event that will be raised when a designer is created. 
        /// 
        event DesignerEventHandler IDesignerEventService.DesignerCreated { 
            add {
                if (_events == null) {
                    _events = new EventHandlerList();
                } 
                _events[EventDesignerCreated] = Delegate.Combine((Delegate)_events[EventDesignerCreated], value);
            } 
            remove { 
                if (_events != null) {
                    _events[EventDesignerCreated] = Delegate.Remove((Delegate)_events[EventDesignerCreated], value); 
                }
            }
        }
 
        /// 
        ///     Adds an event that will be raised when a designer is disposed. 
        ///  
        event DesignerEventHandler IDesignerEventService.DesignerDisposed {
            add { 
                if (_events == null) {
                    _events = new EventHandlerList();
                }
                _events[EventDesignerDisposed] = Delegate.Combine((Delegate)_events[EventDesignerDisposed], value); 
            }
            remove { 
                if (_events != null) { 
                    _events[EventDesignerDisposed] = Delegate.Remove((Delegate)_events[EventDesignerDisposed], value);
                } 
            }
        }

        ///  
        ///     Adds an event that will be raised when the global selection changes.
        ///  
        event EventHandler IDesignerEventService.SelectionChanged { 
            add {
                if (_events == null) { 
                    _events = new EventHandlerList();
                }
                _events[EventSelectionChanged] = Delegate.Combine((Delegate)_events[EventSelectionChanged], value);
            } 
            remove {
                if (_events != null) { 
                    _events[EventSelectionChanged] = Delegate.Remove((Delegate)_events[EventSelectionChanged], value); 
                }
            } 
        }
    }
}
 

// 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