private VisualTextLine GetPartialLineBeforeCollapse(IEnumerable <CharInfo> charInfos, VisualTextLine line, int startIndex, int count)
        {
            var collapseInfo       = charInfos.First(info => !info.IsCharacter);
            var contents           = line.RenderedText;
            var textBeforeCollapse = string.Empty;

            if (collapseInfo.PrevCharPosition.Column >= startIndex)
            {
                textBeforeCollapse = contents.Substring(startIndex, collapseInfo.PrevCharPosition.Column);
            }
            else
            {
                textBeforeCollapse = contents.Substring(startIndex);
            }

            var diff = 0;

            if (startIndex + count >= collapseInfo.NextCharPosition.Column)
            {
                diff = (startIndex + count) - collapseInfo.NextCharPosition.Column;
            }

            var textAfterCollapse = string.Join("", contents.Skip(collapseInfo.NextCharPosition.Column).Take(diff));

            return(VisualTextLine.Create(textBeforeCollapse + textAfterCollapse, line.Index));
        }
Example #2
0
        public VisualTextLine CollapseTextRange(TextRange area, IReadOnlyList <string> lines, ICollapseRepresentation collapseRepresentationAlgorithm)
        {
            var precedingText      = new string(lines[area.StartPosition.Line].Take(area.StartPosition.Column).ToArray());
            var followingText      = new string(lines[area.EndPosition.Line].Skip(area.EndPosition.Column + 1).ToArray());
            var collapsedLineIndex = area.StartPosition.Line;
            var middlePart         = new List <string>();
            var start = area.StartPosition.Line;
            var end   = area.EndPosition.Line;

            if (start != end)
            {
                for (var i = start; i <= end; i++)
                {
                    var currentLine = lines[i];

                    if (i == start)
                    {
                        currentLine = string.Join("", currentLine.Skip(area.StartPosition.Column));
                    }
                    else if (i == end)
                    {
                        currentLine = string.Join("", currentLine.Take(area.EndPosition.Column + 1));
                    }

                    middlePart.Add(currentLine);
                }
            }
            else
            {
                middlePart.Add(string.Join("", lines[start].Skip(area.StartPosition.Column).Take((1 + area.EndPosition.Column) - area.StartPosition.Column)));
            }

            return(VisualTextLine.Create(middlePart, precedingText, followingText, collapsedLineIndex, collapseRepresentationAlgorithm.GetCollapseRepresentation()));
        }
        public ChangeInLinesInfo GetChangeInLines(IReadOnlyList <VisualTextLine> lines, TextRange range)
        {
            var orderedRanges = (new[] { range.StartPosition, range.EndPosition }).OrderBy(elem => elem.Line).ThenBy(elem => elem.Column).ToArray();
            var pair          = new TextRange {
                StartPosition = orderedRanges[0],
                EndPosition   = orderedRanges[1]
            };
            var rangeEnd = -1;

            if (pair.StartPosition.Line == pair.EndPosition.Line)
            {
                rangeEnd = pair.EndPosition.Line;
            }
            else
            {
                rangeEnd = pair.EndPosition.Line + 1;
            }

            var firstPart  = Cut(lines[pair.StartPosition.Line], 0, pair.StartPosition.Column);
            var secondPart = Cut(lines[pair.EndPosition.Line], pair.EndPosition.Column);

            return(new ChangeInLinesInfo {
                LinesToChange = new Dictionary <TextPosition, VisualTextLine> {
                    [new TextPosition(pair.StartPosition.Column, pair.StartPosition.Line)] =
                        VisualTextLine.MergeLines(new[] { firstPart, secondPart }, firstPart.Index)
                },
                LinesToRemove = Enumerable.Range(pair.StartPosition.Line, rangeEnd).ToList()
            });
        }
