/// <summary>
 /// Called after a UISensitiveObject has been attached to the sensitive-tree.
 /// </summary>
 /// <param name="obj">The new object.</param>
 private void ObjectAttached(UISensitiveObject obj)
 {
     if (this.raisingMouseEvents)
     {
         /// Postpone the needed sensor operations
         List <UISensitiveObject> newObjects = new List <UISensitiveObject>();
         obj.WalkSensitiveTreeDFS(ref newObjects);
         foreach (UISensitiveObject newObj in newObjects)
         {
             /// Save the created sensor and indicate that it will have to be registered.
             UIMouseSensor newSensor = newObj.MouseSensor as UIMouseSensor;
             if (newSensor == null)
             {
                 throw new UIException("Incompatible mouse sensor!");
             }
             this.tmpSensors.Add(newSensor);
             this.tmpSensorOperations.Add(true);
         }
     }
     else
     {
         /// Execute the needed sensor operations
         List <UISensitiveObject> newObjects = new List <UISensitiveObject>();
         obj.WalkSensitiveTreeDFS(ref newObjects);
         foreach (UISensitiveObject newObj in newObjects)
         {
             UIMouseSensor newSensor = newObj.MouseSensor as UIMouseSensor;
             if (newSensor == null)
             {
                 throw new UIException("Incompatible mouse sensor!");
             }
             this.allSensors.Add(newSensor);
         }
     }
 }
 /// <summary>
 /// Raises the mouse wheel events on the appropriate sensor.
 /// </summary>
 private void RaiseMouseWheelEvents(int wheelPos,
                                    RCIntVector newPointerPos,
                                    UIMouseSensor targetSensor)
 {
     if (this.wheelPosition != wheelPos)
     {
         targetSensor.OnWheel(newPointerPos, wheelPos - this.wheelPosition);
     }
 }
        /// <see cref="UIObject.Render_i"/>
        protected override void Render_i(IUIRenderContext renderContext)
        {
            UIMouseSensor sensor  = this.activeSensor != null ? this.activeSensor : this.touchedSensors[this.touchedSensors.Count - 1];
            UIPointer     pointer = sensor.GetMousePointer(this.pointerPosition);

            if (pointer == null)
            {
                pointer = this.defaultMousePointer;
            }
            if (pointer != null)
            {
                renderContext.RenderSprite(pointer.Icon,
                                           this.pointerPosition - pointer.Offset);
            }
        }
 /// <summary>
 /// Called before a UISensitiveObject is detached from the sensitive-tree.
 /// </summary>
 /// <param name="obj">The detaching object.</param>
 private void ObjectDetaching(UISensitiveObject obj)
 {
     if (this.raisingMouseEvents)
     {
         /// Postpone the needed sensor operations
         List <UISensitiveObject> detachingObjects = new List <UISensitiveObject>();
         obj.WalkSensitiveTreeDFS(ref detachingObjects);
         foreach (UISensitiveObject detachingObj in detachingObjects)
         {
             /// Save the removed sensor and indicate that it will have to be unregistered.
             UIMouseSensor removedSensor = detachingObj.MouseSensor as UIMouseSensor;
             if (removedSensor == null)
             {
                 throw new UIException("Incompatible mouse sensor!");
             }
             this.tmpSensors.Add(removedSensor);
             this.tmpSensorOperations.Add(false);
         }
     }
     else
     {
         /// Execute the needed sensor operations
         List <UISensitiveObject> detachingObjects = new List <UISensitiveObject>();
         obj.WalkSensitiveTreeDFS(ref detachingObjects);
         foreach (UISensitiveObject detachingObj in detachingObjects)
         {
             UIMouseSensor deletedSensor = detachingObj.MouseSensor as UIMouseSensor;
             if (deletedSensor != null && this.allSensors.Contains(deletedSensor))
             {
                 deletedSensor.Reset();
                 this.allSensors.Remove(deletedSensor);
                 int idxOfDeleted = this.touchedSensors.IndexOf(deletedSensor);
                 if (idxOfDeleted != -1)
                 {
                     this.touchedSensors.RemoveRange(idxOfDeleted, this.touchedSensors.Count - idxOfDeleted);
                 }
                 if (this.activeSensor == deletedSensor)
                 {
                     this.activeSensor = null;
                 }
             }
             else
             {
                 throw new UIException("UIMouseSensor not registered!");
             }
         }
     }
 }
        /// <summary>
        /// Gets the sensors that are visible at the current position of the mouse pointer.
        /// </summary>
        private List <UIMouseSensor> GetVisibleSensors(RCIntVector pointerPosition)
        {
            List <UISensitiveObject> touchedObjects = this.targetObject.GetObjectsVisibleAt(pointerPosition);
            List <UIMouseSensor>     retList        = new List <UIMouseSensor>();

            foreach (UISensitiveObject obj in touchedObjects)
            {
                UIMouseSensor sensor = obj.MouseSensor as UIMouseSensor;
                if (sensor == null)
                {
                    throw new UIException("Mouse sensor not found!");
                }
                retList.Add(sensor);
            }
            return(retList);
        }
        /// <summary>
        /// Raises the mouse button events on the appropriate sensor.
        /// </summary>
        private void RaiseMouseButtonEvents(RCSet <UIMouseButton> buttons,
                                            RCIntVector newPointerPos,
                                            UIMouseSensor targetSensor)
        {
            foreach (UIMouseButton btn in this.pressedButtons)
            {
                if (!buttons.Contains(btn))
                {
                    targetSensor.OnButtonUp(newPointerPos, btn);
                }
            }

            foreach (UIMouseButton btn in buttons)
            {
                if (!this.pressedButtons.Contains(btn))
                {
                    targetSensor.OnButtonDown(newPointerPos, btn);
                }
            }
        }
        /// <summary>
        /// Executes the saved sensor operations.
        /// </summary>
        private void ExecuteSensorOperations()
        {
            for (int i = 0; i < this.tmpSensorOperations.Count; i++)
            {
                if (this.tmpSensorOperations[i])
                {
                    /// Register sensor
                    UIMouseSensor newSensor = this.tmpSensors[i];
                    this.allSensors.Add(newSensor);
                }
                else
                {
                    /// Unregister sensor
                    UIMouseSensor deletedSensor = this.tmpSensors[i];
                    if (this.allSensors.Contains(deletedSensor))
                    {
                        deletedSensor.Reset();
                        this.allSensors.Remove(deletedSensor);
                        int idxOfDeleted = this.touchedSensors.IndexOf(deletedSensor);
                        if (idxOfDeleted != -1)
                        {
                            this.touchedSensors.RemoveRange(idxOfDeleted, this.touchedSensors.Count - idxOfDeleted);
                        }

                        if (this.activeSensor == deletedSensor)
                        {
                            this.activeSensor = null;
                        }
                    }
                    else
                    {
                        throw new UIException("UIMouseSensor not registered!");
                    }
                }
            }
            this.tmpSensorOperations.Clear();
            this.tmpSensors.Clear();
        }
        /// <summary>
        /// Ctor.
        /// </summary>
        /// <param name="targetObj">The UISensitiveObject that this UIMouseManager will be bound to.</param>
        public UIMouseManager(UISensitiveObject targetObj)
            : base(targetObj.PixelScaling, targetObj.Position, targetObj.Range)
        {
            if (targetObj == null)
            {
                throw new ArgumentNullException("targetObj");
            }
            if (targetObj.SensitiveParent != null)
            {
                throw new InvalidOperationException("targetObj must be the root of the sensitive-tree!");
            }
            if (targetObj.Parent == null)
            {
                throw new InvalidOperationException("targetObj must have a parent!");
            }

            this.objectDisposed      = false;
            this.raisingMouseEvents  = false;
            this.targetObject        = targetObj;
            this.defaultMousePointer = null;

            /// Attach this UIMouseManager to the parent of targetObject.
            this.targetObject.Parent.Attach(this);
            this.SendInFrontOfTargetObject();

            /// Subscribe for the events of the target object.
            this.targetObject.Attached         += this.OnInvalidTreeOperation;
            this.targetObject.Detached         += this.OnInvalidTreeOperation;
            this.targetObject.BroughtForward   += this.OnInvalidTreeOperation;
            this.targetObject.BroughtToTop     += this.OnInvalidTreeOperation;
            this.targetObject.SentBackward     += this.OnInvalidTreeOperation;
            this.targetObject.SentToBottom     += this.OnInvalidTreeOperation;
            this.targetObject.ClipRectChanged  += this.OnInvalidTreeOperation;
            this.targetObject.CloakRectChanged += this.OnInvalidTreeOperation;
            this.targetObject.RangeRectChanged += this.OnInvalidTreeOperation;
            this.targetObject.PositionChanged  += this.OnInvalidTreeOperation;
            this.targetObject.ObjectAttached   += this.ObjectAttached;
            this.targetObject.ObjectDetaching  += this.ObjectDetaching;

            /// Subscribe for the events of this object
            this.Attached                    += this.OnInvalidTreeOperation;
            this.Detached                    += this.OnInvalidTreeOperation;
            this.BroughtForward              += this.OnInvalidTreeOperation;
            this.BroughtToTop                += this.OnInvalidTreeOperation;
            this.SentBackward                += this.OnInvalidTreeOperation;
            this.SentToBottom                += this.OnInvalidTreeOperation;
            this.ClipRectChanged             += this.OnInvalidTreeOperation;
            this.CloakRectChanged            += this.OnInvalidTreeOperation;
            this.RangeRectChanged            += this.OnInvalidTreeOperation;
            this.PositionChanged             += this.OnInvalidTreeOperation;
            this.ChildAttached               += this.OnInvalidTreeOperation;
            this.ChildDetached               += this.OnInvalidTreeOperation;
            this.AbsolutePixelScalingChanged += this.OnInvalidTreeOperation;

            /// Subscribe for system mouse events.
            UIRoot.Instance.MouseAccess.StateChanged += this.OnMouseEvent;

            /// Set the initial position of the mouse pointer in the scaled range
            this.scale           = 1.0f;
            this.scaledRange     = this.Range * this.scale;
            this.scaledPosition  = this.scaledRange.Location + (this.scaledRange.Size / 2);
            this.pointerPosition = this.scaledPosition / this.scale;

            /// Set the initial state of the mouse wheel and buttons
            this.pressedButtons = new RCSet <UIMouseButton>();
            this.wheelPosition  = 0;

            /// Create the UIMouseSensors
            this.allSensors          = new RCSet <UIMouseSensor>();
            this.touchedSensors      = new List <UIMouseSensor>();
            this.activeSensor        = null;
            this.tmpSensorOperations = new List <bool>();
            this.tmpSensors          = new List <UIMouseSensor>();

            List <UISensitiveObject> sensitiveTree = new List <UISensitiveObject>();

            this.targetObject.WalkSensitiveTreeDFS(ref sensitiveTree);
            foreach (UISensitiveObject obj in sensitiveTree)
            {
                UIMouseSensor sensor = obj.MouseSensor as UIMouseSensor;
                if (sensor == null)
                {
                    throw new UIException("Incompatible mouse sensor!");
                }
                this.allSensors.Add(sensor);
            }
        }