Example #1
0
        private TControl FindRemovedWithData <TControl, TData> (ref DenseList <Control> list, string key, TData data)
            where TControl : Control
        {
            // Look for a match in the controls we have previously removed
            for (int i = 0, c = list.Count; i < c; i++)
            {
                var tctl = EvaluateMatch <TControl, TData>(list[i], key, data);
                if (tctl == null)
                {
                    continue;
                }

                list.RemoveAt(i);
                return(tctl);
            }
            return(null);
        }
Example #2
0
        internal ContainerBuilder(UIContext context, Control control)
        {
            if (control == null)
            {
                throw new ArgumentNullException("control");
            }
            if (!(control is IControlContainer))
            {
                throw new InvalidCastException("control must implement IControlContainer");
            }

            Context   = context;
            Control   = control;
            Container = (IControlContainer)control;
            NextIndex = Container?.ChildrenToSkipWhenBuilding ?? 0;
            Children  = Container.Children;
            PreviousRemovedControls    = new DenseList <Control>();
            CurrentRemovedControls     = new DenseList <Control>();
            ExtraLayoutFlags           = default(ControlFlags);
            OverrideLayoutFlags        = null;
            WaitingForFocusBeneficiary = null;
        }
Example #3
0
        public void ReplaceWith(ref DenseList <Control> newControls)
        {
            for (int i = 0; i < newControls.Count; i++)
            {
                var newControl = newControls[i];
                if (newControl == null)
                {
                    throw new ArgumentNullException($"newControls[{i}]");
                }
            }

            for (int i = 0; i < newControls.Count; i++)
            {
                var newControl = newControls[i];
                if (newControl == null)
                {
                    throw new ArgumentNullException($"newControls[{i}]");
                }
                var isNew = !IndexTable.TryGetValue(newControl, out int oldIndex);
                if (!isNew)
                {
                    if (oldIndex == i)
                    {
                        continue;
                    }

                    // HACK: Erase the slot that previously held this control
                    if (oldIndex >= 0)
                    {
                        Items[oldIndex] = null;
                    }
                }

                if (i < Count)
                {
                    var oldControl = Items[i];
                    // HACK: Flag this control as potentially dead
                    if (oldControl != null)
                    {
                        IndexTable[oldControl] = -1;
                    }

                    Items[i] = newControl;
                }
                else
                {
                    Items.Add(newControl);
                }

                IndexTable[newControl] = i;
                if (isNew)
                {
                    newControl.SetParent(WeakHost);
                }
            }

            // Find dead controls that we removed and never re-added
            foreach (var kvp in IndexTable)
            {
                if (kvp.Value <= -1)
                {
                    DeadControlScratchBuffer.Add(kvp.Key);
                }
            }

            while (Count > newControls.Count)
            {
                var i            = Count - 1;
                var extraControl = Items[i];

                // We may have moved this extra control, in which case we don't want to go through
                //  the remove path that fires events.
                if ((extraControl != null) && (IndexTable[extraControl] == i))
                {
                    DeadControlScratchBuffer.Add(extraControl);
                }

                // We moved it, so we just need to remove whatever's at this location
                Items.RemoveAt(i);
            }

#if DEBUG
            foreach (var item in Items)
            {
                if (item == null)
                {
                    throw new Exception("Bad state");
                }
            }
#endif

            // Fire the relevant notifications for the dead controls and purge them from the table
            foreach (var deadControl in DeadControlScratchBuffer)
            {
                IndexTable.Remove(deadControl);
                FireControlRemoveEvents(deadControl);
            }

#if DEBUG
            foreach (var kvp in IndexTable)
            {
                if (kvp.Value <= -1)
                {
                    throw new Exception("Bad state");
                }
            }
#endif

            Invalidate();
            DeadControlScratchBuffer.Clear();
        }
Example #4
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
            });
        }