Example #4
0
        public void TwoNonEmptyLinesEnteredBackspacePressedAtTheBeginningOfSecond_LineShouldBeEqualToText1Text2()
        {
            const string text1 = "asdf";
            const string text2 = "zxcv";
            var          lines = new List <VisualTextLine> {
                VisualTextLine.Create(text1, 0),
                VisualTextLine.Create(text2, 1)
            };
            var newLines = algorithm.GetChangeInLines(lines, new TextPosition(column: 0, line: 1), Key.Back);

            Assert.AreEqual(text1 + text2, newLines.LinesToChange.First().Value.GetStringContents()[0]);
        }
Example #5
0
        public void TwoNonEmptyLinesEnteredDelPressedAtTheEndOfFirstOne_LineShouldBeEqualToText1Text2()
        {
            const string text1 = "asdf";
            const string text2 = "zxcv";
            var          lines = new List <VisualTextLine> {
                VisualTextLine.Create(text1, 0),
                VisualTextLine.Create(text2, 1)
            };
            var newLines = algorithm.GetChangeInLines(lines, new TextPosition(column: 4, line: 0), Key.Delete);

            Assert.AreEqual(text1 + text2, newLines.LinesToChange.First().Value.GetStringContents()[0]);
        }
 private void DrawLine(VisualTextLine line)
 {
     if (line.Index < visuals.Count)
     {
         visuals.Insert(line.Index, line);
         visuals.RemoveAt(line.Index + 1);
         line.Draw();
     }
     else
     {
         visuals.Add(line);
         line.Draw();
     }
 }
        private ChangeInLinesInfo DeleteFromActiveLine(IReadOnlyList <VisualTextLine> lines, TextPosition startingTextPosition)
        {
            var currentLine     = lines[startingTextPosition.Line];
            var firstPart       = Cut(currentLine, 0, startingTextPosition.Column);
            var secondPart      = Cut(currentLine, startingTextPosition.Column + 1);
            var lineAfterRemove = VisualTextLine.MergeLines(new[] { firstPart, secondPart }, currentLine.Index);

            return(new ChangeInLinesInfo {
                LinesToChange = new Dictionary <TextPosition, VisualTextLine> {
                    [new TextPosition(startingTextPosition.Column, startingTextPosition.Line)] = lineAfterRemove
                },
                LinesToRemove = new int[0]
            });
        }
Example #8
0
        public void CacheThreeSingleLines_ShouldCacheThreeLines()
        {
            collection.Add(VisualTextLine.Create("asdf", 0));
            collection.Add(VisualTextLine.Create("{", 1));
            collection.Add(VisualTextLine.Create("", 2));
            collection.Add(VisualTextLine.Create("}", 3));

            var cachedResult = collection.ConvertToCachedLines(3, 1);

            Assert.AreEqual(cachedResult.Count, 3);
            Assert.AreEqual(cachedResult[0].RenderedText, "{");
            Assert.AreEqual(cachedResult[1].RenderedText, "");
            Assert.AreEqual(cachedResult[2].RenderedText, "}");
        }
Example #9
0
        public void OneNonEmptyLineEnteredText2SelectedBackspacePressed_LineShouldBeText1Text3()
        {
            const string text1 = "some ";
            const string text2 = "text";
            const string text3 = " asdf";
            var          lines = new List <VisualTextLine> {
                VisualTextLine.Create(text1 + text2 + text3, 0)
            };
            var newLines = algorithm.GetChangeInLines(lines, new TextRange {
                StartPosition = new TextPosition(column: 5, line: 0),
                EndPosition   = new TextPosition(column: 9, line: 0)
            });

            Assert.AreEqual(text1 + text3, newLines.LinesToChange.First().Value.GetStringContents()[0]);
        }
        private ChangeInLinesInfo RemoveFromActiveLine(IReadOnlyList <VisualTextLine> lines, TextPosition startingTextPosition)
        {
            var currentLine     = lines[startingTextPosition.Line];
            var attachRest      = startingTextPosition.Column < lines[startingTextPosition.Line].Length;
            var firstPart       = Cut(currentLine, 0, startingTextPosition.Column - 1);
            var secondPart      = attachRest ? Cut(currentLine, startingTextPosition.Column) : null;
            var lineAfterRemove = secondPart != null?VisualTextLine.MergeLines(new[] { firstPart, secondPart }, currentLine.Index) : firstPart;

            return(new ChangeInLinesInfo {
                LinesToChange = new Dictionary <TextPosition, VisualTextLine> {
                    [new TextPosition(startingTextPosition.Column - 1, startingTextPosition.Line)] = lineAfterRemove
                },
                LinesToRemove = new int[0]
            });
        }
        private void RedrawCollapsedLine(VisualTextLine collapsedLine, int line)
        {
            if (line >= visuals.Count)
            {
                visuals.Add(null);
            }
            else
            {
                visuals[line] = null;
            }

            visuals[line] = collapsedLine;

            collapsedLine.Draw();
        }
