public void Relayout() { var styles = new AssembledStyles(); var box = new MockBox(styles); var fixMap = new Dictionary<Box, Rectangle>(); var layoutInfo = ParaBuilderTests.MakeLayoutInfo(100, m_gm.VwGraphics); var site = new MockSite(); var root = new RootBox(styles); root.Site = site; using (var lcb = new LayoutCallbacks(root)) { Assert.IsFalse(box.Relayout(layoutInfo, fixMap, lcb), "Relayout of box never laid out should return false (can't have old loc)"); } Assert.AreEqual(layoutInfo, box.LastLayoutTransform, "Relayout of box never laid out should call Layout() with same transform"); Assert.AreEqual(0, site.RectsInvalidated.Count, "Relayout of box never laid out should not invalidate anything"); box.LastLayoutTransform = null; using (var lcb = new LayoutCallbacks(root)) Assert.IsFalse(box.Relayout(layoutInfo, fixMap, lcb), "Relayout of box not in map should return false"); Assert.IsNull(box.LastLayoutTransform, "Relayout of box not in map should not call Layout()"); Assert.AreEqual(0, site.RectsInvalidated.Count, "Relayout of box not in map should not invalidate anything"); fixMap[box] = new Rectangle(2,3,4,7); using (var lcb = new LayoutCallbacks(root)) Assert.IsTrue(box.Relayout(layoutInfo, fixMap, lcb), "Relayout of box in map should return true"); Assert.AreEqual(layoutInfo, box.LastLayoutTransform, "Relayout of box in map should call Layout() with same transform"); Assert.AreEqual(1, site.RectsInvalidatedInRoot.Count, "Relayout of box in map should invalidate rect from map"); Assert.AreEqual(new Rectangle(2, 3, 4, 7), site.RectsInvalidatedInRoot[0], "Relayout of box in map should invalidate proper rect"); }
public void Relayout() { var styles = new AssembledStyles(); var box = new MockBox(styles); var fixMap = new Dictionary <Box, Rectangle>(); var layoutInfo = ParaBuilderTests.MakeLayoutInfo(100, m_gm.VwGraphics); var site = new MockSite(); var root = new RootBox(styles); root.Site = site; using (var lcb = new LayoutCallbacks(root)) { Assert.IsFalse(box.Relayout(layoutInfo, fixMap, lcb), "Relayout of box never laid out should return false (can't have old loc)"); } Assert.AreEqual(layoutInfo, box.LastLayoutTransform, "Relayout of box never laid out should call Layout() with same transform"); Assert.AreEqual(0, site.RectsInvalidated.Count, "Relayout of box never laid out should not invalidate anything"); box.LastLayoutTransform = null; using (var lcb = new LayoutCallbacks(root)) Assert.IsFalse(box.Relayout(layoutInfo, fixMap, lcb), "Relayout of box not in map should return false"); Assert.IsNull(box.LastLayoutTransform, "Relayout of box not in map should not call Layout()"); Assert.AreEqual(0, site.RectsInvalidated.Count, "Relayout of box not in map should not invalidate anything"); fixMap[box] = new Rectangle(2, 3, 4, 7); using (var lcb = new LayoutCallbacks(root)) Assert.IsTrue(box.Relayout(layoutInfo, fixMap, lcb), "Relayout of box in map should return true"); Assert.AreEqual(layoutInfo, box.LastLayoutTransform, "Relayout of box in map should call Layout() with same transform"); Assert.AreEqual(1, site.RectsInvalidatedInRoot.Count, "Relayout of box in map should invalidate rect from map"); Assert.AreEqual(new Rectangle(2, 3, 4, 7), site.RectsInvalidatedInRoot[0], "Relayout of box in map should invalidate proper rect"); }
private void _Traverse(RootBox rb) { EWPF.Fixup(rb.Index, _traverseType); EWPF.Fixup(rb.Radicand, _traverseType); Leaf(); }
protected override void EnsureDefaultSelection() { if (RootBox != null) { RootBox.MakeSimpleSel(true, true, true, true); } }
protected void MakeTextSelectionAndScrollToView(int ichMin, int ichLim, int ws, int ihvoPara, int ihvoEnd) { SelLevInfo[] rgsli = new SelLevInfo[1]; // entry 0 says which StTextPara rgsli[0].ihvo = ihvoPara; rgsli[0].tag = (int)StText.StTextTags.kflidParagraphs; // entry 1 says to use the Contents of the Text. //rgsli[1].tag = (int)FDO.Ling.Text.TextTags.kflidContents; try { RootBox.MakeTextSelection(0, rgsli.Length, rgsli, (int)StTxtPara.StTxtParaTags.kflidContents, 0, ichMin, ichLim, ws, false, // Range, arbitrary assoc prev. ihvoEnd, null, // don't set any special text props for typing true); // install it Focus(); // Scroll this selection into View. IVwSelection sel = this.RootBox.Selection; this.ScrollSelectionIntoView(sel, VwScrollSelOpts.kssoDefault); Update(); } catch (Exception) { } }
public void DrawIP() { ParaBox para; RootBox root = ParaBuilderTests.MakeTestParaSimpleString(m_gm.VwGraphics, ParaBuilderTests.MockBreakOption.ThreeFullLines, out para); InsertionPoint ip = root.SelectAtEnd(); ip.Install(); Assert.AreEqual(ip, root.Selection); Assert.AreEqual(para, ip.Para, "IP should know about the paragraph it is in"); Assert.AreEqual(para.Source.Length, ip.StringPosition, "the IP should be at the end of the paragraph"); Assert.AreEqual(true, ip.AssociatePrevious, "selection at end should always associate previous in non-empty para"); StringBox third = para.FirstBox.Next.Next as StringBox; Assert.IsNotNull(third, "para with three simple lines should have three string boxes"); MockSegment seg3 = third.Segment as MockSegment; Assert.IsNotNull(seg3); PaintTransform ptrans = new PaintTransform(2, 4, 96, 100, 0, -10, 120, 128); ip.Draw(m_gm.VwGraphics, ptrans); StringBox first = para.FirstBox as StringBox; StringBox second = para.FirstBox.Next as StringBox; // All three segments should be invited to draw it, though only one will. var seg1 = first.Segment as MockSegment; VerifySegmentDrawing(para, first, seg1, -4); var seg2 = second.Segment as MockSegment; VerifySegmentDrawing(para, second, seg2, -14); VerifySegmentDrawing(para, third, seg3, -24); seg1.NextPosIpResult = new MockSegment.PositionsOfIpResults(); seg1.NextPosIpResult.PrimaryHere = false; seg2.NextPosIpResult = new MockSegment.PositionsOfIpResults(); seg2.NextPosIpResult.PrimaryHere = false; seg3.NextPosIpResult = new MockSegment.PositionsOfIpResults(); seg3.NextPosIpResult.RectPrimary = new Rect(5, 6, 7, 9); seg3.NextPosIpResult.PrimaryHere = true; Rectangle selRect = ip.GetSelectionLocation(m_gm.VwGraphics, ptrans); // All three should be asked for the position, though only the third returns a useful one. VerifySelLocation(para, first, seg1, -4); VerifySelLocation(para, second, seg2, -14); VerifySelLocation(para, third, seg3, -24); Assert.AreEqual(new Rectangle(5, 6, 2, 3), selRect); // The final thing that goes into drawing IPs is the Invalidate call. MockSite site = new MockSite(); site.m_transform = ptrans; site.m_vwGraphics = m_gm.VwGraphics; root.Site = site; ip.Invalidate(); Assert.IsNotNull(site.GraphicsHolder, "Invalidate should have created a Graphics holder"); Assert.IsTrue(site.GraphicsHolder.WasDisposed, "invalidate should have disposed of the Graphics Holder"); Assert.AreEqual(1, site.RectsInvalidated.Count, "invalidate should have invalidated one rectangle"); Assert.AreEqual(new Rectangle(5, 6, 2, 3), site.RectsInvalidated[0], "invalidate should have invalidated the selection rectangle"); }
public void MoveLeft() { ParaBox para; RootBox root = ParaBuilderTests.MakeTestParaSimpleString(m_gm.VwGraphics, ParaBuilderTests.MockBreakOption.ThreeFullLines, out para); InsertionPoint ip = root.SelectAtEnd(); // Todo: try moving left. Eventualy cover various options, such as from start of paragraph, over diacritics, etc. }
protected void SelectUpTo(int end1) { if (HvoRoot == 0) { return; } int end = Math.Min(end1, m_cache.GetVectorSize(HvoRoot, AnnotationListId) - 1); if (end < 0) { return; } if (EndSelLimitIndex > -1 && EndSelLimitIndex < end) { end = EndSelLimitIndex; } try { m_InSelectionChanged = true; SelLevInfo[] levelsA = new SelLevInfo[1]; levelsA[0].ihvo = 0; levelsA[0].tag = AnnotationListId; SelLevInfo[] levelsE = new SelLevInfo[1]; levelsE[0].ihvo = end; levelsE[0].tag = AnnotationListId; RootBox.MakeTextSelInObj(0, 1, levelsA, 1, levelsE, false, false, false, true, true); } finally { m_InSelectionChanged = false; } }
private void InitSandbox() { SetSandboxSize(); m_vc.LeftPadding = 0; m_rootb.Reconstruct(); using (new HoldGraphics(this)) { Rectangle rcSrcRoot; Rectangle rcDstRoot; GetCoordRects(out rcSrcRoot, out rcDstRoot); var rgvsli = new SelLevInfo[1]; //rgvsli[1].ihvo = 0; // first morpheme bundle //rgvsli[1].tag = (int)WfiAnalysis.WfiAnalysisTags.kflidMorphBundles; rgvsli[0].ihvo = 0; rgvsli[0].tag = m_fdoCache.MetaDataCacheAccessor.GetFieldId2(CmObjectTags.kClassId, "Self", false); var sel = RootBox.MakeTextSelInObj(0, rgvsli.Length, rgvsli, 0, null, true, false, false, false, false); if (sel == null) { Debug.WriteLine("Could not make selection in InitSandbox"); return; // can't position it accurately. } Rect rcSec; bool fSplit, fEndBeforeAnchor; sel.Location(m_graphicsManager.VwGraphics, rcSrcRoot, rcDstRoot, out m_rcPrimary, out rcSec, out fSplit, out fEndBeforeAnchor); } SetPadding(); SetSandboxLocation(); }
/// <summary> /// Move to the last bundle /// </summary> /// <param name="arg"></param> /// <returns></returns> public bool OnLastBundle(object arg) { var levels = new SelLevInfo[3]; levels[2].tag = StTextTags.kflidParagraphs; levels[2].ihvo = RootStText.ParagraphsOS.Count - 1; var lastPara = (IStTxtPara)RootStText.ParagraphsOS.Last(); levels[1].tag = StTxtParaTags.kflidSegments; levels[1].ihvo = lastPara.SegmentsOS.Count - 1; ISegment lastSegment = lastPara.SegmentsOS.Last(); int i; for (i = lastSegment.AnalysesRS.Count - 1; i >= 0; i--) { if (!(lastSegment.AnalysesRS[i] is IPunctuationForm)) { break; } } levels[0].tag = SegmentTags.kflidAnalyses; levels[0].ihvo = i; RootBox.MakeTextSelInObj(0, levels.Length, levels, 0, null, false, false, false, true, true); return(true); }
public void InsertCharInEmptyLine() { string contents = ""; var engine = new FakeRenderEngine() { Ws = 34, SegmentHeight = 13 }; var factory = new FakeRendererFactory(); factory.SetRenderer(34, engine); var styles = new AssembledStyles().WithWs(34); var clientRuns = new List <IClientRun>(); var run = new StringClientRun(contents, styles); clientRuns.Add(run); var data1 = new MockData1(34, 35); data1.SimpleThree = contents; var source = new TextSource(clientRuns, null); var para = new ParaBox(styles, source); var hookup = new StringHookup(this, () => data1.SimpleThree, hook => data1.SimpleThreeChanged += hook.StringPropChanged, hook => data1.SimpleThreeChanged -= hook.StringPropChanged, para); hookup.Writer = newVal => data1.SimpleThree = newVal; run.Hookup = hookup; var root = new RootBox(styles); var block = new BlockBox(styles, Color.Red, 20000, 10000); root.AddBox(block); root.AddBox(para); var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory); root.Layout(layoutArgs); Assert.That(root.Height, Is.EqualTo(13 + block.Height)); Assert.That(para.Width, Is.EqualTo(FakeRenderEngine.SimulatedWidth(contents))); Assert.That(root.Width, Is.EqualTo(block.Width)); int simulatedWidth = FakeRenderEngine.SimulatedWidth("x"); Assert.That(root.Width, Is.GreaterThan(para.Width + simulatedWidth)); PaintTransform ptrans = new PaintTransform(2, 4, 96, 100, 0, 10, 120, 128); MockSite site = new MockSite(); site.m_transform = ptrans; site.m_vwGraphics = m_gm.VwGraphics; root.Site = site; var oldRootWidth = root.Width; var ip = root.SelectAtEnd(); ip.InsertText("x"); Assert.That(root.Height, Is.EqualTo(13 + block.Height)); Assert.That(root.Width, Is.EqualTo(oldRootWidth)); Assert.That(para.Width, Is.EqualTo(simulatedWidth)); var expectedInvalidate = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin + block.Height, simulatedWidth + RootBox.InvalidateMargin * 2, 13 + 2 * RootBox.InvalidateMargin); Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate)); }
public void PaintParaBox() { AssembledStyles styles = new AssembledStyles(); var clientRuns = new List<IClientRun>(); BlockBox box0 = new BlockBox(styles, Color.Red, 72000, 36000); clientRuns.Add(box0); BlockBox box1 = new BlockBox(styles, Color.Blue, 36000, 18000); clientRuns.Add(box1); BlockBox box2 = new BlockBox(styles, Color.Red, 24000, 18000); clientRuns.Add(box2); BlockBox box3 = new BlockBox(styles, Color.Red, 72000, 36000); clientRuns.Add(box3); BlockBox box4 = new BlockBox(styles, Color.Red, 36000, 36000); clientRuns.Add(box4); TextSource source = new TextSource(clientRuns, null); ParaBox para = new ParaBox(styles, source); RootBox root = new RootBox(styles); root.AddBox(para); MockGraphics graphics = new MockGraphics(); LayoutInfo layoutArgs = ParaBuilderTests.MakeLayoutInfo(100, graphics); root.Layout(layoutArgs); PaintTransform ptrans = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96); root.Paint(graphics, ptrans); Assert.AreEqual(5, graphics.RectanglesDrawn.Count); VerifyRect(2, 2, 96, 48, graphics, 0, Color.Red); VerifyRect(2, 48+2, 48, 24, graphics, 1, Color.Blue); VerifyRect(2+48, 48 + 2, 32, 24, graphics, 2, Color.Red); VerifyRect(2, 24 + 48 + 2, 96, 48, graphics, 3, Color.Red); VerifyRect(2, 48 + 24 + 48 + 2, 48, 48, graphics, 4, Color.Red); }
/// <summary> /// Make a selection in the specified writing system at the specified character offset. /// </summary> public void SelectAt(int ws, int ich) { CheckDisposed(); var cpropPrevious = 0; if (ws != m_rgws[0].Handle) { // According to the documentation on RootBox.MakeTextSelection, cpropPrevious // needs to be the index into the ws array that matches the ws to be selected. cpropPrevious = GetRightPositionInWsArray(ws); if (cpropPrevious < 0) { Debug.Fail("InnerLabeledMultiStringView could not select correct ws"); cpropPrevious = 0; // safety net to keep from crashing outright. } } try { RootBox.MakeTextSelection(0, 0, null, m_flid, cpropPrevious, ich, ich, ws, true, -1, null, true); } catch (Exception) { Debug.Assert(false, "Unexpected failure to make selection in LabeledMultiStringView"); } }
Point TopLeftOfSecondStringBox(RootBox root) { ParaBox pb = root.FirstBox as ParaBox; StringBox second = pb.FirstBox.Next as StringBox; return(second.TopLeft); }
private void SelectRange(int begin1, int end1) { if (HvoRoot == 0) { return; } int end = Math.Min(end1, Decorator.get_VecSize(HvoRoot, OccurenceListId) - 1); int begin = Math.Min(begin1, end); if (end < 0 || begin < 0) { return; } try { m_InSelectionChanged = true; SelLevInfo[] levelsA = new SelLevInfo[1]; levelsA[0].ihvo = begin; levelsA[0].tag = OccurenceListId; SelLevInfo[] levelsE = new SelLevInfo[1]; levelsE[0].ihvo = end; levelsE[0].tag = OccurenceListId; RootBox.MakeTextSelInObj(0, 1, levelsA, 1, levelsE, false, false, false, true, true); } finally { m_InSelectionChanged = false; } }
private void CheckMultipleRuns(RootBox root) { Assert.That(root.FirstBox, Is.TypeOf(typeof(ParaBox))); Assert.That(root.FirstBox, Is.EqualTo(root.LastBox), "one box with two literals"); var para = (ParaBox)root.FirstBox; Assert.That(para.Source.ClientRuns, Has.Count.EqualTo(2)); var run1 = (StringClientRun)para.Source.ClientRuns[0]; Assert.That(run1.Style.FontWeight, Is.EqualTo((int)VwFontWeight.kvfwBold)); Assert.That(run1.Style.FontItalic, Is.True); Assert.That(run1.Style.ForeColor.ToArgb(), Is.EqualTo(Color.Red.ToArgb())); if (run1.Hookup != null) { Assert.That(run1.Hookup.ClientRunIndex, Is.EqualTo(0)); } var run2 = (StringClientRun)para.Source.ClientRuns[1]; Assert.That(run2.Style.BackColor.ToArgb(), Is.EqualTo(Color.Yellow.ToArgb())); Assert.That(run2.Style.ForeColor.ToArgb(), Is.EqualTo(Color.Blue.ToArgb())); if (run2.Hookup != null) { Assert.That(run2.Hookup.ClientRunIndex, Is.EqualTo(1)); } // Make sure everything didn't get applied to both runs Assert.That(run1.Style.BackColor.ToArgb(), Is.Not.EqualTo(Color.Blue.ToArgb())); Assert.That(run2.Style.FontItalic, Is.False); }
public void TestClick() { ParaBox para; RootBox root = ParaBuilderTests.MakeTestParaSimpleString(m_gm.VwGraphics, ParaBuilderTests.MockBreakOption.ThreeFullLines, out para); PaintTransform ptrans = new PaintTransform(2, 4, 96, 100, 0, 0, 120, 128); var seg = FirstMockSegment(root); seg.OnPointToCharReturn(4, false); var sel = root.GetSelectionAt(new Point(5, 10), m_gm.VwGraphics, ptrans); Assert.That(sel.IsInsertionPoint); Assert.That(((InsertionPoint)sel).StringPosition, Is.EqualTo(4)); Assert.That(((InsertionPoint)sel).AssociatePrevious, Is.False); Assert.That(seg.PointToCharVg, Is.EqualTo(m_gm.VwGraphics)); Assert.That(seg.PointToCharIchBase, Is.EqualTo(0)); // not much of a test, but we don't have any way to offset paras yet Assert.That(seg.PointToCharRcDst, Is.EqualTo(ptrans.DestRect)); Assert.That(seg.PointToCharRcSrc, Is.EqualTo(ptrans.SourceRect)); // Should be offset by the Paint transform origin. Assert.That(seg.PointToCharClickPosition, Is.EqualTo(new Point(5, 10))); seg = SecondMockSegment(root); seg.OnPointToCharReturn(14, true); sel = root.GetSelectionAt(new Point(7, 20), m_gm.VwGraphics, ptrans); Assert.That(sel.IsInsertionPoint); Assert.That(((InsertionPoint)sel).StringPosition, Is.EqualTo(14)); Assert.That(((InsertionPoint)sel).AssociatePrevious, Is.True); Assert.That(seg.PointToCharVg, Is.EqualTo(m_gm.VwGraphics)); Assert.That(seg.PointToCharIchBase, Is.EqualTo(IchMinOfSecondStringBox(root))); // Should be offset by the Paint transform origin and the origin of the second box. var topLeft = TopLeftOfSecondStringBox(root); Assert.That(seg.PointToCharClickPosition, Is.EqualTo(new Point(7, 20))); }
protected void SelectUpTo(int end1) { if (HvoRoot == 0 || RootBox == null) { return; } //Debug.Assert(RootBox != null, "Why is the chart ribbon's RootBox null?"); var end = Math.Min(end1, Decorator.get_VecSize(HvoRoot, OccurenceListId) - 1); if (end < 0) { return; } if (EndSelLimitIndex > -1 && EndSelLimitIndex < end) { end = EndSelLimitIndex; } try { m_InSelectionChanged = true; var levelsA = new SelLevInfo[1]; levelsA[0].ihvo = 0; levelsA[0].tag = OccurenceListId; var levelsE = new SelLevInfo[1]; levelsE[0].ihvo = end; levelsE[0].tag = OccurenceListId; RootBox.MakeTextSelInObj(0, 1, levelsA, 1, levelsE, false, false, false, true, true); } finally { m_InSelectionChanged = false; } }
private void InitLongText() { AssembledStyles styles = new AssembledStyles(); RootBox root = new RootBox(styles); var owner = new ParagraphOwnerDemo(); var words = "This is a bit of text from which we can extract substrings of increasing length to populate various paragraphs in different ways".Split(' '); var sb = new StringBuilder(); for (int i = 0; i < 20; i++) { var para = new ParagraphDemo(); if (i < words.Length) { sb.Append(words[i]); } para.Contents = sb.ToString(); if (i < words.Length) { sb.Append(" "); } owner.InsertParagraph(0, para); } int ws = 1; // arbitrary with default renderer factory. root.Builder.Show(Display.Of(() => owner.Paragraphs).Using( (builder, para) => builder.AddString(() => para.Contents, ws)) .EditParagraphsUsing(new ParagraphOpsDemo(owner))); theSharpView.Root = root; root.SelectAtEnd().Install(); theSharpView.Focus(); }
/// <summary> /// Clear all text. If fReconstruct is true, also clears the display. /// </summary> public void Clear(bool fReconstruct) { CheckDisposed(); if (m_sda == null) { var cda = VwCacheDaClass.Create(); cda.TsStrFactory = TsStringUtils.TsStrFactory; m_sda = cda; if (WritingSystemFactory != null) { m_sda.WritingSystemFactory = WritingSystemFactory; } m_cd = cda; } else { m_hvoNextPara = khvoFirstPara; m_cd.CacheVecProp(m_hvoRoot, (int)SampleTags.ktagTextParas, new int[0], 0); if (fReconstruct) { RootBox.Reconstruct(); } } }
public void PileOfBlocksLayout() { var styles = new AssembledStyles(); BlockBox box1 = new BlockBox(styles, Color.Red, 72000, 36000); BlockBox box2 = new BlockBox(styles, Color.Blue, 108000, 18000); BlockBox box3 = new BlockBox(styles, Color.Orange, 72000, 18000); RootBox root = new RootBox(styles); root.AddBox(box1); root.AddBox(box2); root.AddBox(box3); LayoutInfo layoutArgs = MakeLayoutInfo(); root.Layout(layoutArgs); Assert.That(box1.Height, Is.EqualTo(48)); Assert.That(box2.Height, Is.EqualTo(24)); Assert.That(root.Height, Is.EqualTo(48 + 24 + 24)); Assert.That(box1.Left, Is.EqualTo(0)); Assert.That(box2.Left, Is.EqualTo(0)); Assert.That(box1.Top, Is.EqualTo(0)); Assert.That(box2.Top, Is.EqualTo(48)); Assert.That(box3.Top, Is.EqualTo(48 + 24)); Assert.That(box1.Width, Is.EqualTo(96)); Assert.That(box2.Width, Is.EqualTo(144)); Assert.That(root.Width, Is.EqualTo(144)); }
/// <summary> /// Assuming the first box in the root is a paragraph, and its first box is a string box with a mock segment, return it. /// </summary> /// <param name="root"></param> /// <returns></returns> MockSegment FirstMockSegment(RootBox root) { ParaBox pb = root.FirstBox as ParaBox; StringBox first = pb.FirstBox as StringBox; return(first.Segment as MockSegment); }
/// <summary> /// Assuming the first box in the root is a paragraph, and its second box is a string box with a mock segment, return it. /// </summary> /// <param name="root"></param> /// <returns></returns> MockSegment SecondMockSegment(RootBox root) { ParaBox pb = root.FirstBox as ParaBox; StringBox second = pb.FirstBox.Next as StringBox; return(second.Segment as MockSegment); }
private void VerifyPaint(RootBox root, Rectangle clipRect, int xScrollOffset, int yScrollOffset, Rectangle[] paintRects) { MockGraphics graphics = new MockGraphics(); graphics.ClipRectangle = clipRect; PaintTransform ptrans = new PaintTransform(0, 0, 96, 96, xScrollOffset, yScrollOffset, 96, 96); root.Paint(graphics, ptrans); var drawActions = graphics.DrawActions; // after the paint, it gets created when first rect added. if (paintRects == null || paintRects.Length == 0) { Assert.IsTrue(drawActions == null || drawActions.Count == 0); return; } Assert.That(drawActions, Has.Count.EqualTo(paintRects.Length * 2)); int position = 0; // First all the blocks get drawn in their PaintBackground routine foreach (var rect in paintRects) { VerifyRect(drawActions, ref position, rect); } // Then we verify that the PaintForeground routines got called. for (; position < drawActions.Count; position++) { Assert.That(drawActions[position], Is.InstanceOf(typeof(FgBlockBox))); } }
/// <summary> /// Any selection that involves an IAnalysis should be expanded to complete IAnalysis objects. /// This method also updates a list of selected AnalysisOccurrences. /// </summary> /// <param name="prootb"></param> /// <param name="vwselNew"></param> protected override void HandleSelectionChange(IVwRootBox prootb, IVwSelection vwselNew) { if (m_fInSelChanged) { return; } m_fInSelChanged = true; try { m_selectedWordforms = null; base.HandleSelectionChange(prootb, vwselNew); if (vwselNew == null) { return; } SelLevInfo[] analysisLevels; SelLevInfo[] endLevels; if (TryGetAnalysisLevelsAndEndLevels(vwselNew, out analysisLevels, out endLevels)) { m_selectedWordforms = GetSelectedOccurrences(analysisLevels, endLevels[0].ihvo); RootBox.MakeTextSelInObj(0, analysisLevels.Length, analysisLevels, endLevels.Length, endLevels, false, false, false, true, true); } else { RootBox.DestroySelection(); } } finally { m_fInSelChanged = false; } }
protected void MakeTextSelectionAndScrollToView(int ichMin, int ichLim, int ws, int ipara, int ihvoEnd) { var rgsli = new SelLevInfo[1]; // entry 0 says which StTextPara rgsli[0].ihvo = ipara; rgsli[0].tag = StTextTags.kflidParagraphs; // entry 1 says to use the Contents of the Text. //rgsli[1].tag = (int)FDO.Ling.Text.TextTags.kflidContents; try { RootBox.MakeTextSelection(0, rgsli.Length, rgsli, StTxtParaTags.kflidContents, 0, ichMin, ichLim, ws, false, // Range, arbitrary assoc prev. ihvoEnd, null, // don't set any special text props for typing true); // install it // Don't steal the focus from another window. See FWR-1795. if (ParentForm == Form.ActiveForm) { Focus(); } // Scroll this selection into View. var sel = RootBox.Selection; ScrollSelectionIntoView(sel, VwScrollSelOpts.kssoDefault); Update(); } catch (Exception) { } }
int IchMinOfSecondStringBox(RootBox root) { ParaBox pb = root.FirstBox as ParaBox; StringBox second = pb.FirstBox.Next as StringBox; return(second.IchMin); }
public void MakeSimpleRange() { ParaBox para; RootBox root = ParaBuilderTests.MakeTestParaSimpleString(m_gm.VwGraphics, ParaBuilderTests.MockBreakOption.ThreeFullLines, out para); InsertionPoint ip = root.SelectAtEnd(); InsertionPoint ip2 = new InsertionPoint(ip.Hookup, ip.StringPosition - 2, false); RangeSelection range = new RangeSelection(ip, ip2); Assert.AreEqual(ip, range.Anchor); Assert.AreEqual(ip2, range.DragEnd); Assert.That(range.EndBeforeAnchor, Is.True); Assert.That(range.Start, Is.EqualTo(ip2)); Assert.That(range.End, Is.EqualTo(ip)); StringBox first = para.FirstBox as StringBox; StringBox second = para.FirstBox.Next as StringBox; StringBox third = second.Next as StringBox; MockSegment seg3 = third.Segment as MockSegment; seg3.DrawRangeLeft = 17; seg3.DrawRangeRight = 23; PaintTransform ptrans = new PaintTransform(2, 4, 96, 100, 0, 10, 120, 128); range.Draw(m_gm.VwGraphics, ptrans); // All three segments should be invited to draw it, though only one will. // The top of rsSrc gets more negative each line; the destination rectangle where we actually draw keeps getting lower. // Remember the effect of 10 pixels of scroll offset. VerifyRangeSegmentDrawing(para, first, first.Segment as MockSegment, range, -4, -6, 4); VerifyRangeSegmentDrawing(para, second, second.Segment as MockSegment, range, -14, 4, 14); VerifyRangeSegmentDrawing(para, third, seg3, range, -24, 14, 24); }
private void InitStyledText() { AssembledStyles styles = new AssembledStyles(); RootBox root = new RootBox(styles); root.RendererFactory = theSharpView.RendererFactory; var obj0 = new ParagraphDemo() { Contents = "plain " }; var obj1 = new ParagraphDemo() { Contents = "bold " }; var obj2 = new ParagraphDemo() { Contents = "italic " }; var obj3 = new ParagraphDemo() { Contents = "bold italic " }; var obj4 = new ParagraphDemo() { Contents = "red on yellow" }; int ws = 1; // arbitrary with default renderer factory. root.Builder.Show( Paragraph.Containing( Display.Of(() => obj0.Contents, ws).FaceName("Times New Roman"), Display.Of(() => obj1.Contents, ws).FaceName("Times New Roman").Bold, Display.Of(() => obj2.Contents, ws).FaceName("Times New Roman").Italic, Display.Of(() => obj3.Contents, ws).FaceName("Times New Roman").Bold.Italic, Display.Of(() => obj4.Contents, ws).ForeColor(Color.Red).BackColor(Color.Yellow) ).Border(1.Points(), Color.Red).Pads(2.Points(), 3.Points(), 2.Points(), 3.Points()) ); root.Builder.Show( Paragraph.Containing( Display.Of("plain"), Display.Of("underOnYellow").Underline(FwUnderlineType.kuntSingle).BackColor(Color.Yellow).FaceName("Times New Roman") ).Margins(3.Points(), 2.Points(), 5.Points(), 2.Points()) .Borders(1.Points(), 2.Points(), 3.Points(), 4.Points(), Color.Green) .BackColor(Color.Pink).Pads(2.Points(), 2.Points(), 2.Points(), 2.Points()), Paragraph.Containing( Display.Of("doubleRedOnPink").Underline(FwUnderlineType.kuntDouble, Color.Red).BackColor(Color.Pink), Display.Of("dotted").Underline(FwUnderlineType.kuntDotted), Display.Of("dottedOnYellow").Underline(FwUnderlineType.kuntDotted).BackColor(Color.Yellow) ), Paragraph.Containing( Display.Of("dashed").Underline(FwUnderlineType.kuntDashed), Display.Of("dashedRed").Underline(FwUnderlineType.kuntDashed).ForeColor(Color.Red), Display.Of("squiggle").Underline(FwUnderlineType.kuntSquiggle, Color.Red) ) ); theSharpView.Root = root; root.SelectAtEnd().Install(); theSharpView.Focus(); }
/// ------------------------------------------------------------------------------------ /// <summary> /// If we need to make a selection, but we can't because edits haven't been updated in /// the view, this method requests creation of a selection after the unit of work is /// complete. It will also scroll the selection into view. /// Derived classes should implement this if they have any hope of supporting multi- /// paragraph editing. /// </summary> /// <param name="helper">The selection to restore</param> /// ------------------------------------------------------------------------------------ public override void RequestVisibleSelectionAtEndOfUow(SelectionHelper helper) { Assert.IsNull(RequestedSelectionAtEndOfUow); RequestedSelectionAtEndOfUow = helper; RootBox.DestroySelection(); // Need to act like real program in this regard }
private void SetupFakeRootSite(RootBox root) { PaintTransform ptrans = new PaintTransform(2, 4, 96, 100, 0, 10, 120, 128); MockSite site = new MockSite(); site.m_transform = ptrans; site.m_vwGraphics = m_gm.VwGraphics; root.Site = site; }
protected override bool OnRightMouseUp(Point pt, Rectangle rcSrcRoot, Rectangle rcDstRoot) { IVwSelection sel = RootBox.MakeSelAt(pt.X, pt.Y, rcSrcRoot, rcDstRoot, false); TextSelInfo tsi = new TextSelInfo(sel); return(HandleRightClickOnObject(tsi.Hvo(false))); }
public void InvalidateInRoot() { var site = new MockSite(); var root = new RootBox(new AssembledStyles()); root.Site = site; using (var lc = new LayoutCallbacks(root)) { lc.InvalidateInRoot(new Rectangle(10, 13, 17, 19)); lc.InvalidateInRoot(new Rectangle(9, 8, 5, 4)); Assert.That(site.RectsInvalidatedInRoot, Is.Empty); } Assert.That(site.RectsInvalidatedInRoot, Has.Member(new Rectangle(10, 13, 17, 19))); Assert.That(site.RectsInvalidatedInRoot, Has.Member(new Rectangle(9, 8, 5, 4))); }
public void LazyBoxExpanded() { var root = new RootBox(new AssembledStyles()); root.RaiseLazyExpanded(new RootBox.LazyExpandedEventArgs()); // make sure harmless with no subscribers root.LazyExpanded += root_LazyExpanded; using (var lc = new LayoutCallbacks(root)) { lc.RaiseLazyExpanded(10, 17, 5); lc.RaiseLazyExpanded(5, 6, -2); Assert.That(m_expandArgs, Is.Empty); } VerifyExpandArgs(0, 10, 17, 5); VerifyExpandArgs(1, 5, 6, -2); }
public void MakeRootBox() { AssembledStyles styles = new AssembledStyles(); BlockBox box = new BlockBox(styles, Color.Red, 72000, 36000); RootBox root = new RootBox(styles); root.AddBox(box); LayoutInfo transform = MakeLayoutInfo(); root.Layout(transform); Assert.AreEqual(48, box.Height); Assert.AreEqual(96, box.Width); Assert.AreEqual(48, root.Height); Assert.AreEqual(96, root.Width); }
public void PaintBarBox() { AssembledStyles styles = new AssembledStyles(); BlockBox box = new BlockBox(styles, Color.Red, 72000, 36000); RootBox root = new RootBox(styles); root.AddBox(box); LayoutInfo transform = MakeLayoutInfo(); root.Layout(transform); PaintTransform ptrans = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96); MockGraphics graphics = new MockGraphics(); root.Paint(graphics, ptrans); Assert.AreEqual(1, graphics.RectanglesDrawn.Count); Assert.AreEqual(new Rectangle(2, 2, 96, 48), graphics.RectanglesDrawn[0]); Assert.AreEqual((int)ColorUtil.ConvertColorToBGR(Color.Red), graphics.BackColor); }
public void OneBlockPara() { AssembledStyles styles = new AssembledStyles(); List<IClientRun> clientRuns = new List<IClientRun>(); BlockBox box = new BlockBox(styles, Color.Red, 72000, 36000); clientRuns.Add(box); TextSource source = new TextSource(clientRuns, null); ParaBox para = new ParaBox(styles, source); RootBox root = new RootBox(styles); root.AddBox(para); LayoutInfo layoutArgs = MakeLayoutInfo(); root.Layout(layoutArgs); Assert.AreEqual(48, box.Height); Assert.AreEqual(96, box.Width); Assert.AreEqual(48, root.Height); Assert.AreEqual(96, root.Width); }
public void InstallSelection() { var root = new RootBox(new AssembledStyles()); var firstSel = new DummySelection(); root.Selection = firstSel; Assert.IsTrue(firstSel.WasInvalidated); firstSel.WasInvalidated = false; var secondSel = new DummySelection(); root.Selection = secondSel; Assert.IsTrue(firstSel.WasInvalidated); // the old one needs to disappear Assert.IsTrue(secondSel.WasInvalidated); secondSel.WasInvalidated = false; firstSel.WasInvalidated = false; root.Selection = null; Assert.IsFalse(firstSel.WasInvalidated); // this was not previously visible Assert.IsTrue(secondSel.WasInvalidated); // old one still needs to go. }
public void PaintPictureBox() { AssembledStyles styles = new AssembledStyles(); Bitmap bm = new Bitmap(20, 30); ImageBox box = new ImageBox(styles.WithMargins(new Thickness(72.0 / 96.0 * 2.0)) .WithBorders(new Thickness(72.0 / 96.0 * 3.0)) .WithPads(new Thickness(72.0 / 96.0 * 7.0, 72.0 / 96.0 * 8.0, 72.0 / 96.0 * 11.0, 72.0 / 96.0 * 13.0)), bm); RootBox root = new RootBox(styles); BlockBox block = new BlockBox(styles, Color.Yellow, 2000, 4000); root.AddBox(block); root.AddBox(box); LayoutInfo transform = MakeLayoutInfo(); root.Layout(transform); Assert.That(box.Height, Is.EqualTo(30 + 2*2+3*2+8+13)); Assert.That(box.Width, Is.EqualTo(20 + 2*2 +3*2 + 7 + 11)); Assert.That(box.Ascent, Is.EqualTo(box.Height)); PaintTransform ptrans = new PaintTransform(2, 4, 96, 96, 10, 40, 96, 96); MockGraphics graphics = new MockGraphics(); root.Paint(graphics, ptrans); Assert.That(graphics.LastRenderPictureArgs, Is.Not.Null); Assert.That(graphics.LastRenderPictureArgs.Picture, Is.EqualTo(box.Picture)); Assert.That(graphics.LastRenderPictureArgs.X, Is.EqualTo(2-10 + 2 + 3 + 7)); Assert.That(graphics.LastRenderPictureArgs.Y, Is.EqualTo(4 - 40 + block.Height + 2 + 3 + 8)); Assert.That(graphics.LastRenderPictureArgs.Cx, Is.EqualTo(20)); Assert.That(graphics.LastRenderPictureArgs.Cy, Is.EqualTo(30)); int hmWidth = box.Picture.Width; int hmHeight = box.Picture.Height; Assert.That(graphics.LastRenderPictureArgs.XSrc, Is.EqualTo(0)); Assert.That(graphics.LastRenderPictureArgs.YSrc, Is.EqualTo(hmHeight)); Assert.That(graphics.LastRenderPictureArgs.CxSrc, Is.EqualTo(hmWidth)); Assert.That(graphics.LastRenderPictureArgs.CySrc, Is.EqualTo(-hmHeight)); Assert.That(graphics.LastRenderPictureArgs.RcWBounds.left, Is.EqualTo(2 - 10 + 2 + 3 + 7)); Assert.That(graphics.LastRenderPictureArgs.RcWBounds.top, Is.EqualTo(4 - 40 + block.Height + 2 + 3 + 8)); Assert.That(graphics.LastRenderPictureArgs.RcWBounds.right, Is.EqualTo(2 - 10 + 2 + 3 + 7 + 20)); Assert.That(graphics.LastRenderPictureArgs.RcWBounds.bottom, Is.EqualTo(4 - 40 + block.Height + 2 + 3 + 8 + 30)); }
public void PileOfBlocksLayout() { var styles = new AssembledStyles(); BlockBox box1 = new BlockBox(styles, Color.Red, 72000, 36000); BlockBox box2 = new BlockBox(styles, Color.Blue, 108000, 18000); BlockBox box3 = new BlockBox(styles, Color.Orange, 72000, 18000); RootBox root = new RootBox(styles); root.AddBox(box1); root.AddBox(box2); root.AddBox(box3); LayoutInfo layoutArgs = MakeLayoutInfo(); root.Layout(layoutArgs); Assert.That(box1.Height, Is.EqualTo(48)); Assert.That(box2.Height, Is.EqualTo(24)); Assert.That(root.Height, Is.EqualTo(48 + 24 + 24) ); Assert.That(box1.Left, Is.EqualTo(0)); Assert.That(box2.Left, Is.EqualTo(0)); Assert.That(box1.Top, Is.EqualTo(0)); Assert.That(box2.Top, Is.EqualTo(48)); Assert.That(box3.Top, Is.EqualTo(48 + 24)); Assert.That(box1.Width, Is.EqualTo(96)); Assert.That(box2.Width, Is.EqualTo(144)); Assert.That(root.Width, Is.EqualTo(144)); }
public void DivClippedPaint() { var styles = new AssembledStyles(); var box1 = new FgBlockBox(styles, Color.Red, 72000, 36000); var box2 = new FgBlockBox(styles, Color.Blue, 108000, 18000); var box3 = new FgBlockBox(styles, Color.Orange, 72000, 18000); var box4 = new FgBlockBox(styles, Color.Orange, 72000, 18000); var div1 = new DivBox(styles); div1.AddBox(box1); div1.AddBox(box2); div1.AddBox(box3); div1.AddBox(box4); RootBox root = new RootBox(styles); root.AddBox(div1); LayoutInfo layoutArgs = MakeLayoutInfo(); root.Layout(layoutArgs); var rect1 = new Rectangle(0, 0, 96, 48); var rect2 = new Rectangle(0, 0, 144, 24); rect2.Offset(0, rect1.Bottom); var rect3 = new Rectangle(0, 0, 96, 24); rect3.Offset(0, rect2.Bottom); var rect4 = new Rectangle(0, 0, 96, 24); rect4.Offset(0, rect3.Bottom); var paintRects = new[] { rect1, rect2, rect3, rect4 }; VerifyPaint(root, new Rectangle(-1000, -1000, 2000, 2000), 0, 0, paintRects); // Clipping off the top part, but not the whole, of a box does not prevent drawing it. VerifyPaint(root, new Rectangle(-1000, 10, 2000, -10 + rect4.Bottom - 10), 0, 0, paintRects); // Even clipping all but one pixel does not prevent drawing. VerifyPaint(root, new Rectangle(-1000, 47, 2000, -47 + rect3.Bottom + 1), 0, 0, paintRects); // However if we clip a bit more we should draw less var middleTwo = new[] {rect2, rect3}; VerifyPaint(root, new Rectangle(-1000, 48, 2000, -48 + rect3.Bottom - 2), 0, 0, middleTwo); // If the clip covers just a bit of the first box we paint just that. var firstOne = new[] {rect1}; VerifyPaint(root, new Rectangle(-1000, -1000, 2000, 1000 + 10), 0, 0, firstOne); // If the clip covers just a bit of the last box we paint just that. var lastOne = new[] { rect4 }; VerifyPaint(root, new Rectangle(-1000, rect4.Bottom - 2, 2000, 1000), 0, 0, lastOne); // If the clip is entirely above the pile we draw nothing. VerifyPaint(root, new Rectangle(-1000, -1000, 2000, 990), 0, 0, null); // Likewise if entirely below. VerifyPaint(root, new Rectangle(-1000, rect4.Bottom + 10, 2000, 10), 0, 0, null); // Now try with simulated scrolling. Use a normal clip rectangle, but pretend the first two // and a bit boxes are scrolled off. var offset = rect2.Bottom + 10; var rect3Offset = rect3; rect3Offset.Offset(0, -offset); var rect4Offset = rect4; rect4Offset.Offset(0, -offset); var lastTwoOffset = new[] {rect3Offset, rect4Offset}; VerifyPaint(root, new Rectangle(-1000, 0, 2000, 200), 0, offset, lastTwoOffset); }
public void NextAndPrevInSelectionSeq() { var styles = new AssembledStyles(); var root = new RootBox(styles); Assert.That(root.NextInSelectionSequence(true), Is.Null); Assert.That(root.PreviousInSelectionSequence, Is.Null); var block = new BlockBox(styles, Color.Red, 6000, 6000); root.AddBox(block); Assert.That(root.NextInSelectionSequence(true), Is.EqualTo(block)); Assert.That(block.PreviousInSelectionSequence, Is.EqualTo(root)); var div = new DivBox(styles); root.AddBox(div); Assert.That(block.NextInSelectionSequence(true), Is.EqualTo(div)); Assert.That(div.PreviousInSelectionSequence, Is.EqualTo(block)); var divChild = new DivBox(styles); div.AddBox(divChild); var block2 = new BlockBox(styles, Color.Red, 6000, 6000); divChild.AddBox(block2); var block3 = new BlockBox(styles, Color.Red, 6000, 6000); divChild.AddBox(block3); var block4 = new BlockBox(styles, Color.Red, 6000, 6000); div.AddBox(block4); // up and forward Assert.That(block3.NextInSelectionSequence(true), Is.EqualTo(block4)); Assert.That(block4.PreviousInSelectionSequence, Is.EqualTo(block3)); // Can go back from a box to a previous empty group var emptyDiv = new DivBox(styles); root.AddBox(emptyDiv); var block5 = new BlockBox(styles, Color.Red, 6000, 6000); root.AddBox(block5); Assert.That(emptyDiv.NextInSelectionSequence(true), Is.EqualTo(block5)); Assert.That(block5.PreviousInSelectionSequence, Is.EqualTo(emptyDiv)); Assert.That(div.NextInSelectionSequence(true), Is.EqualTo(divChild)); Assert.That(div.NextInSelectionSequence(false), Is.EqualTo(emptyDiv)); }
public void CommonContainerTests() { var styles = new AssembledStyles(); var columnWidths = new FixedColumnWidths(new[] {10}); var root1 = new RootBox(styles); var root2 = new RootBox(styles); VerifyCC(root1, root1, root1, root1, root1); VerifyCC(root2, root2, root2, root2, root2); var row1 = new RowBox(styles, columnWidths, false); var div1 = new DivBox(styles); root2.AddBox(row1); root1.AddBox(div1); VerifyCC(row1, row1, row1, row1, row1); VerifyCC(div1, div1, div1, div1, div1); VerifyCC(root1, div1, root1, root1, div1); VerifyCC(root2, row1, root2, root2, row1); var row2 = new RowBox(styles, columnWidths, false); var div2 = new DivBox(styles); root2.AddBox(row2); root1.AddBox(div2); VerifyCC(row1, row2, root2, row1, row2); VerifyCC(div1, div2, root1, div1, div2); var row3 = new RowBox(styles, columnWidths, false); var div3 = new DivBox(styles); row1.AddBox(row3); div1.AddBox(div3); VerifyCC(row1, row3, row1, row1, row3); VerifyCC(row2, row3, root2, row2, row1); VerifyCC(div1, div3, div1, div1, div3); VerifyCC(div2, div3, root1, div2, div1); var row4 = new RowBox(styles, columnWidths, false); var div4 = new DivBox(styles); row2.AddBox(row4); div2.AddBox(div4); VerifyCC(row3, row4, root2, row1, row2); VerifyCC(row1, row4, root2, row1, row2); VerifyCC(div3, div4, root1, div1, div2); VerifyCC(div1, div4, root1, div1, div2); }
public static SelectionBuilder In(RootBox root) { return In(root.RootHookup); }
Point TopLeftOfSecondStringBox(RootBox root) { ParaBox pb = root.FirstBox as ParaBox; StringBox second = pb.FirstBox.Next as StringBox; return second.TopLeft; }
private void VerifyPaint(RootBox root, Rectangle clipRect, int xScrollOffset, int yScrollOffset, Rectangle[] paintRects) { MockGraphics graphics = new MockGraphics(); graphics.ClipRectangle = clipRect; PaintTransform ptrans = new PaintTransform(0, 0, 96, 96, xScrollOffset, yScrollOffset, 96, 96); root.Paint(graphics, ptrans); var drawActions = graphics.DrawActions; // after the paint, it gets created when first rect added. if (paintRects == null || paintRects.Length == 0) { Assert.IsTrue(drawActions == null || drawActions.Count == 0); return; } Assert.That(drawActions, Has.Count.EqualTo(paintRects.Length * 2)); int position = 0; // First all the blocks get drawn in their PaintBackground routine foreach (var rect in paintRects) { VerifyRect(drawActions, ref position, rect); } // Then we verify that the PaintForeground routines got called. for (; position < drawActions.Count; position++) Assert.That(drawActions[position], Is.InstanceOf(typeof(FgBlockBox))); }
public void FiveBlockPara() { AssembledStyles styles = new AssembledStyles(); var clientRuns = new List<IClientRun>(); BlockBox box0 = new BlockBox(styles, Color.Red, 72000, 36000); clientRuns.Add(box0); BlockBox box1 = new BlockBox(styles, Color.Blue, 36000, 18000); clientRuns.Add(box1); BlockBox box2 = new BlockBox(styles, Color.Red, 24000, 18000); clientRuns.Add(box2); BlockBox box3 = new BlockBox(styles, Color.Red, 72000, 36000); clientRuns.Add(box3); BlockBox box4 = new BlockBox(styles, Color.Red, 36000, 36000); clientRuns.Add(box4); TextSource source = new TextSource(clientRuns, null); ParaBox para = new ParaBox(styles, source); RootBox root = new RootBox(styles); root.AddBox(para); LayoutInfo layoutArgs = MakeLayoutInfo(); root.Layout(layoutArgs); VerifyBox(box0, 96, 48, box1, para, "box0"); VerifyBox(box1, 48, 24, box2, para, "box1"); VerifyBox(box2, 32, 24, box3, para, "box2"); VerifyBox(box3, 96, 48, box4, para, "box3"); VerifyBox(box4, 48, 48, null, para, "box4"); VerifyGroup(para, 96 + 48 + 32 + 96 + 48, 48, null, root, box0, box4, "para"); VerifyGroup(root, 96 + 48 + 32 + 96 + 48, 48, null, null, para, para, "root"); VerifyParaLine(para, 0, box0, box4, 0, "para unlimited one line"); // Check multi-line layout (one line has room for two boxes). LayoutInfo layoutArgs2 = MakeLayoutInfo(100, m_gm.VwGraphics); root.Layout(layoutArgs2); Assert.AreEqual(4, para.Lines.Count, "para1 at 100 has four lines"); VerifyBox(box0, 96, 48, box1, para, "box0/100"); VerifyBox(box1, 48, 24, box2, para, "box1/100"); VerifyBox(box2, 32, 24, box3, para, "box2/100"); VerifyBox(box3, 96, 48, box4, para, "box3/100"); VerifyBox(box4, 48, 48, null, para, "box4/100"); VerifyParaLine(para, 0, box0, box0, 0, "para/100 first"); VerifyParaLine(para, 1, box1, box2, 48, "para/100 second"); VerifyParaLine(para, 2, box3, box3, 48 + 24, "para/100 third"); VerifyParaLine(para, 3, box4, box4, 48 + 24 + 48, "para/100 fourth"); // At 100 pixels wide, box0 goes on the first line, boxes 1 and 2 on the third, box 3 and box4 take the fourth and fifth. // Multiple lines means the paragraph occupies its full width. int height100 = 48 + 24 + 48 + 48; VerifyGroup(para, 100, height100, null, root, box0, box4, "para/100"); VerifyGroup(root, 100, height100, null, null, para, para, "root/100"); // Check layout when some boxes won't fit on a whole line. LayoutInfo layoutArgs3 = MakeLayoutInfo(50, m_gm.VwGraphics); root.Layout(layoutArgs3); Assert.AreEqual(5, para.Lines.Count, "para1 at 50 has five lines"); VerifyBox(box0, 96, 48, box1, para, "box0/50"); VerifyParaLine(para, 0, box0, box0, 0, "para/50 first"); VerifyParaLine(para, 1, box1, box1, 48, "para/50 second"); VerifyParaLine(para, 2, box2, box2, 48 + 24, "para/50 third"); VerifyParaLine(para, 3, box3, box3, 48 + 24 + 24, "para/50 fourth"); VerifyParaLine(para, 4, box4, box4, 48 + 24 + 24 +48, "para/50 fifth"); // At 100 pixels wide, box0 goes on the first line, boxes 1 and 2 on the third, box 3 and box4 take the fourth and fifth. // Multiple lines means the paragraph occupies its full width. int height50 = 48 + 24 + 24 + 48 + 48; VerifyGroup(para, 96, height50, null, root, box0, box4, "para/50"); VerifyGroup(root, 96, height50, null, null, para, para, "root/50"); }
public void ContentChangeWrapping() { var styles = new AssembledStyles().WithWs(s_simpleStringWs); string contents1 = "This is a simple string. It has two sentences."; var clientRuns = new List<IClientRun>(); clientRuns.Add(new StringClientRun(contents1, styles)); var source = new TextSource(clientRuns, null); var para = new ParaBox(styles, source); var root = new RootBox(styles); root.AddBox(para); var layoutArgs = MakeLayoutInfo(30, m_gm.VwGraphics); }
/// <summary> /// Assuming the first box in the root is a paragraph, and its first box is a string box with a mock segment, return it. /// </summary> /// <param name="root"></param> /// <returns></returns> MockSegment FirstMockSegment(RootBox root) { ParaBox pb = root.FirstBox as ParaBox; StringBox first = pb.FirstBox as StringBox; return first.Segment as MockSegment; }
/// <summary> /// Assuming the first box in the root is a paragraph, and its second box is a string box with a mock segment, return it. /// </summary> /// <param name="root"></param> /// <returns></returns> MockSegment SecondMockSegment(RootBox root) { ParaBox pb = root.FirstBox as ParaBox; StringBox second = pb.FirstBox.Next as StringBox; return second.Segment as MockSegment; }
int IchMinOfSecondStringBox(RootBox root) { ParaBox pb = root.FirstBox as ParaBox; StringBox second = pb.FirstBox.Next as StringBox; return second.IchMin; }
void root_LazyExpanded(object sender, RootBox.LazyExpandedEventArgs e) { m_expandArgs.Add(e); }
/// <summary> /// The setup method for para builder is also useful for testing stuff related to the paragraph itself. /// </summary> /// <param name="vg"></param> /// <param name="para"></param> /// <returns></returns> internal static RootBox MakeTestParaSimpleString(IVwGraphics vg, MockBreakOption breakOption, out ParaBox para) { var styles = new AssembledStyles().WithWs(s_simpleStringWs); string contents = AssembleStrings(s_simpleStringWords); var clientRuns = new List<IClientRun>(); clientRuns.Add(new StringClientRun(contents, styles)); var source = new TextSource(clientRuns, null); para = new ParaBox(styles, source); var root = new RootBox(styles); root.AddBox(para); var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, vg); var engine = layoutArgs.GetRenderer(1) as MockRenderEngine; switch (breakOption) { case MockBreakOption.ThreeOkayBreaks: // This option generates three lines as long as the width is sufficient because // Asked to break the whole string we answer a segment that has the first three words. engine.AddMockSeg(0, contents.Length, SumStringLengths(s_simpleStringWords, 0, 3), s_widthFirstMockSeg, s_simpleStringWs, LgEndSegmentType.kestOkayBreak); // Asked to break the rest of the line we answer a segment with the next three. engine.AddMockSeg(SumStringLengths(s_simpleStringWords, 0, 3), contents.Length, SumStringLengths(s_simpleStringWords, 3, 6), s_widthSecondMockSeg, s_simpleStringWs, LgEndSegmentType.kestOkayBreak); // Asked to break the rest of the line we answer a segment with the last three. engine.AddMockSeg(SumStringLengths(s_simpleStringWords, 0, 6), contents.Length, SumStringLengths(s_simpleStringWords, 6, 9), s_widthThirdMockSeg, s_simpleStringWs, LgEndSegmentType.kestNoMore); break; case MockBreakOption.FourSegsThreeLines: // Asked to break the whole string we answer a segment that has the first two words but allows more. engine.AddMockSeg(0, contents.Length, SumStringLengths(s_simpleStringWords, 0, 2), 50, s_simpleStringWs, LgEndSegmentType.kestOkayBreak); // Asked to break the rest of the line we give one more word and say it fills the line. engine.AddMockSeg(SumStringLengths(s_simpleStringWords, 0, 2), contents.Length, SumStringLengths(s_simpleStringWords, 0, 3), 20, s_simpleStringWs, LgEndSegmentType.kestMoreLines); // Asked to break the rest of the line we answer a segment with the next three and say it fills the line. engine.AddMockSeg(SumStringLengths(s_simpleStringWords, 0, 3), contents.Length, SumStringLengths(s_simpleStringWords, 3, 6), s_widthSecondMockSeg, s_simpleStringWs, LgEndSegmentType.kestMoreLines); // Asked to break the rest of the line we answer a segment with the last three. engine.AddMockSeg(SumStringLengths(s_simpleStringWords, 0, 6), contents.Length, SumStringLengths(s_simpleStringWords, 6, 9), s_widthThirdMockSeg, s_simpleStringWs, LgEndSegmentType.kestNoMore); // Asked to do anything else engine.OtherSegPolicy = UnexpectedSegments.MakeOneCharSeg; break; case MockBreakOption.ThreeFullLines: // Asked to break the whole string we answer a segment that has the first three words. SetupMockEngineForThreeLines(contents, engine, s_simpleStringWords); break; } root.Layout(layoutArgs); return root; }
public void NestedDivsLayout() { var styles = new AssembledStyles(); BlockBox box1 = new BlockBox(styles, Color.Red, 72000, 36000); BlockBox box2 = new BlockBox(styles, Color.Blue, 108000, 18000); BlockBox box3 = new BlockBox(styles, Color.Orange, 72000, 18000); BlockBox box4 = new BlockBox(styles, Color.Orange, 72000, 18000); var div1 = new DivBox(styles); var div2 = new DivBox(styles); div1.AddBox(box1); div1.AddBox(box2); div2.AddBox(box3); div2.AddBox(box4); RootBox root = new RootBox(styles); root.AddBox(div1); root.AddBox(div2); LayoutInfo layoutArgs = MakeLayoutInfo(); root.Layout(layoutArgs); Assert.That(box1.Height, Is.EqualTo(48)); Assert.That(box2.Height, Is.EqualTo(24)); Assert.That(root.Height, Is.EqualTo(48 + 24 + 24 + 24)); Assert.That(box1.Left, Is.EqualTo(0)); Assert.That(box2.Left, Is.EqualTo(0)); Assert.That(box1.Top, Is.EqualTo(0)); Assert.That(box2.Top, Is.EqualTo(48)); Assert.That(div2.Top, Is.EqualTo(48 + 24)); Assert.That(box4.Top, Is.EqualTo(24)); Assert.That(box1.Width, Is.EqualTo(96)); Assert.That(box2.Width, Is.EqualTo(144)); Assert.That(root.Width, Is.EqualTo(144)); // Now try changing the size of a block. MockSite site = new MockSite(); root.Site = site; PaintTransform ptrans = new PaintTransform(2, 4, 96, 96, 0, 10, 120, 128); site.m_transform = ptrans; site.m_vwGraphics = m_gm.VwGraphics; box2.UpdateSize(144000, 36000); Assert.That(box2.Width, Is.EqualTo(96*2)); Assert.That(box2.Height, Is.EqualTo(48)); Assert.That(div1.Height, Is.EqualTo(96)); // two children now both 48 high. Assert.That(root.Height, Is.EqualTo(48 +48 + 24 + 24)); // new heights of 4 children. Assert.That(root.Width, Is.EqualTo(96*2)); // Since it got both wider and higher, we should invalidate at least the whole current size. var bigInvalidate = root.InvalidateRect; Assert.That(site.RectsInvalidatedInRoot, Has.Member(bigInvalidate)); site.RectsInvalidated.Clear(); box2.UpdateSize(108000, 36000); Assert.That(root.Height, Is.EqualTo(48 + 48 + 24 + 24)); // unchanged this time Assert.That(root.Width, Is.EqualTo(144)); // narrower box2 still determines it // Got narrower, at least the whole old invalidate rectangle should be invalidated. Assert.That(site.RectsInvalidatedInRoot, Has.Member(bigInvalidate)); site.RectsInvalidated.Clear(); box2.UpdateSize(108000, 18000); Assert.That(root.Height, Is.EqualTo(48 + 24 + 24 + 24)); // new smaller value Assert.That(root.Width, Is.EqualTo(144)); // unchanged this time // It got shorter. We want an optimized invalidate rectangle that does not // include the top box. But it must include the space at the bottom that the root box used to occupy. // There are other possible implementations, but currently, we expect the old rectangle of box2 // to be invalidated (its in the fixmap so its own Relayout does this); // the shrinkage area at the bottom of div2; // and the area computed because div2 moved. VerifyExpectedRectangle(site.RectsInvalidatedInRoot, 0, 48, 144, 48); // old box2 VerifyExpectedRectangle(site.RectsInvalidatedInRoot, 0, 48 + 24, 144, 24); // shrinkage of div1 // This is from the new top of div2 to its old bottom (old bottom was 48 + 48 + 24 + 24) VerifyExpectedRectangle(site.RectsInvalidatedInRoot, 0, 48 + 24, 144, 48 + 24); site.RectsInvalidated.Clear(); box2.UpdateSize(108000, 72000); Assert.That(root.Height, Is.EqualTo(48 + 96 + 24 + 24)); // new larger value Assert.That(root.Width, Is.EqualTo(144)); // unchanged this time // It got longer. We want an optimized invalidate rectangle that does not // include the top box. But it must include the space at the bottom where the root box grew. // There are other possible implementations, but currently, we expect the old rectangle of box2 // to be invalidated (it returns true from Relayout); // the growth area at the bottom of div2; // and the area computed because div2 moved. VerifyExpectedRectangle(site.RectsInvalidatedInRoot, 0, 48, 144, 96); // new box2 VerifyExpectedRectangle(site.RectsInvalidatedInRoot, 0, 48 + 24, 144, 96 - 24); // new part of div1 occupied by box2 // This is from the old top of div2 to its new bottom (48 + 96 + 24 + 24) VerifyExpectedRectangle(site.RectsInvalidatedInRoot, 0, 48 + 24, 144, 96 + 24); }
public void EmptyString() { int ws = 1; AssembledStyles styles = new AssembledStyles().WithWs((ws)); var clientRuns = new List<IClientRun>(); StringClientRun clientRun = new StringClientRun("", styles); clientRuns.Add(clientRun); TextSource source = new TextSource(clientRuns, null); ParaBox para = new ParaBox(styles, source); RootBox root = new RootBox(styles); root.AddBox(para); LayoutInfo layoutArgs = MakeLayoutInfo(); var engine = layoutArgs.GetRenderer(1) as MockRenderEngine; engine.AddMockSeg(0, 0, 0, 0, ws, LgEndSegmentType.kestNoMore); root.Layout(layoutArgs); Assert.AreEqual(1, para.Lines.Count); Assert.IsTrue(root.Height > 0); }
public void RowClippedPaint() { var styles = new AssembledStyles(); var box1 = new FgBlockBox(styles, Color.Red, 36000, 72000); var box2 = new FgBlockBox(styles, Color.Blue, 18000, 108000); var box3 = new FgBlockBox(styles, Color.Orange, 18000, 72000); var box4 = new FgBlockBox(styles, Color.Orange, 18000, 72000); var widths = new FixedColumnWidths(new[] { 34, 67, 99, 46 }); var row1 = new RowBox(styles, widths, false); row1.AddBox(box1); row1.AddBox(box2); row1.AddBox(box3); row1.AddBox(box4); RootBox root = new RootBox(styles); root.AddBox(row1); LayoutInfo layoutArgs = MakeLayoutInfo(); root.Layout(layoutArgs); var rect1 = new Rectangle(0, 0, 48, 96); var rect2 = new Rectangle(0, 0, 24, 144); rect2.Offset(rect1.Right, 0); var rect3 = new Rectangle(0, 0, 24, 96); rect3.Offset(rect2.Right, 0); var rect4 = new Rectangle(0, 0, 24, 96); rect4.Offset(rect3.Right, 0); var paintRects = new[] { rect1, rect2, rect3, rect4 }; VerifyPaint(root, new Rectangle(-1000, -1000, 2000, 2000), 0, 0, paintRects); // Clipping off the left part, but not the whole, of a box does not prevent drawing it. VerifyPaint(root, new Rectangle(10, -1000, -10 + rect4.Right - 10, 2000), 0, 0, paintRects); // Even clipping all but one pixel does not prevent drawing. VerifyPaint(root, new Rectangle(47, -1000, -47 + rect3.Right + 1, 2000), 0, 0, paintRects); // However if we clip a bit more we should draw less var middleTwo = new[] { rect2, rect3 }; VerifyPaint(root, new Rectangle(48, -1000, -48 + rect3.Right - 2, 2000), 0, 0, middleTwo); // If the clip covers just a bit of the first box we paint just that. var firstOne = new[] { rect1 }; VerifyPaint(root, new Rectangle(-1000, -1000, 1000 + 10, 2000), 0, 0, firstOne); // If the clip covers just a bit of the last box we paint just that. var lastOne = new[] { rect4 }; VerifyPaint(root, new Rectangle(rect4.Right - 2, -1000, 1000, 2000), 0, 0, lastOne); // If the clip is entirely above the pile we draw nothing. VerifyPaint(root, new Rectangle(-1000, -1000, 990, 2000), 0, 0, null); // Likewise if entirely below. VerifyPaint(root, new Rectangle(rect4.Right + 10, -1000, 10, 2000), 0, 0, null); // Now try with simulated scrolling. Use a normal clip rectangle, but pretend the first two // and a bit boxes are scrolled off. var offset = rect2.Right + 10; var rect3Offset = rect3; rect3Offset.Offset(-offset, 0); var rect4Offset = rect4; rect4Offset.Offset(-offset, 0); var lastTwoOffset = new[] { rect3Offset, rect4Offset }; VerifyPaint(root, new Rectangle(0, -1000, 200, 2000), offset, 0, lastTwoOffset); }
private void CheckMultipleRuns(RootBox root) { Assert.That(root.FirstBox, Is.TypeOf(typeof(ParaBox))); Assert.That(root.FirstBox, Is.EqualTo(root.LastBox), "one box with two literals"); var para = (ParaBox) root.FirstBox; Assert.That(para.Source.ClientRuns, Has.Count.EqualTo(2)); var run1 = (StringClientRun) para.Source.ClientRuns[0]; Assert.That(run1.Style.FontWeight, Is.EqualTo((int)VwFontWeight.kvfwBold)); Assert.That(run1.Style.FontItalic, Is.True); Assert.That(run1.Style.ForeColor.ToArgb(), Is.EqualTo(Color.Red.ToArgb())); if (run1.Hookup != null) Assert.That(run1.Hookup.ClientRunIndex, Is.EqualTo(0)); var run2 = (StringClientRun)para.Source.ClientRuns[1]; Assert.That(run2.Style.BackColor.ToArgb(), Is.EqualTo(Color.Yellow.ToArgb())); Assert.That(run2.Style.ForeColor.ToArgb(), Is.EqualTo(Color.Blue.ToArgb())); if (run2.Hookup != null) Assert.That(run2.Hookup.ClientRunIndex, Is.EqualTo(1)); // Make sure everything didn't get applied to both runs Assert.That(run1.Style.BackColor.ToArgb(), Is.Not.EqualTo(Color.Blue.ToArgb())); Assert.That(run2.Style.FontItalic, Is.False); }
public void NestedRowsLayout() { var styles = new AssembledStyles(); var box1 = new LayoutInfoRecorderBox(styles, Color.Red, 72000, 36000); var box2 = new LayoutInfoRecorderBox(styles, Color.Blue, 108000, 18000); var box3 = new LayoutInfoRecorderBox(styles, Color.Orange, 72000, 18000); var box4 = new LayoutInfoRecorderBox(styles, Color.Orange, 72000, 18000); var widths = new FixedColumnWidths(new[] {34, 67, 99}); // pass widths to RowBox constructor var row1 = new RowBox(styles, widths, false); var row2 = new RowBox(styles, widths, false); row1.AddBox(box1); row1.AddBox(box2); row2.AddBox(box3); row2.AddBox(box4); RootBox root = new RootBox(styles); root.AddBox(row1); root.AddBox(row2); LayoutInfo layoutArgs = MakeLayoutInfo(); root.Layout(layoutArgs); Assert.That(box1.LastLayoutInfo.MaxWidth, Is.EqualTo(34)); Assert.That(box1.Height, Is.EqualTo(48)); Assert.That(box2.Height, Is.EqualTo(24)); Assert.That(box3.Height, Is.EqualTo(24)); Assert.That(box4.Height, Is.EqualTo(24)); Assert.That(root.Height, Is.EqualTo(48 + 24)); Assert.That(box1.Left, Is.EqualTo(0)); Assert.That(box2.Left, Is.EqualTo(96)); Assert.That(box3.Left, Is.EqualTo(0)); Assert.That(box4.Left, Is.EqualTo(96)); Assert.That(row1.Top, Is.EqualTo(0)); Assert.That(box1.Top, Is.EqualTo(0)); Assert.That(box2.Top, Is.EqualTo(0)); Assert.That(row2.Top, Is.EqualTo(48)); Assert.That(box3.Top, Is.EqualTo(0)); Assert.That(box4.Top, Is.EqualTo(0)); Assert.That(box1.Width, Is.EqualTo(96)); Assert.That(box2.Width, Is.EqualTo(144)); Assert.That(box3.Width, Is.EqualTo(96)); Assert.That(box4.Width, Is.EqualTo(96)); Assert.That(root.Width, Is.EqualTo(96 + 144)); // Now try changing the size of a block. MockSite site = new MockSite(); root.Site = site; PaintTransform ptrans = new PaintTransform(2, 4, 96, 96, 0, 10, 120, 128); site.m_transform = ptrans; site.m_vwGraphics = m_gm.VwGraphics; box2.UpdateSize(144000, 36000); Assert.That(box2.Width, Is.EqualTo(96 * 2)); Assert.That(box2.Height, Is.EqualTo(48)); Assert.That(row1.Height, Is.EqualTo(48)); Assert.That(root.Height, Is.EqualTo(72)); Assert.That(root.Width, Is.EqualTo(96 * 3)); // Since it got both wider and higher, we should invalidate at least the whole current size. var bigInvalidate = root.InvalidateRect; Assert.That(site.RectsInvalidatedInRoot, Has.Member(bigInvalidate)); site.RectsInvalidated.Clear(); box2.UpdateSize(108000, 18000); Assert.That(root.Height, Is.EqualTo(48 + 24)); // unchanged this time Assert.That(root.Width, Is.EqualTo(96 + 144)); // narrower box2 still determines it // Got narrower, at least the whole old invalidate rectangle should be invalidated. Assert.That(site.RectsInvalidatedInRoot, Has.Member(bigInvalidate)); site.RectsInvalidated.Clear(); box2.UpdateSize(72000, 18000); Assert.That(root.Height, Is.EqualTo(48 + 24)); // unchanged this time Assert.That(root.Width, Is.EqualTo(144 + 48)); // new smaller value // It got thinner. We want an optimized invalidate rectangle that does not // include the left boxes. But it must include the space at the right that the root box used to occupy. // There are other possible implementations, but currently, we expect the old rectangle of box2 // to be invalidated (it's in the fixmap so its own Relayout does this); // the shrinkage area at the right of row2; // and the area computed because row2 moved. //VerifyExpectedRectangle(site.RectsInvalidatedInRoot, 0, 48, 48, 144); // old box2 //VerifyExpectedRectangle(site.RectsInvalidatedInRoot, 0, 48 + 24, 144, 24); // shrinkage of row1 // This is from the new left of div2 to its old right (old right was 48 + 48 + 24 + 24) //VerifyExpectedRectangle(site.RectsInvalidatedInRoot, 0, 48 + 24, 144, 48 + 24); site.RectsInvalidated.Clear(); box2.UpdateSize(144000, 18000); Assert.That(root.Height, Is.EqualTo(48 + 24)); // unchanged this time Assert.That(root.Width, Is.EqualTo(144 + 144)); // new larger value // It got wider. We want an optimized invalidate rectangle that does not // include the left boxes. But it must include the space at the right where the root box grew. // There are other possible implementations, but currently, we expect the old rectangle of box2 // to be invalidated (it returns true from Relayout); // the growth area at the right of div2; // and the area computed because div2 moved. //VerifyExpectedRectangle(site.RectsInvalidatedInRoot, 0, 48, 144, 96); // new box2 //VerifyExpectedRectangle(site.RectsInvalidatedInRoot, 0, 48 + 24, 144, 96 - 24); // new part of div1 occupied by box2 // This is from the old left of div2 to its new right (48 + 96 + 24 + 24) //VerifyExpectedRectangle(site.RectsInvalidatedInRoot, 0, 48 + 24, 144, 96 + 24); }
/// <summary> /// This setup method for para builder is also useful for testing stuff related to the paragraph itself. /// For example, we take advantage of it for testing backspace at start of client run. /// </summary> internal static RootBox MakeTestParaThreeStrings(IVwGraphics vg, MockBreakOption breakOption, out ParaBox para) { var styles = new AssembledStyles().WithWs(s_simpleStringWs); var styles2 = new AssembledStyles().WithWs(s_secondGroupWs); string contents1 = AssembleStrings(s_firstGroupWords); string contents2 = AssembleStrings(s_secondGroupWords); string contents3 = AssembleStrings(s_thirdGroupWords); var clientRuns = new List<IClientRun>(); clientRuns.Add(new StringClientRun(contents1, styles)); clientRuns.Add(new StringClientRun(contents2, styles2)); clientRuns.Add(new StringClientRun(contents3, styles)); var source = new TextSource(clientRuns, null); para = new ParaBox(styles, source); var root = new RootBox(styles); root.AddBox(para); var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, vg); int totalLength = contents1.Length + contents2.Length + contents3.Length; // Arrange the following line breaks. // First the builder will ask to break the whole string, it puts the first three words on a line and indicates it is full. SetupMockEngineForThreeStringsPara(s_firstGroupWords, s_secondGroupWords, s_thirdGroupWords, layoutArgs); root.Layout(layoutArgs); return root; }