/// <summary> /// Occurs after log information indicates that a <see cref="ClientRun"/> has been finished. /// </summary> protected override void OnClientRunFinished() { var clientRun = ClientRuns.LastOrDefault(); if (clientRun == null) { return; } var slotRun = clientRun.SlotRuns.Count != 0 ? clientRun.SlotRuns[FoldingSlot] : null; var lastUnitRun = slotRun?.UnitRuns.LastOrDefault(); if (_logBuffer != null && _logBuffer.Count != 0) { if (lastUnitRun != null) { lastUnitRun.EndIndex = _logBuffer[_logBuffer.Count - 1].Index; foreach (var logLine in _logBuffer.Where(x => x.Index < lastUnitRun.StartIndex)) { clientRun.LogLines.Add(logLine); } foreach (var logLine in _logBuffer.Where(x => x.Index >= lastUnitRun.StartIndex && x.Index <= lastUnitRun.EndIndex)) { lastUnitRun.LogLines.Add(logLine); } } else { foreach (var logLine in _logBuffer) { clientRun.LogLines.Add(logLine); } } } _logBuffer = null; }
private void EnsureUnitRunExists(int lineIndex, int queueIndex) { var slotRun = EnsureSlotRunExists(lineIndex, FoldingSlot); var unitRun = new UnitRun(slotRun) { QueueIndex = queueIndex, StartIndex = lineIndex }; var previousUnitRun = slotRun.UnitRuns.FirstOrDefault(); if (previousUnitRun != null) { previousUnitRun.EndIndex = lineIndex - 1; previousUnitRun.IsComplete = true; var clientRun = ClientRuns.Peek(); foreach (var logLine in _logBuffer.Where(x => x.LineIndex < previousUnitRun.StartIndex)) { clientRun.LogLines.Add(logLine); } foreach (var logLine in _logBuffer.Where(x => x.LineIndex >= previousUnitRun.StartIndex && x.LineIndex <= previousUnitRun.EndIndex)) { previousUnitRun.LogLines.Add(logLine); } _logBuffer.RemoveAll(x => x.LineIndex <= previousUnitRun.EndIndex); } slotRun.UnitRuns.Push(unitRun); }
internal InsertionPoint SelectAtStart(ParaBox para) { if (ClientRuns.Count == 0) { return(null); } return(ClientRuns.First().SelectAtStart(para)); }
internal InsertionPoint SelectAtEnd(ParaBox para) { if (ClientRuns.Count == 0) { return(null); } return(ClientRuns.Last().SelectAtEnd(para)); }
private ClientRun EnsureClientRunExists(int lineIndex) { if (ClientRuns.Count == 0) { ClientRuns.Push(new ClientRun(this, lineIndex)); } return(ClientRuns.Peek()); }
private ClientRun EnsureClientRunExists(int lineIndex) { if (ClientRuns.Count == 0) { ClientRuns.Add(new ClientRun(this, lineIndex)); } return(ClientRuns.Last()); }
private ClientRun EnsureClientRunExists(int lineIndex, bool createNew) { if (createNew && ClientRuns.Count != 0) { OnClientRunFinished(); } if (createNew || ClientRuns.Count == 0) { ClientRuns.Add(new ClientRun(this, lineIndex)); } return(ClientRuns.Last()); }
private ClientRun EnsureClientRunExists(int lineIndex, bool createNew) { if (createNew && ClientRuns.Count != 0) { Finish(); } if (createNew || ClientRuns.Count == 0) { ClientRuns.Push(new ClientRun(this, lineIndex)); } return(ClientRuns.Peek()); }
/// <summary> /// Return the index of the client run containing the indicated character (the one at position ichRenTarget if associatePrevious /// is false, the previous one if it is true...except we always answer the last one if ichRen is after its start. /// Also return the character offset into the indicated clientrun. /// </summary> int ClientRunContainingRender(int ichRenTarget, bool associatePrevious, out int offset) { if (m_runs.Length == 0) { offset = 0; return(0); } int iMapRun = 0; while (iMapRun < m_runs.Length && m_runs[iMapRun].RenderLim < ichRenTarget) { iMapRun++; } // every earlier run ends strictly before ichRenTarget and cannot contain the target character if (iMapRun >= m_runs.Length) { // it's at or beyond the end of the paragraph var result = m_runs.Last().ClientRun; offset = result.Length; return(ClientRuns.Count - 1); } var mapRun = m_runs[iMapRun]; // since we didn't run out of runs, any previous run must end strictly before ichRenTarget. // However, it's possible, if ichRenTarget is equal to the limit of this run, that // the character we want is in the next run. if (iMapRun < m_runs.Length - 1 && ichRenTarget == mapRun.RenderLim && !associatePrevious) { iMapRun++; // it's at the start of the next run. mapRun = m_runs[iMapRun]; } var clientRun = mapRun.ClientRun; int clientRunIndex = ClientRuns.IndexOf(clientRun); int logicalStartOfClientRun = ClientRuns.Take(clientRunIndex).Sum(run => run.Length); if (mapRun.RenderLength == mapRun.LogLength) { // no complications: offset into the mapRun plus the offset of the mapRun into the client run. offset = ichRenTarget - mapRun.RenderStart + mapRun.LogStart - logicalStartOfClientRun; } else { // So far all other runs have a logical length of zero or one. // Review JohnT: I'm not sure what it is most useful to return for an expanded ORC...possibly change the API so // we can return a range? Return start or end of it, whichever we are closest to? // for now we'll let both these cases be handled as at the start of the run. offset = mapRun.Offset + mapRun.LogStart - logicalStartOfClientRun; } return(ClientRuns.IndexOf(clientRun)); }
protected override void Finish() { var clientRun = ClientRuns.FirstOrDefault(); if (clientRun == null) { return; } foreach (var unitRun in clientRun.SlotRuns.Values.SelectMany(x => x.UnitRuns)) { if (!unitRun.IsComplete) { unitRun.EndIndex = unitRun.LogLines[unitRun.LogLines.Count - 1].LineIndex; } } }
/// <summary> /// Occurs after log information indicates that a <see cref="ClientRun"/> has been finished. /// </summary> protected override void OnClientRunFinished() { var clientRun = ClientRuns.LastOrDefault(); if (clientRun == null) { return; } foreach (var unitRun in clientRun.SlotRuns.Values.SelectMany(x => x.UnitRuns).Cast <FahClientUnitRun>()) { if (!unitRun.IsComplete) { unitRun.EndIndex = unitRun.LogLines[unitRun.LogLines.Count - 1].Index; } } }
/// <summary> /// Remove some of your runs. This causes the MapRuns to be recalculated when needed, but does not redo layout /// or update display; the caller is responsible to relayout. /// </summary> internal void RemoveRuns(int first, int count) { ClientRuns.RemoveRange(first, count); AdjustClientRunIndexes(first); Runs = null; // ensure recalculated when needed. }
/// <summary> /// Insert another run. This causes the MapRuns to be recalculated when needed, but does not redo layout /// or update display; it is intended for use by the ViewBuilder during box construction. /// May also be used during later edits, but then the caller is responsible to relayout. /// </summary> internal void InsertRun(int index, IClientRun run) { ClientRuns.Insert(index, run); AdjustClientRunIndexes(index); // Enhance: want a test that shows this is needed. Runs = null; // ensure recalculated when needed. }