Example #12
0
        public void FourCharactersEnteredSelectionForLastTwo_LineShouldBeText1()
        {
            const string text1 = "as";
            const string text2 = "df";
            var          lines = new List <VisualTextLine> {
                VisualTextLine.Create(text1 + text2, 0)
            };
            var newLines = algorithm.GetChangeInLines(lines, new TextRange {
                StartPosition = new TextPosition(column: 2, line: 0),
                EndPosition   = new TextPosition(column: 4, line: 0)
            });

            Assert.AreEqual(0, newLines.LinesToRemove.Count());
            Assert.AreEqual(text1, newLines.LinesToChange.ElementAt(0).Value.GetStringContents()[0]);
        }
Example #13
0
        public void ThreeLinesEnteredBackspacePressedOnTheSecondOne_LinesShouldBeText1Text3AndLinesToRemoveShouldBeLast()
        {
            const string text1 = "a";
            const string text2 = "";
            const string text3 = "b";
            var          lines = new List <VisualTextLine> {
                VisualTextLine.Create(text1, 0),
                VisualTextLine.Create(text2, 1),
                VisualTextLine.Create(text3, 2)
            };
            var newLines = algorithm.GetChangeInLines(lines, new TextPosition(column: 0, line: 1), Key.Back);

            Assert.IsTrue((new[] { 2 }).OrderBy(key => key).ToArray().SequenceEqual(newLines.LinesToRemove.ToArray()));
            Assert.AreEqual(text1, newLines.LinesToChange.First().Value.GetStringContents()[0]);
            Assert.AreEqual(text3, newLines.LinesToChange.Last().Value.GetStringContents()[0]);
        }
        private VisualTextLine CutStandardLine(VisualTextLine line, int startIndex, int count)
        {
            var contents = line.GetStringContents()[0];
            var newText  = string.Empty;

            if (startIndex + count == line.Length)
            {
                newText = contents.Substring(startIndex);
            }
            else
            {
                newText = contents.Substring(startIndex, count - startIndex);
            }

            return(VisualTextLine.Create(newText, line.Index));
        }
Example #15
0
        public void OneLineEnteredSelectionOfFourCharsDeletePressed_LineShouldBeText1Text3()
        {
            const string text1 = "asdf";
            const string text2 = "qwer";
            const string text3 = "zxcv";
            var          lines = new List <VisualTextLine> {
                VisualTextLine.Create(text1 + text2 + text3, 0)
            };
            var newLines = algorithm.GetChangeInLines(lines, new TextRange {
                StartPosition = new TextPosition(column: 4, line: 0),
                EndPosition   = new TextPosition(column: 8, line: 0)
            });
            var removedLinesIndexes = newLines.LinesToRemove.ToArray();

            Assert.AreEqual(0, removedLinesIndexes.Length);
            Assert.AreEqual(text1 + text3, newLines.LinesToChange.ElementAt(0).Value.GetStringContents()[0]);
        }
