示例#1
0
        private void RasterizeAcceleratorOverlay(
            UIOperationContext context, ref ImperativeRenderer labelRenderer, ref ImperativeRenderer targetRenderer,
            Control control, AbstractString label, bool showFocused = false, Control forControl = null
            )
        {
            if (control == null)
            {
                return;
            }
            if (!showFocused && (control == Focused) && !label.IsNull && (label.Length > 0))
            {
                return;
            }
            if (label.Length <= 0)
            {
                return;
            }

            var box = control.GetRect();

            if ((box.Width <= 1) || (box.Height <= 1))
            {
                return;
            }

            var decorator = Decorations.AcceleratorTarget;
            var settings  = new Decorations.DecorationSettings {
                Box        = box,
                ContentBox = box
            };

            decorator.Rasterize(ref context, ref targetRenderer, settings);

            var outlinePadding = 1f;

            decorator = Decorations.AcceleratorLabel;
            Color?textColor = null;

            decorator.GetTextSettings(ref context, default(ControlStates), out Material material, ref textColor, out _);
            var layout    = decorator.GlyphSource.LayoutString(label, buffer: AcceleratorOverlayBuffer);
            var textScale = 1f;

            if (layout.Size.X > (box.Width - decorator.Padding.X))
            {
                textScale = Math.Max(0.25f, (box.Width - decorator.Padding.X) / layout.Size.X);
            }
            var scaledSize = layout.Size * textScale;

            var labelTraits = new DenseList <string> {
                "above"
            };
            var labelPosition = box.Position - new Vector2(0, scaledSize.Y + decorator.Padding.Y + outlinePadding);

            if (labelPosition.Y <= 0)
            {
                labelTraits[0] = "inside";
                labelPosition  = box.Position;
            }
            labelPosition.X = Arithmetic.Clamp(labelPosition.X, 0, CanvasSize.X - scaledSize.X);
            labelPosition.Y = Math.Max(0, labelPosition.Y);

            var labelBox = new RectF(
                labelPosition,
                scaledSize + decorator.Padding.Size
                );

            if (IsObstructedByAnyPreviousBox(ref labelBox, forControl))
            {
                labelBox.Left = box.Extent.X - labelBox.Width;
            }
            if (IsObstructedByAnyPreviousBox(ref labelBox, forControl))
            {
                labelTraits[0] = "below";
                labelBox.Left  = labelPosition.X;
                labelBox.Top   = box.Extent.Y + 1; // FIXME: Why the +1?
            }

            while (IsObstructedByAnyPreviousBox(ref labelBox, forControl))
            {
                labelTraits[0] = "stacked";
                labelBox.Left  = box.Left;
                labelBox.Width = box.Width;
                labelBox.Top   = labelBox.Extent.Y + 0.5f;
            }
            // HACK

            var labelContentBox = new RectF(
                labelBox.Position + new Vector2(decorator.Padding.Left, decorator.Padding.Top),
                scaledSize
                );

            settings = new Decorations.DecorationSettings {
                Box        = labelBox,
                ContentBox = box,
                Traits     = labelTraits
            };
            decorator.Rasterize(ref context, ref labelRenderer, settings);
            labelRenderer.DrawMultiple(layout.DrawCalls, offset: labelContentBox.Position.Floor(), scale: new Vector2(textScale), layer: 1);

            RasterizedOverlayBoxes.Add(new RasterizedOverlayBox {
                Control    = forControl,
                ControlBox = box,
                LabelBox   = labelBox
            });
        }