Пример #1
0
        public void UpdateLayout()
        {
            base.VerifyAccess();
            if (!this._isUpdating)
            {
                this._isUpdating = true;
                WindowManager.Instance.Invalidate();
                LayoutQueue measureQueue = this.MeasureQueue;
                LayoutQueue arrangeQueue = this.ArrangeQueue;
                int         num          = 0;
                bool        flag         = true;
                UIElement   parent       = null;
                try
                {
                    this.invalidateTreeIfRecovering();
                    while (!this.MeasureQueue.IsEmpty || !this.ArrangeQueue.IsEmpty)
                    {
                        if (++num > 0x99)
                        {
                            base.Dispatcher.BeginInvoke(this._updateLayoutBackground, this);
                            parent = null;
                            flag   = false;
                            return;
                        }
                        int  num2          = 0;
                        long loopStartTime = 0L;
Label_0070:
                        if (++num2 > 0x99)
                        {
                            num2 = 0;
                            if (this.LimitExecution(ref loopStartTime))
                            {
                                parent = null;
                                flag   = false;
                                return;
                            }
                        }
                        parent = measureQueue.GetTopMost();
                        if (parent != null)
                        {
                            parent.Measure(parent._previousAvailableWidth, parent._previousAvailableHeight);
                            measureQueue.RemoveOrphans(parent);
                            goto Label_0070;
                        }
                        num2          = 0;
                        loopStartTime = 0L;
Label_00C7:
                        if (++num2 > 0x99)
                        {
                            num2 = 0;
                            if (this.LimitExecution(ref loopStartTime))
                            {
                                parent = null;
                                flag   = false;
                                return;
                            }
                        }
                        parent = arrangeQueue.GetTopMost();
                        if (parent != null)
                        {
                            int num4;
                            int num5;
                            int num6;
                            int num7;
                            this.getProperArrangeRect(parent, out num4, out num5, out num6, out num7);
                            parent.Arrange(num4, num5, num6, num7);
                            arrangeQueue.RemoveOrphans(parent);
                            goto Label_00C7;
                        }
                    }
                    parent = null;
                    flag   = false;
                }
                finally
                {
                    this._isUpdating          = false;
                    this._layoutRequestPosted = false;
                    if (flag)
                    {
                        this._gotException       = true;
                        this._forceLayoutElement = parent;
                        base.Dispatcher.BeginInvoke(this._updateLayoutBackground, this);
                    }
                }
            }
        }
Пример #2
0
        public void UpdateLayout()
        {
            VerifyAccess();

            //make UpdateLayout to be a NOP if called during UpdateLayout.
            if (_isUpdating)
            {
                return;
            }

            _isUpdating = true;

            WindowManager.Instance.Invalidate();

            LayoutQueue measureQueue = MeasureQueue;
            LayoutQueue arrangeQueue = ArrangeQueue;

            int       cnt            = 0;
            bool      gotException   = true;
            UIElement currentElement = null;

            //NOTE:
            //
            //There are a bunch of checks here that break out of and re-queue layout if
            //it looks like things are taking too long or we have somehow gotten into an
            //infinite loop.   In the TinyCLR we will probably have better ways of
            //dealing with a bad app through app domain separation, but keeping this
            //robustness can't hurt.  In a single app domain scenario, it could
            //give the opportunity to get out to the system if something is misbehaving,
            //we like this kind of reliability in embedded systems.
            //

            try
            {
                invalidateTreeIfRecovering();

                while ((!MeasureQueue.IsEmpty) || (!ArrangeQueue.IsEmpty))
                {
                    if (++cnt > 153)
                    {
                        //loop detected. Lets re-queue and let input/user to correct the situation.
                        //
                        Dispatcher.BeginInvoke(_updateLayoutBackground, this);
                        currentElement = null;
                        gotException   = false;
                        return;
                    }

                    //loop for Measure
                    //We limit the number of loops here by time - normally, all layout
                    //calculations should be done by this time, this limit is here for
                    //emergency, "infinite loop" scenarios - yielding in this case will
                    //provide user with ability to continue to interact with the app, even though
                    //it will be sluggish. If we don't yield here, the loop is goign to be a deadly one

                    int      loopCounter   = 0;
                    TimeSpan loopStartTime = TimeSpan.Zero;

                    while (true)
                    {
                        if (++loopCounter > 153)
                        {
                            loopCounter = 0;
                            if (LimitExecution(ref loopStartTime))
                            {
                                currentElement = null;
                                gotException   = false;
                                return;
                            }
                        }

                        currentElement = measureQueue.GetTopMost();

                        if (currentElement == null)
                        {
                            break;                         //exit if no more Measure candidates
                        }
                        currentElement.Measure(
                            currentElement._previousAvailableWidth,
                            currentElement._previousAvailableHeight
                            );

                        measureQueue.RemoveOrphans(currentElement);
                    }

                    //loop for Arrange
                    //if Arrange dirtied the tree go clean it again

                    //We limit the number of loops here by time - normally, all layout
                    //calculations should be done by this time, this limit is here for
                    //emergency, "infinite loop" scenarios - yielding in this case will
                    //provide user with ability to continue to interact with the app, even though
                    //it will be sluggish. If we don't yield here, the loop is goign to be a deadly one
                    loopCounter   = 0;
                    loopStartTime = TimeSpan.Zero;

                    while (true)
                    {
                        if (++loopCounter > 153)
                        {
                            loopCounter = 0;
                            if (LimitExecution(ref loopStartTime))
                            {
                                currentElement = null;
                                gotException   = false;
                                return;
                            }
                        }

                        currentElement = arrangeQueue.GetTopMost();

                        if (currentElement == null)
                        {
                            break;                         //exit if no more Arrange candidates
                        }
                        int arrangeX, arrangeY, arrangeWidth, arrangeHeight;

                        getProperArrangeRect(currentElement, out arrangeX, out arrangeY, out arrangeWidth, out arrangeHeight);

#if TINYCLR_DEBUG_LAYOUT
                        Trace.Print("arrangeWidth = " + arrangeWidth);
                        Trace.Print("arrangeHeight = " + arrangeWidth);
#endif

                        currentElement.Arrange(arrangeX, arrangeY, arrangeWidth, arrangeHeight);
                        arrangeQueue.RemoveOrphans(currentElement);
                    }

                    /* REFACTOR -- do we need Layout events and Size changed events?
                     *
                     *                  //let LayoutUpdated handlers to call UpdateLayout
                     *                  //note that it means we can get reentrancy into UpdateLayout past this point,
                     *                  //if any of event handlers call UpdateLayout sync. Need to protect from reentrancy
                     *                  //in the firing methods below.
                     *
                     *                  fireSizeChangedEvents();
                     *                  if ((!MeasureQueue.IsEmpty) || (!ArrangeQueue.IsEmpty)) continue;
                     *                  fireLayoutUpdateEvent();
                     */
                }

                currentElement = null;
                gotException   = false;
            }
            finally
            {
                _isUpdating          = false;
                _layoutRequestPosted = false;

                if (gotException)
                {
                    //set indicator
                    _gotException       = true;
                    _forceLayoutElement = currentElement;

                    //make attempt to request the subsequent layout calc
                    Dispatcher.BeginInvoke(_updateLayoutBackground, this);
                }
            }
        }