Example #16
0
        public void CacheCollapsedAndSingleLines_ShouldCacheThreeLines()
        {
            const string FirstLine = "asdf";
            const string Collapse  = "{...}";
            const string LastLine  = "zxcv";

            collection.Add(VisualTextLine.Create(FirstLine, 0));
            collection.Add(VisualTextLine.Create(new[] { "{", "", "}" }, "", "", 1, Collapse));
            collection.Add(VisualTextLine.Create(LastLine, 2));

            var cachedResult = collection.ConvertToCachedLines(3);

            Assert.AreEqual(cachedResult.Count, 3);
            Assert.AreEqual(cachedResult[0].RenderedText, FirstLine);
            Assert.AreEqual(cachedResult[1].RenderedText, Collapse);
            Assert.AreEqual(cachedResult[2].RenderedText, LastLine);
        }
Example #17
0
        public void ExpandText(FoldClickedMessage message)
        {
            var collapseIndex        = message.AreaBeforeFolding.StartPosition.Line;
            var collapsedLineContent = ((VisualTextLine)visuals[collapseIndex]).GetStringContents();
            var expandedLines        = collapsedLineContent.Select((line, index) => VisualTextLine.Create(line, collapseIndex + index)).ToArray();
            var linesToRedraw        = collapsingAlgorithm.GetLinesToRedrawAfterExpand(visuals.ToEnumerableOf <VisualTextLine>().Where(line => line.Index > message.AreaBeforeFolding.StartPosition.Line), expandedLines.Length - 1);

            visuals.RemoveRange(collapseIndex, LinesCount - collapseIndex);

            foreach (var line in expandedLines)
            {
                visuals.Insert(line.Index, line);
                line.Draw();
            }

            AddLines(linesToRedraw);
            UpdateSize();
        }
Example #18
0
        private int[] GetCollapseSelectionRange(TextPosition clickPosition, VisualTextLine activeLine, int lineLength)
        {
            var startColumn = clickPosition.Column;
            var endColumn   = clickPosition.Column;

            if (endColumn + 1 <= lineLength)
            {
                endColumn += 1;
            }
            else
            {
                startColumn -= 1;
            }
            // move left from current position
            for (var i = clickPosition.Column; i >= 0; i--)
            {
                var charInfo = activeLine.GetCharInfoAt(i);

                if (!charInfo.IsCharacter && !char.IsLetterOrDigit(charInfo.Text[0]))
                {
                    startColumn = i;
                }
                else
                {
                    break;
                }
            }
            // move right from current position
            for (var i = clickPosition.Column; i < lineLength; i++)
            {
                var charInfo = activeLine.GetCharInfoAt(i);

                if (!charInfo.IsCharacter && !char.IsLetterOrDigit(charInfo.Text[0]))
                {
                    endColumn = i + 1;
                }
                else
                {
                    break;
                }
            }

            return(new[] { startColumn, endColumn });
        }
Example #19
0
        public void ThreeNonEmptyLinesEnteredBackspacePressedAtCharOneBeforeTheLastOneInTheLastLine_LinesShouldBeText4()
        {
            const string text1 = "some text";
            const string text2 = "";
            const string text3 = "totally unimportant text";
            const string text4 = "text that stays";
            var          lines = new List <VisualTextLine> {
                VisualTextLine.Create(text1, 0),
                VisualTextLine.Create(text2, 1),
                VisualTextLine.Create(text3 + text4, 2)
            };
            var newLines = algorithm.GetChangeInLines(lines, new TextRange {
                StartPosition = new TextPosition(column: 0, line: 0),
                EndPosition   = new TextPosition(column: 24, line: 2)
            });

            Assert.AreEqual(text4, newLines.LinesToChange.First().Value.GetStringContents()[0]);
            Assert.IsTrue((new[] { 0, 1, 2 }).OrderBy(key => key).ToArray().SequenceEqual(newLines.LinesToRemove.OrderBy(key => key).ToArray()));
        }
        private ChangeInLinesInfo RemoveThisLine(IReadOnlyList <VisualTextLine> lines, TextPosition startingTextPosition)
        {
            var firstLine     = lines[startingTextPosition.Line - 1];
            var linesAffected = new List <KeyValuePair <TextPosition, VisualTextLine> > {
                new KeyValuePair <TextPosition, VisualTextLine>(
                    new TextPosition(lines[startingTextPosition.Line - 1].Length, startingTextPosition.Line - 1),
                    VisualTextLine.MergeLines(new[] { firstLine, lines[startingTextPosition.Line] }, firstLine.Index))
            };

            for (var i = startingTextPosition.Line + 1; i < lines.Count; i++)
            {
                linesAffected.Add(new KeyValuePair <TextPosition, VisualTextLine>(new TextPosition(0, i - 1), lines[i].CloneWithIndexChange(i - 1)));
            }

            return(new ChangeInLinesInfo {
                LinesToChange = linesAffected,
                LinesToRemove = new[] { lines.Count - 1 }
            });
        }
