コード例 #1
0
        public override void Invalidate(Rectangle rect)
        {
            if (!Control.IsLoaded)
            {
                if (Widget.Loaded)
                {
                    Application.Instance.AsyncInvoke(() => Invalidate(rect));
                }
                return;
            }
            if (tiled)
            {
                foreach (var tile in visibleTiles.Values)
                {
                    if (tile.Bounds.Intersects(rect))
                    {
                        tile.InvalidateVisual();
                    }
                }
            }
            else if (OptimizedInvalidateRect)
            {
                if (((rect.Width * rect.Height) / (Control.ActualWidth * Control.ActualHeight)) > 0.9)
                {
                    Invalidate();
                    return;
                }

                if (invalidateTiles == null)
                {
                    invalidateTiles = new List <EtoTile>();
                }

                var overlappingTiles = new List <EtoTile>();
                foreach (var overlappingTile in invalidateTiles)
                {
                    if (rect == overlappingTile.Bounds)
                    {
                        overlappingTile.InvalidateVisual();
                        return;
                    }
                    else if (rect.Intersects(overlappingTile.Bounds))
                    {
                        rect.Union(overlappingTile.Bounds);
                        overlappingTiles.Add(overlappingTile);
                    }
                }

                EtoTile tile;
                if (unusedTiles.Count > 0)
                {
                    tile            = unusedTiles[unusedTiles.Count - 1];
                    tile.Bounds     = rect;
                    tile.Visibility = sw.Visibility.Visible;
                    unusedTiles.Remove(tile);
                }
                else
                {
                    tile = new EtoTile
                    {
                        Handler             = this,
                        SnapsToDevicePixels = true
                    };
                    tile.Bounds = rect;
                    Control.Children.Add(tile);
                }
                invalidateTiles.Add(tile);

                foreach (var overlappingTile in overlappingTiles)
                {
                    overlappingTile.Visibility = sw.Visibility.Collapsed;
                    invalidateTiles.Remove(overlappingTile);
                    unusedTiles.Add(overlappingTile);
                }
            }
            else
            {
                base.Invalidate(rect);
            }
        }
コード例 #2
0
        void UpdateTiles(bool rebuildKeys = false)
        {
            if (!tiled || !Control.IsLoaded)
            {
                return;
            }

            var controlSize = new Size((int)Control.ActualWidth, (int)Control.ActualHeight);
            var rect        = new Rectangle(controlSize);
            var scroll      = scrollable;

            if (scroll != null)
            {
                // only show tiles in the visible rect of the scrollable
                var visibleRect       = new Rectangle(scroll.ClientSize);
                var scrollableHandler = (ScrollableHandler)scroll.Handler;
                visibleRect.Offset(-Control.TranslatePoint(new sw.Point(), scrollableHandler.ContentControl).ToEtoPoint());
                rect.Intersect(visibleRect);
            }

            // cache unused tiles and remove them from the visible tiles list
            var keys = visibleTiles.Keys.ToArray();

            for (int i = 0; i < keys.Length; i++)
            {
                var key  = keys[i];
                var tile = visibleTiles[keys[i]];
                if (!tile.Bounds.Intersects(rect))
                {
                    visibleTiles.Remove(key);
                    // keep tile, but make it invisible when needed later
                    tile.Visibility = sw.Visibility.Collapsed;
                    unusedTiles.Add(tile);
                }
            }

            // rebuild keys (e.g. when the size of the control changes)
            if (rebuildKeys)
            {
                RebuildKeys();
            }

            // calculate tile range that is visible
            var top    = rect.Top / tileSize.Height;
            var bottom = (rect.Bottom + tileSize.Height - 1) / tileSize.Height;
            var left   = rect.Left / tileSize.Width;
            var right  = (rect.Right + tileSize.Width - 1) / tileSize.Width;

            // make sure all needed tiles are created/visible
            for (var y = top; y < bottom; y++)
            {
                for (var x = left; x < right; x++)
                {
                    var position = new Point(x, y);
                    if (!maxTiles.Contains(position))
                    {
                        continue;
                    }
                    var key = position.Y * maxTiles.Width + position.X;

                    // calculate bounds of tile
                    var xpos  = x * tileSize.Width;
                    var ypos  = y * tileSize.Height;
                    var xsize = Math.Min(tileSize.Width, controlSize.Width - xpos);
                    var ysize = Math.Min(tileSize.Height, controlSize.Height - ypos);
                    if (xsize < 0 || ysize < 0)
                    {
                        continue;
                    }

                    var     bounds = new Rectangle(xpos, ypos, xsize, ysize);
                    EtoTile tile;

                    if (!visibleTiles.TryGetValue(key, out tile))
                    {
                        tile = unusedTiles.FirstOrDefault();
                        if (tile != null)
                        {
                            // use existing cached tile and make it visible again
                            unusedTiles.Remove(tile);
                            tile.Position   = position;
                            tile.Bounds     = bounds;
                            tile.Visibility = sw.Visibility.Visible;
                            tile.InvalidateVisual();
                        }
                        else
                        {
                            // need a new tile, no cached ones left
                            tile = new EtoTile
                            {
                                Handler             = this,
                                SnapsToDevicePixels = true,
                                Position            = position,
                                Bounds = bounds
                            };
                            Control.Children.Add(tile);
                        }
                        // set tile as visible
                        visibleTiles[key] = tile;
                    }
                    else
                    {
                        tile.Bounds = bounds;
                        tile.InvalidateVisual();
                    }
                }
            }
        }