예제 #1
0
        /// <summary>Gets the renderable data at the given point (may be null).</summary>
        public RenderableData Get(float x, float y)
        {
            InputGridEntry ige = Front;

            while (ige != null)
            {
                // Get the render data:
                RenderableData renderData = ige.RenderData;

                // Get the zone:
                ScreenRegion screenBox = renderData.OnScreenRegion;

                // Is this node visible and is the point within it?
                if (screenBox != null && screenBox.Contains(x, y))
                {
                    // At this point, the mouse could still be outside it.
                    // This happens with inline elements - their clipping boundary can contain multiple sub-boxes.
                    // So, time to check how many boxes it has, then the individual boxes if we've got more than one.

                    LayoutBox box = renderData.FirstBox;

                    if (box != null && box.NextInElement != null)
                    {
                        // Multiple boxes. Must be contained in one of them to win.

                        while (box != null)
                        {
                            if (box.Contains(x, y))
                            {
                                // Ok!
                                return(renderData);
                            }

                            // Advance to the next one:
                            box = box.NextInElement;
                        }
                    }
                    else
                    {
                        // Yep!
                        return(renderData);
                    }
                }

                ige = ige.Previous;
            }

            return(null);
        }
예제 #2
0
        /// <summary>Gets a grid entry for the given
        private InputGridEntry GetEntry()
        {
            InputGridEntry ige = PooledCell_;

            if (ige == null)
            {
                return(new InputGridEntry());
            }

            // Update pool:
            PooledCell_  = ige.Previous;
            ige.Previous = null;

            return(ige);
        }
예제 #3
0
        /// <summary>Empties the grid into the pool.</summary>
        public void Empty()
        {
            if (Grid == null)
            {
                return;
            }

            // For each grid cell..
            for (int i = 0; i < Grid.Length; i++)
            {
                InputGridCell cell = Grid[i];

                if (cell.Back != null)
                {
                    // Pool:
                    cell.Back.Previous = PooledCell_;
                    PooledCell_        = cell.Front;

                    // Clear:
                    cell.Back  = null;
                    cell.Front = null;
                }
            }
        }
예제 #4
0
        /// <summary>Pushes the given renderable data into the grid now.</summary>
        public void Push(RenderableData renderData)
        {
            // Node must be an element:
            if (renderData == null || !(renderData.Node is Dom.Element))
            {
                return;
            }

            // Get the region:
            ScreenRegion region = renderData.OnScreenRegion;

            if (region == null)
            {
                return;
            }

            // Get the bounds:
            int minX = (int)(region.ScreenMinX / CellSize);
            int minY = (int)(region.ScreenMinY / CellSize);

            if (minX >= Width || minY >= Height)
            {
                // ..It's offscreen?
                return;
            }

            if (minX < 0)
            {
                minX = 0;
            }

            if (minY < 0)
            {
                minY = 0;
            }

            // Max (inclusive):
            int maxX = (int)(region.ScreenMaxX / CellSize);
            int maxY = (int)(region.ScreenMaxY / CellSize);

            if (maxX < 0 || maxY < 0)
            {
                // ..It's offscreen?
                return;
            }

            if (maxX >= Width)
            {
                maxX = Width - 1;
            }

            if (maxY >= Height)
            {
                maxY = Height - 1;
            }

            // Generating a bunch of entries now!
            int cellIndex = minY * Width;

            // Only having one box means we don't need to do multiline testing.
            // It also means we can optimise "central" boxes too (see below about that).
            bool oneBox = (renderData.FirstBox != null && renderData.FirstBox.NextInElement == null);

            for (int y = minY; y <= maxY; y++)
            {
                // Central boxes are on *both* middle X and middle Y
                // The content in the cell already is being completely overlapped
                // so we can simply empty it out (and recycle the entries too).
                bool centralBox = (oneBox && y != minY && y != maxY);

                for (int x = minX; x <= maxX; x++)
                {
                    // Get the target cell:
                    InputGridCell cell = Grid[cellIndex + x];

                    if (centralBox && x != minX && x != maxX)
                    {
                        // Overwrite! Pool the cell:
                        if (cell.Back != null)
                        {
                            // Pool:
                            cell.Back.Previous = PooledCell_;
                            PooledCell_        = cell.Front;

                            // Clear:
                            cell.Back  = null;
                            cell.Front = null;
                        }
                    }

                    // Get an entry (typically from the pool):
                    InputGridEntry ige = GetEntry();

                    // Set it up:
                    ige.RenderData = renderData;

                    if (cell.Front == null)
                    {
                        cell.Back  = ige;
                        cell.Front = ige;
                    }
                    else
                    {
                        // Stack on the front:
                        ige.Previous = cell.Front;
                        cell.Front   = ige;
                    }
                }

                cellIndex += Width;
            }
        }