Example #21
0
        public void FourLinesEnteredDeletePressedAtTheEndOfFirst_LinesShouldBeText1Text2Text3()
        {
            const string text1 = "asdf";
            const string text2 = "zxcv";
            const string text3 = "qwer";
            var          lines = new List <VisualTextLine> {
                VisualTextLine.Create(text1, 0),
                VisualTextLine.Create(string.Empty, 1),
                VisualTextLine.Create(text2, 2),
                VisualTextLine.Create(text3, 3)
            };
            var newLines            = algorithm.GetChangeInLines(lines, new TextPosition(column: 4, line: 0), Key.Delete);
            var removedLinesIndexes = newLines.LinesToRemove.ToArray();

            Assert.AreEqual(text1, newLines.LinesToChange.First().Value.GetStringContents()[0]);
            Assert.AreEqual(text2, newLines.LinesToChange.ElementAt(1).Value.GetStringContents()[0]);
            Assert.AreEqual(text3, newLines.LinesToChange.ElementAt(2).Value.GetStringContents()[0]);
            Assert.AreEqual(1, removedLinesIndexes.Length);
            Assert.AreEqual(3, removedLinesIndexes[0]);
        }
Example #22
0
        public void TwoLinesEnteredSelectionInTheMiddleOfFirst_LinesShouldBeText1Text3Text4()
        {
            const string text1 = "as";
            const string text2 = " df ";
            const string text3 = "qwer";
            const string text4 = "zxcv";
            var          lines = new List <VisualTextLine> {
                VisualTextLine.Create(text1 + text2 + text3, 0),
                VisualTextLine.Create(text4, 1)
            };
            var newLines = algorithm.GetChangeInLines(lines, new TextRange {
                StartPosition = new TextPosition(column: 2, line: 0),
                EndPosition   = new TextPosition(column: 6, line: 0)
            });
            var removedLineIndexes = newLines.LinesToRemove.ToArray();

            Assert.AreEqual(0, removedLineIndexes.Length);
            Assert.AreEqual(1, newLines.LinesToChange.Count());
            Assert.AreEqual(text1 + text3, newLines.LinesToChange.ElementAt(0).Value.GetStringContents()[0]);
        }
        private ChangeInLinesInfo DeleteNextLine(IReadOnlyList <VisualTextLine> lines, TextPosition startingTextPosition)
        {
            var firstLine     = lines[startingTextPosition.Line];
            var secondLine    = startingTextPosition.Line + 1 < lines.Count ? lines[startingTextPosition.Line + 1] : null;
            var linesToMerge  = secondLine == null ? new[] { firstLine } : new[] { firstLine, secondLine };
            var linesAffected = new List <KeyValuePair <TextPosition, VisualTextLine> > {
                new KeyValuePair <TextPosition, VisualTextLine>(
                    new TextPosition(startingTextPosition.Column, startingTextPosition.Line),
                    VisualTextLine.MergeLines(linesToMerge, firstLine.Index))
            };

            for (var i = startingTextPosition.Line + 2; i < lines.Count; i++)
            {
                linesAffected.Add(new KeyValuePair <TextPosition, VisualTextLine>(new TextPosition(0, i - 1), lines[i].CloneWithIndexChange(i - 1)));
            }

            return(new ChangeInLinesInfo {
                LinesToChange = linesAffected,
                LinesToRemove = new[] { lines.Count - 1 }
            });
        }
        private VisualTextLine Cut(VisualTextLine line, int startIndex, int?count = null)
        {
            var substringLength = count == null ? line.Length - startIndex : count.Value;

            if (line is CollapsedVisualTextLine)
            {
                var charInfos = Enumerable.Range(startIndex, substringLength).Select(index => line.GetCharInfoAt(index));

                if (charInfos.Any(info => !info.IsCharacter))
                {
                    return(GetPartialLineBeforeCollapse(charInfos, line, startIndex, substringLength));
                }
                else
                {
                    return(GetPartialLineAfterCollapse(line, startIndex, substringLength));
                }
            }
            else
            {
                return(CutStandardLine(line, startIndex, substringLength));
            }
        }
