Ejemplo n.º 1
0
        void SetDecorations(swd.TextRange range, sw.TextDecorationCollection decorations, bool value)
        {
            using (Control.DeclareChangeBlock())
            {
                // set the property to each element in the range so it keeps all other decorations
                foreach (var element in range.GetElements().OfType <swd.Inline>().Distinct())
                {
                    var existingDecorations = element.GetValue(swd.Inline.TextDecorationsProperty) as sw.TextDecorationCollection;

                    // need to keep the range before changing otherwise the range changes
                    var elementRange = new swd.TextRange(element.ElementStart, element.ElementEnd);

                    sw.TextDecorationCollection newDecorations = null;

                    // remove decorations from the element
                    element.SetValue(swd.Inline.TextDecorationsProperty, null);

                    if (existingDecorations != null && existingDecorations.Count > 0)
                    {
                        // merge desired decorations with existing decorations.
                        if (value)
                        {
                            newDecorations = new sw.TextDecorationCollection(existingDecorations.Union(decorations));
                        }
                        else
                        {
                            newDecorations = new sw.TextDecorationCollection(existingDecorations.Except(decorations));
                        }

                        // split up existing decorations to the parts of the element that don't fall within the range
                        existingDecorations = new sw.TextDecorationCollection(existingDecorations);                         // copy so we don't update existing elements
                        if (elementRange.Start.CompareTo(range.Start) < 0)
                        {
                            new swd.TextRange(elementRange.Start, range.Start).ApplyPropertyValue(swd.Inline.TextDecorationsProperty, existingDecorations);
                        }
                        if (elementRange.End.CompareTo(range.End) > 0)
                        {
                            new swd.TextRange(range.End, elementRange.End).ApplyPropertyValue(swd.Inline.TextDecorationsProperty, existingDecorations);
                        }
                    }
                    else
                    {
                        // no existing decorations, just set the new value
                        newDecorations = value ? decorations : null;
                    }

                    if (newDecorations != null && newDecorations.Count > 0)
                    {
                        // apply new decorations to the desired range, which may be a combination of existing decorations
                        swd.TextPointer start = elementRange.Start.CompareTo(range.Start) < 0 ? range.Start : elementRange.Start;
                        swd.TextPointer end   = elementRange.End.CompareTo(range.End) > 0 ? range.End : elementRange.End;
                        new swd.TextRange(start, end).ApplyPropertyValue(swd.Inline.TextDecorationsProperty, newDecorations);
                    }
                }
            }
        }