public void StringsInSource() { ITsString tss = tsf.MakeString("abc def", wsEn); AssembledStyles styles = new AssembledStyles(); TssClientRun clientRun = new TssClientRun(tss, styles); var clientRuns = new List<IClientRun>(); clientRuns.Add(clientRun); TextSource ts = new TextSource(clientRuns); }
/// <summary> /// Return an otherwise equivalent Tss client run that has the specified Contents. /// Subclasses should override to return the appropriate subclass and copy any additional information. /// </summary> internal virtual TssClientRun CopyWithNewContents(ITsString newContents) { ITsString tss = newContents; int var; if (tss == null) { tss = TsStrFactoryClass.Create().EmptyString(Tss.get_Properties(0).GetIntPropValues((int)FwTextPropType.ktptWs, out var)); } var result = new TssClientRun(tss, Style); result.Hookup = Hookup; return(result); }
/// <summary> /// Given a function that fetches strings, a run which represents the initial value of that string /// already inserted into a particular paragraph box, and that we have identified the fetcher as /// a property with the specified name of the specified target object, but we have not been able to find /// a ''Name'Changed' event on the target object, this stub provides a possible place for a subclass to /// use an alternative strategy for hooking something up to notify the view of changes to the property. /// </summary> protected override void MakeHookupForString(Func<ITsString> fetcher, TssClientRun run, string name, object target, ParaBox para) { var cmObj = target as ICmObject; if (cmObj != null) { // Set up for PropChanged notification. RootFdo.DataAccess = cmObj.Cache.DomainDataByFlid; // ensures hooked up to receive PropChanged. Tuple<int, int> key = GetPropChangedKey(name, cmObj); var stringHookup = new TssHookup(target, fetcher, hookup => RootFdo.AddHookupToPropChanged(key, hookup), hookup => RootFdo.RemoveHookupFromPropChanged(key, hookup), para); stringHookup.Tag = key.Item2; AddHookupToRun(run, stringHookup); // Enhance JohnT: consider doing this by reflection. stringHookup.Writer = newVal => RootFdo.DataAccess.SetString(cmObj.Hvo, key.Item2, newVal); } }
public void TssRuns() { string part1 = "abc def"; ITsString tss = tsf.MakeString(part1, wsEn); AssembledStyles styles = new AssembledStyles(); TssClientRun clientRun = new TssClientRun(tss, styles); Assert.AreEqual(1, clientRun.UniformRunCount); Assert.AreEqual(part1, clientRun.UniformRunText(0)); AssembledStyles style1 = clientRun.UniformRunStyles(0); Assert.AreEqual(wsEn, style1.Ws); Assert.AreEqual(0, clientRun.UniformRunStart(0)); Assert.AreEqual(part1.Length, clientRun.UniformRunLength(0)); string part2 = " ghi"; ITsStrBldr bldr = tss.GetBldr(); bldr.Replace(part1.Length, part1.Length, part2, ttpFrn); TssClientRun clientRun2 = new TssClientRun(bldr.GetString(), styles); Assert.AreEqual(2, clientRun2.UniformRunCount); Assert.AreEqual(part1, clientRun2.UniformRunText(0)); Assert.AreEqual(part2, clientRun2.UniformRunText(1)); style1 = clientRun2.UniformRunStyles(0); Assert.AreEqual(wsEn, style1.Ws); AssembledStyles style2 = clientRun2.UniformRunStyles(1); Assert.AreEqual(wsFrn, style2.Ws); Assert.AreEqual(0, clientRun2.UniformRunStart(0)); Assert.AreEqual(part1.Length, clientRun2.UniformRunLength(0)); Assert.AreEqual(part1.Length, clientRun2.UniformRunStart(1)); Assert.AreEqual(part2.Length, clientRun2.UniformRunLength(1)); var source = new TextSource(new List<IClientRun>(new [] {clientRun2})); var runs = source.Runs; Assert.That(runs.Length, Is.EqualTo(2)); Assert.That(runs[0].LogLength, Is.EqualTo(part1.Length)); Assert.That(runs[1].LogLength, Is.EqualTo(part2.Length)); Assert.That(runs[1].LogStart, Is.EqualTo(part1.Length)); Assert.That(runs[1].Offset, Is.EqualTo(0)); // nothing fancy with ORCs, run starts at 0 in uniform run. }
public void StringChangedTests() { string part0 = "abc"; AssembledStyles styles = new AssembledStyles().WithWs(wsEn); StringClientRun clientRun0 = new StringClientRun(part0, styles); var clientRuns = new List<IClientRun>(); clientRuns.Add(clientRun0); TextSource source = new TextSource(clientRuns); List<IRenderRun> renderRuns = source.RenderRuns; VerifyRenderRun(renderRuns[0], 0, 3, "initial state has all in one run"); var clientRun1 = new StringClientRun("abcd", styles); var output1 = source.ClientRunChanged(0, clientRun1); Assert.AreEqual(1, output1.NewSource.RenderRuns.Count, "replacing single run with simple string should produce single render run."); VerifyRenderRun(output1.NewSource.RenderRuns[0], 0, 4, "replacing client run should make a new source with modified single run"); Assert.AreEqual(3, output1.StartChange); Assert.AreEqual(0, output1.DeleteCount); Assert.AreEqual(1, output1.InsertCount); // try changing the middle of three runs, from a simple one to a complex one. clientRuns = new List<IClientRun>(); clientRuns.Add(clientRun0); string part2 = "def"; var clientRun2 = new StringClientRun(part2, styles); clientRuns.Add(clientRun2); string part3 = " mnop"; var clientRun3 = new StringClientRun(part3, styles); clientRuns.Add(clientRun3); source = new TextSource(clientRuns, MockInterpretOrc); string part4 = "q\xfffc"; var clientRun4 = new StringClientRun(part4, styles); var output2 = source.ClientRunChanged(1, clientRun4); Assert.AreEqual(3, output2.NewSource.RenderRuns.Count, "three render runs because ORC interprets as french string."); VerifyRenderRun(output2.NewSource.RenderRuns[0], 0, part0.Length + 1, "first run up to ORC"); VerifyRenderRun(output2.NewSource.RenderRuns[1], part0.Length + 1, orcText.Length, "second run is French from ORC"); VerifyRenderRun(output2.NewSource.RenderRuns[2], part0.Length + 1 + orcText.Length, part3.Length, "third run is stuff after ORC"); VerifyFetch(output2.NewSource, 0, output2.NewSource.Length, part0 + "q" + orcText + part3); Assert.AreEqual(part0.Length, output2.StartChange); Assert.AreEqual(part2.Length, output2.DeleteCount); Assert.AreEqual(1 + orcText.Length, output2.InsertCount); // Now do a variation where some of the new run survives at each end. // To catch a tricky special case, we want to replace some regular text with an ORC // that expands to the same thing. var bldr = tsf.MakeString("de" + orcText, wsEn).GetBldr(); bldr.SetIntPropValues(2, 2 + orcText.Length, (int)FwTextPropType.ktptWs, (int) FwTextPropVar.ktpvDefault, wsFrn); var clientRunFakeOrc = new TssClientRun(bldr.GetString(), styles); clientRuns = new List<IClientRun>(); clientRuns.Add(clientRun0); clientRuns.Add(clientRunFakeOrc); clientRuns.Add(clientRun3); source = new TextSource(clientRuns, MockInterpretOrc); string partDeqOrc = "deq\xfffc"; var clientRun5 = new StringClientRun(partDeqOrc, styles); var output3 = source.ClientRunChanged(1, clientRun5); Assert.AreEqual(3, output3.NewSource.RenderRuns.Count, "three render runs because ORC interprets as french string."); VerifyRenderRun(output3.NewSource.RenderRuns[0], 0, part0.Length + 3, "first run up to ORC"); VerifyRenderRun(output3.NewSource.RenderRuns[1], part0.Length + 3, orcText.Length, "second run is French from ORC"); VerifyRenderRun(output3.NewSource.RenderRuns[2], part0.Length + 3 + orcText.Length, part3.Length, "third run is stuff after ORC"); VerifyFetch(output3.NewSource, 0, output3.NewSource.Length, part0 + "deq" + orcText + part3); // This should be interpreted as inserting the "q" after the "de" and before the orc text. Assert.AreEqual(part0.Length + 2, output3.StartChange); Assert.AreEqual(0, output3.DeleteCount); Assert.AreEqual(1, output3.InsertCount); // special case where nothing changes. clientRuns = new List<IClientRun>(); clientRuns.Add(clientRun0); clientRuns.Add(clientRun2); source = new TextSource(clientRuns, MockInterpretOrc); var output4 = source.ClientRunChanged(1, clientRun2); Assert.AreEqual(1, output4.NewSource.RenderRuns.Count, "two client runs collapse to one render"); VerifyRenderRun(output4.NewSource.RenderRuns[0], 0, part0.Length + part2.Length, "run has expected length"); VerifyFetch(output4.NewSource, 0, output4.NewSource.Length, part0 + part2); Assert.AreEqual(part0.Length, output4.StartChange); Assert.AreEqual(0, output4.DeleteCount); Assert.AreEqual(0, output4.InsertCount); }
public void RenderRuns() { string part0 = "abc def"; AssembledStyles styles = new AssembledStyles().WithWs(wsEn); StringClientRun clientRun0 = new StringClientRun(part0, styles); var clientRuns = new List<IClientRun>(); clientRuns.Add(clientRun0); string part0a = " frn"; StringClientRun clientRun0a = new StringClientRun(part0a, styles.WithWs(wsFrn)); clientRuns.Add(clientRun0a); // Run 1 string part1 = " ghijk"; // english string part2 = " lmno"; // french ITsString tss = tsf.MakeString(part1, wsEn); ITsStrBldr bldr = tss.GetBldr(); bldr.Replace(bldr.Length, bldr.Length, part2, ttpFrn); TssClientRun clientRun1 = new TssClientRun(bldr.GetString(), styles); clientRuns.Add(clientRun1); // Run 2a string part2a = " french insert"; string part2b = " insert"; // english ITsString tssInsert = tsf.MakeString(part2b, wsEn); bldr = tssInsert.GetBldr(); bldr.Replace(0, 0, part2a, ttpFrn); TssClientRun clientRun2b = new TssClientRun(bldr.GetString(), styles); clientRuns.Add(clientRun2b); // IRuntem 2 string part3 = " pq"; string part4 = "\xfffc"; StringClientRun clientRun2 = new StringClientRun(part3 + part4, styles); clientRuns.Add(clientRun2); // Run 3 string part5 = "more french"; string part6 = "\xfffc"; StringClientRun clientRun3 = new StringClientRun(part5 + part6, styles.WithWs(wsFrn)); clientRuns.Add(clientRun3); // Run 4 string part7 = "English"; StringClientRun clientRun4 = new StringClientRun(part7, styles.WithWs(wsFrn)); clientRuns.Add(clientRun4); BlockBox box = new BlockBox(styles.WithWs(wsFrn), Color.Red, 72000, 36000); TextSource source = new TextSource(clientRuns, (run, offset) => (run == clientRun2 ? new StringClientRun(orcText, run.UniformRunStyles(0).WithWs(wsFrn)) : (IClientRun)box)); List<IRenderRun> renderRuns = source.RenderRuns; VerifyRenderRun(renderRuns[0], 0, part0.Length, "first - en"); int len = part0.Length; VerifyRenderRun(renderRuns[1], len, part0a.Length, "0a - frn"); len += part0a.Length; VerifyRenderRun(renderRuns[2], len, part1.Length, "part1 - en"); len += part1.Length; VerifyRenderRun(renderRuns[3], len, part2.Length + part2a.Length, "part2 & 2a (french)"); len += part2.Length + part2a.Length; VerifyRenderRun(renderRuns[4], len, part2b.Length + part3.Length, "2b and 2 (Eng)"); len += part2b.Length + part3.Length; VerifyRenderRun(renderRuns[5], len, orcText.Length + part5.Length, "orc + other french"); len += orcText.Length + part5.Length; VerifyRenderRun(renderRuns[6], len, 1, "single box"); len += 1; VerifyRenderRun(renderRuns[7], len, part7.Length, "run with same props as preceding box"); Assert.AreEqual(8, renderRuns.Count); }
public void MultiUniformRuns() { // Run 0 string part0 = "abc def"; AssembledStyles styles = new AssembledStyles().WithWs(wsEn); StringClientRun clientRun0 = new StringClientRun(part0, styles); var clientRuns = new List<IClientRun>(); clientRuns.Add(clientRun0); // Run 1 string part1 = " ghijk"; string part2 = " lmno"; ITsString tss = tsf.MakeString(part2, wsEn); ITsStrBldr bldr = tss.GetBldr(); bldr.Replace(0, 0, part1, ttpFrn); TssClientRun clientRun1 = new TssClientRun(bldr.GetString(), styles); clientRuns.Add(clientRun1); // Run 2 string part3 = " pq"; string part4 = "\xfffc"; string part5 = "r"; StringClientRun clientRun2 = new StringClientRun(part3+part4+part5, styles); clientRuns.Add(clientRun2); TextSource source = new TextSource(clientRuns, MockInterpretOrc); MapRun[] runs = source.Runs; Assert.AreEqual(6, runs.Length); VerifyRun(0, clientRun0, 0, 0, part0, runs[0], "first run of complex source (abcdef)"); int len = part0.Length; VerifyRun(len, clientRun1, len, 0, part1, runs[1], "2nd run of complex source( ghijk)"); len += part1.Length; VerifyRun(len, clientRun1, len, 0, 1, part2, runs[2], "3rd run of complex source( lmno)"); len += part2.Length; VerifyRun(len, clientRun2, len, 0, part3, runs[3], "4th run of complex source (pq)"); len += part3.Length; int orcPos = len; VerifyRun(len, clientRun2, len, part3.Length, orcText, runs[4], "5th run of complex source (orc->xyz)"); int render = len + orcText.Length; len += 1; VerifyRun(len, clientRun2, render, part3.Length + part4.Length, part5, runs[5], "6th run of complex source(r)"); len += part5.Length; render += part5.Length; Assert.AreEqual(render, source.Length, "Length of complex source"); // LogToRen Assert.AreEqual(0, source.LogToRen(0)); Assert.AreEqual(1, source.LogToRen(1)); Assert.AreEqual(part1.Length - 1, source.LogToRen(part1.Length - 1)); Assert.AreEqual(part1.Length, source.LogToRen(part1.Length)); Assert.AreEqual(part1.Length + 1, source.LogToRen(part1.Length + 1)); Assert.AreEqual(orcPos - 1, source.LogToRen(orcPos - 1)); Assert.AreEqual(orcPos, source.LogToRen(orcPos)); int delta = orcText.Length - 1; Assert.AreEqual(orcPos + 1 + delta, source.LogToRen(orcPos + 1)); Assert.AreEqual(len + delta, source.LogToRen(len)); Assert.AreEqual(len - 1 + delta, source.LogToRen(len - 1)); //RenToLog Assert.AreEqual(0, source.RenToLog(0)); Assert.AreEqual(1, source.RenToLog(1)); Assert.AreEqual(part1.Length - 1, source.RenToLog(part1.Length - 1)); Assert.AreEqual(part1.Length, source.RenToLog(part1.Length)); Assert.AreEqual(part1.Length + 1, source.RenToLog(part1.Length + 1)); Assert.AreEqual(orcPos - 1, source.RenToLog(orcPos - 1)); Assert.AreEqual(orcPos, source.RenToLog(orcPos)); Assert.AreEqual(orcPos, source.RenToLog(orcPos + orcText.Length - 1)); Assert.AreEqual(orcPos + 1, source.RenToLog(orcPos + orcText.Length)); Assert.AreEqual(len, source.RenToLog(len + delta)); Assert.AreEqual(len - 1, source.RenToLog(len + delta - 1)); // Fetch VerifyFetch(source, 0, 0, ""); VerifyFetch(source, 0, 1, "a"); VerifyFetch(source, 0, part0.Length, part0); VerifyFetch(source, orcPos, orcPos + orcText.Length, orcText); VerifyFetch(source, part0.Length, part0.Length + part1.Length, part1); VerifyFetch(source, part0.Length + part1.Length - 2, part0.Length + part1.Length + 2, part1.Substring(part1.Length - 2) + part2.Substring(0, 2)); VerifyFetch(source, part0.Length, part0.Length + part1.Length + part2.Length + 1, part1 + part2 + part3.Substring(0, 1)); VerifyFetch(source, orcPos + orcText.Length - 1, orcPos + orcText.Length + 1, orcText.Substring(orcText.Length - 1) + part5); // GetCharProps. (This test is too restrictive. In several cases, a larger range could be returned. OTOH it is weak // in only verifying the writing system to check the properties returned.) VerifyCharProps(source, 0, wsEn, 0, part0.Length, "props at 0 in complex string"); VerifyCharProps(source, 2, wsEn, 0, part0.Length, "props in middle of first run in complex string"); VerifyCharProps(source, part0.Length - 1, wsEn, 0, part0.Length, "props of last char of first run in complex string"); VerifyCharProps(source, part0.Length, wsFrn, part0.Length, part0.Length + part1.Length, "props at start of second run in complex string"); VerifyCharProps(source, orcPos - 1, wsEn, orcPos - part3.Length, orcPos, "props of last char before ORC"); VerifyCharProps(source, orcPos, wsFrn, orcPos, orcPos + orcText.Length, "props of first char of ORC expansion"); VerifyCharProps(source, orcPos + 1, wsFrn, orcPos, orcPos + orcText.Length, "props of mid char of ORC expansion"); VerifyCharProps(source, orcPos + orcText.Length - 1, wsFrn, orcPos, orcPos + orcText.Length, "props of last char of ORC expansion"); VerifyCharProps(source, orcPos + orcText.Length, wsEn, orcPos + orcText.Length, orcPos + orcText.Length + part5.Length, "props of first char after ORC expansion"); }
/// <summary> /// Return an otherwise equivalent Tss client run that has the specified Contents. /// Subclasses should override to return the appropriate subclass and copy any additional information. /// </summary> internal virtual TssClientRun CopyWithNewContents(ITsString newContents) { ITsString tss = newContents; int var; if (tss == null) tss = TsStrFactoryClass.Create().EmptyString(Tss.get_Properties(0).GetIntPropValues((int)FwTextPropType.ktptWs, out var)); var result = new TssClientRun(tss, Style); result.Hookup = Hookup; return result; }