Example #25
0
        public void FourLinesEnteredSelectionInbetweenDeletePressed_LinesShouldBeText1Text6()
        {
            const string text1 = "as";
            const string text2 = "df";
            const string text3 = "qwer";
            const string text4 = "zxcv";
            const string text5 = "fg";
            const string text6 = "hj";
            var          lines = new List <VisualTextLine> {
                VisualTextLine.Create(text1 + text2, 0),
                VisualTextLine.Create(text3, 1),
                VisualTextLine.Create(text4, 2),
                VisualTextLine.Create(text5 + text6, 3)
            };
            var newLines = algorithm.GetChangeInLines(lines, new TextRange {
                StartPosition = new TextPosition(column: 2, line: 0),
                EndPosition   = new TextPosition(column: 2, line: 3)
            });
            var removedLinesIndexes = newLines.LinesToRemove.ToArray();

            Assert.AreEqual(4, removedLinesIndexes.Length);
            Assert.AreEqual(1, newLines.LinesToChange.Count());
            Assert.AreEqual(text1 + text6, newLines.LinesToChange.ElementAt(0).Value.GetStringContents()[0]);
        }
Example #26
0
        private void InputText(string enteredText)
        {
            var newLines = updatingAlgorithm.GetChangeInLines(GetActualLines(), caretViewReader.CaretPosition, enteredText);

            DrawLines(newLines.Select(entry => VisualTextLine.Create(entry.Value, entry.Key)));
        }
Example #27
0
        public IEnumerable <VisualTextLine> GetLinesToRedrawAfterCollapse(IReadOnlyList <VisualTextLine> visuals, VisualTextLine collapsedLine, TextRange range)
        {
            var linesToRedraw = new List <VisualTextLine>();

            if (range.StartPosition.Line == range.EndPosition.Line)
            {
                return(linesToRedraw);
            }

            var collapseEndLine = range.EndPosition.Line;

            for (int i = collapseEndLine + 1, newIndex = collapsedLine.Index + 1; i < visuals.Count; i++, newIndex++)
            {
                var line = visuals[i].CloneWithIndexChange(newIndex);

                linesToRedraw.Add(line);
            }

            return(linesToRedraw);
        }
Example #28
0
 public IEnumerable <VisualTextLine> ExpandTextRange(TextRange area, IEnumerable <string> lines) =>
 lines.Skip(area.StartPosition.Line).Take(1 + area.EndPosition.Line - area.StartPosition.Line).Select((line, index) => VisualTextLine.Create(line, area.StartPosition.Line + index));
        private VisualTextLine GetPartialLineAfterCollapse(VisualTextLine line, int startIndex, int count)
        {
            var firstPart = line.RenderedText.Substring(startIndex, count);

            return(VisualTextLine.Create(firstPart, line.Index));
        }