示例#1
0
		public void Select()
		{
			var styles = new AssembledStyles();
			var root = new RootBoxFdo(styles);
			var mock1 = new MockData1(23, 23);
			mock1.SimpleThree = "new old contents";
			var engine = new FakeRenderEngine() { Ws = 23, SegmentHeight = 13 };
			var factory = new FakeRendererFactory();
			factory.SetRenderer(23, engine);
			root.Builder.Show(Display.Of(() => mock1.SimpleThree, 23));
			var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			PaintTransform ptrans = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96);
			MockSite site = new MockSite();
			site.m_transform = ptrans;
			site.m_vwGraphics = m_gm.VwGraphics;
			root.Site = site;

			int x = FakeRenderEngine.SimulatedWidth("new ") + 2;
			var location = new Point(x, 8);
			EventArgs e = new EventArgs();
			MouseEventArgs m = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);

			root.OnMouseDown(m, Keys.None, site.m_vwGraphics, site.m_transform);
			root.OnDoubleClick(e);
			Assert.That(!root.Selection.IsInsertionPoint, "Should be ranged selection");
			Assert.That((root.Selection as RangeSelection).SelectedText(), Is.EqualTo("old "));

			mock1.SimpleThree = "new old:contents";
			x = FakeRenderEngine.SimulatedWidth("new o") + 2;
			location = new Point(x, 8);
			m = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);
			root.OnMouseDown(m, Keys.None, site.m_vwGraphics, site.m_transform);
			root.OnMouseClick(m, Keys.None, site.m_vwGraphics, site.m_transform);
			root.OnDoubleClick(e);
			Assert.That(!root.Selection.IsInsertionPoint, "Should be ranged selection");
			Assert.That((root.Selection as RangeSelection).SelectedText(), Is.EqualTo("old"));

			mock1.SimpleThree = "new(old contents";
			x = FakeRenderEngine.SimulatedWidth("new ol") + 2;
			location = new Point(x, 8);
			m = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);
			root.OnMouseDown(m, Keys.None, site.m_vwGraphics, site.m_transform);
			root.OnMouseClick(m, Keys.None, site.m_vwGraphics, site.m_transform);
			root.OnDoubleClick(e);
			Assert.That(!root.Selection.IsInsertionPoint, "Should be ranged selection");
			Assert.That((root.Selection as RangeSelection).SelectedText(), Is.EqualTo("old "));

			mock1.SimpleThree = "newo1dcontents";
			x = FakeRenderEngine.SimulatedWidth("new o1d") + 2;
			location = new Point(x, 8);
			m = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);
			root.OnMouseDown(m, Keys.None, site.m_vwGraphics, site.m_transform);
			root.OnMouseClick(m, Keys.None, site.m_vwGraphics, site.m_transform);
			root.OnDoubleClick(e);
			Assert.That(!root.Selection.IsInsertionPoint, "Should be ranged selection");
			Assert.That((root.Selection as RangeSelection).SelectedText(), Is.EqualTo("newo1dcontents"));
		}
示例#2
0
		public void DragStartsOnMoveInSelection()
		{
			string contents = "This is the day.";
			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 source = new TextSource(clientRuns, null);
			var para = new ParaBox(styles, source);
			var extraBox = new BlockBox(styles, Color.Red, 50, 72000); // tall, narrow spacer at top
			var root = new RootBoxFdo(styles);
			root.AddBox(extraBox);
			root.AddBox(para);
			var layoutArgs = MakeLayoutInfo(Int32.MaxValue/2, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			Assert.That(root.Height, Is.EqualTo(96 + 13));
			Assert.That(root.Width, Is.EqualTo(FakeRenderEngine.SimulatedWidth(contents)));

			var ip1 = run.SelectAt(para, 5, false);
			var ip2 = run.SelectAt(para, 7, true);
			var range = new RangeSelection(ip1, ip2);
			range.Install();
			PaintTransform ptrans = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96);
			var sbox = para.FirstBox as StringBox;
			MockSite site = new MockSite();
			site.m_transform = ptrans;
			site.m_vwGraphics = m_gm.VwGraphics;
			root.Site = site;
			int indent = FakeRenderEngine.SimulatedWidth("This ");
			root.OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, indent + 5, 100, 0), Keys.None, m_gm.VwGraphics, ptrans);
			root.OnMouseMove(new MouseEventArgs(MouseButtons.Left, 1, indent + 5, 100, 0), Keys.None, m_gm.VwGraphics, ptrans);
			Assert.That(GetStringDropData(site), Is.EqualTo("is"));
			Assert.That(site.LastDoDragDropArgs.AllowedEffects, Is.EqualTo(DragDropEffects.Copy),
				"editing not possible in this paragraph, we can only copy");
			Assert.That(root.Selection, Is.EqualTo(range), "selection should not be changed by drag drop");
			site.LastDoDragDropArgs = null;
			root.OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, 3, 100, 0), Keys.None, m_gm.VwGraphics, ptrans);
			Assert.That(site.LastDoDragDropArgs, Is.Null, "click outside selection should not initiate drag");

			// Tack on an extra check that a read-only view does not handle drop.
			var dataObj = new DataObject(DataFormats.StringFormat, "new ");
			var dragArgs = new DragEventArgs(dataObj, (int)DragDropKeyStates.ControlKey, 10, 8,
				DragDropEffects.Copy | DragDropEffects.Move,
				DragDropEffects.None);
			root.OnDragEnter(dragArgs, new Point(14, 8), m_gm.VwGraphics, ptrans);
			Assert.That(dragArgs.Effect, Is.EqualTo(DragDropEffects.None));
			Assert.That(root.DragState, Is.EqualTo(WindowDragState.DraggingHere));
		}
示例#3
0
        public void SendingInsertLineBreak()
        {
            var owner  = new MockData1(55, 77);
            var child1 = new MockData1(55, 77);
            var child2 = new MockData1(55, 77);

            owner.InsertIntoObjSeq1(0, child1);
            owner.InsertIntoObjSeq1(1, child2);
            child1.SimpleThree = "Hello World. ";
            child2.SimpleThree = "This is a test.";

            var styles     = new AssembledStyles();
            var root       = new RootBoxFdo(styles);
            var layoutInfo = HookupTests.MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);

            SetupFakeRootSite(root);
            var po = new MockSendParagraphOperations();

            root.Builder.Show(Display.Of(() => owner.ObjSeq1).Using((bldr, md) => bldr.AddString(() => md.SimpleThree, 55))
                              .EditParagraphsUsing(po));
            Assert.That(po.Hookup, Is.Not.Null);
            root.Layout(layoutInfo);
            var para = (ParaBox)root.FirstBox;
            var ip   = para.SelectAtEnd();

            ip.InsertLineBreak();
            Assert.That(po.InsertFollowingParagraphIp, Is.EqualTo(ip), "should have called InsertFollowingParagraph with right IP");
            Assert.That(po.InsertFollowingParagraphActionPerformed, Is.False, "make selection action performed too soon");
            ((MockSite)root.Site).DoPendingAfterNotificationTasks();
            Assert.That(po.InsertFollowingParagraphActionPerformed, Is.True, "make selection action not performed or not saved");

            po.InsertFollowingParagraphIp = null;
            ip = para.SelectAtStart();
            ip.InsertLineBreak();
            Assert.That(po.InsertFollowingParagraphIp, Is.Null);
            Assert.That(po.InsertPrecedingParagraphIp, Is.EqualTo(ip), "should have called InsertPrecedingParagraph with right IP");
            Assert.That(po.InsertPrecedingParagraphActionPerformed, Is.False, "make selection action performed too soon");
            ((MockSite)root.Site).DoPendingAfterNotificationTasks();
            Assert.That(po.InsertPrecedingParagraphActionPerformed, Is.True, "make selection action not performed or not saved");
            // Todo: test sending InsertLineBreak when selection mid-paragraph, also empty paragraph.
        }
示例#4
0
        public void DrawIPMultiRunPara()
        {
            var     styles = new AssembledStyles();
            RootBox root   = new RootBoxFdo(styles);

            root.Builder.Show(Paragraph.Containing(
                                  Display.Of("first"), Display.Of("second"), Display.Of("third")));
            SetupFakeRootSite(root);
            var layoutInfo = HookupTests.MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);

            root.Layout(layoutInfo);
            InsertionPoint ip = root.SelectAtEnd();

            ip.Install();
            var para = (ParaBox)root.FirstBox;

            Assert.AreEqual(ip, root.Selection);
            Assert.AreEqual(para, ip.Para, "IP should know about the paragraph it is in");
            Assert.AreEqual("third".Length, ip.StringPosition, "IP position is relative to run");
            Assert.AreEqual(true, ip.AssociatePrevious, "selection at end should always associate previous in non-empty para");


            StringBox sbox = para.FirstBox as StringBox;

            Assert.That(sbox, Is.EqualTo(para.LastBox), "uniform text in infinite width should make one string box");
            var seg = sbox.Segment as FakeSegment;

            Assert.IsNotNull(seg);
            PaintTransform ptrans = new PaintTransform(2, 4, 96, 100, 0, -10, 120, 128);

            ip.Draw(m_gm.VwGraphics, ptrans);
            VerifySegmentDrawing(para, sbox, seg.LastDrawIpCall, -4);

            seg.NextPosIpResult             = new MockSegment.PositionsOfIpResults();
            seg.NextPosIpResult.RectPrimary = new Rect(5, 6, 7, 9);
            seg.NextPosIpResult.PrimaryHere = true;
            Rectangle selRect = ip.GetSelectionLocation(m_gm.VwGraphics, ptrans);

            VerifySelLocation(para, sbox, seg.LastPosIpCall, -4);
            Assert.AreEqual(new Rectangle(5, 6, 2, 3), selRect);
        }
示例#5
0
        public void ParaSequenceWithInitialContent()
        {
            var owner  = new MockData1(55, 77);
            var child1 = new MockData1(55, 77);
            var child2 = new MockData1(55, 77);

            owner.InsertIntoObjSeq1(0, child1);
            owner.InsertIntoObjSeq1(1, child2);
            child1.SimpleThree = "Hello World. ";
            child2.SimpleThree = "This is a test.";

            var styles     = new AssembledStyles();
            var root       = new RootBoxFdo(styles);
            var layoutInfo = MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);

            SetupFakeRootSite(root);
            root.Builder.Show(Display.Of(() => owner.ObjSeq1).Using((bldr, md) => bldr.AddString(() => md.SimpleThree, 55)));
            root.Layout(layoutInfo);
            // Two children produces two paragraphs.
            Assert.That(root.FirstBox, Is.AssignableTo(typeof(ParaBox)));
            Assert.That(root.FirstBox.Next, Is.AssignableTo(typeof(ParaBox)));
            Assert.That(root.FirstBox.Next.Next, Is.Null);
        }
示例#6
0
		public void BidiBacktracking()
		{
			var styles = new AssembledStyles();
			var layoutInfo = MakeLayoutInfo();

			var engine = new FakeRenderEngine() {Ws = 34, SegmentHeight = 13};
			var factory = new FakeRendererFactory();
			factory.SetRenderer(34, engine);
			var engine2 = new FakeRenderEngine() {Ws = 35, SegmentHeight = 13};
			factory.SetRenderer(35, engine2);
			engine2.RightToLeft = true;

			// This first test doesn't strictly require backtracking; it is an example of a similar
			// case where all the second client run fits, nothing of the following one fits, but
			// there is a satisfactory break at the end of the last thing that fit.
			// But, the space at the 'end' of "some mixed" will need to be moved to the end so it can 'disappear',
			// so it should become a separate segment.
			// That is, we should get something like
			// this is dexim emos_
			// text
			// Where the underline stands for the space after "some mixed" which is moved to the end of the line.
			var root = new RootBoxFdo(styles);
			root.Builder.Show(Paragraph.Containing(Display.Of("this is ", 34),
												   Display.Of("some mixed ", 35), Display.Of("text", 34)));
			int maxWidth = FakeRenderEngine.SimulatedWidth("this is some mixed t");
			var layoutArgs = MakeLayoutInfo(maxWidth, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			var para = (ParaBox) root.FirstBox;
			var secondChild = (StringBox) para.FirstBox.Next;
			Assert.That(secondChild.Text, Is.EqualTo("some mixed"));
			var thirdChild = (StringBox)secondChild.Next;
			Assert.That(thirdChild.Text, Is.EqualTo(" "));
			Assert.That(thirdChild.Top, Is.EqualTo(para.FirstBox.Top));

			// True backtracking: the second client run fits entirely, but nothing of the following text.
			// We must go back and find the break in the middle of that second run.
			root = new RootBoxFdo(styles);
			root.Builder.Show(Paragraph.Containing(Display.Of("this is ", 34),
												   Display.Of("some mixed", 35), Display.Of("text", 34)));
			maxWidth = FakeRenderEngine.SimulatedWidth("this is some mixedte");
			layoutArgs = MakeLayoutInfo(maxWidth, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			para = (ParaBox)root.FirstBox;
			secondChild = (StringBox)para.FirstBox.Next;
			Assert.That(secondChild.Text, Is.EqualTo("some"));
			thirdChild = (StringBox)secondChild.Next;
			Assert.That(thirdChild.Text, Is.EqualTo(" "));
			Assert.That(thirdChild.Top, Is.EqualTo(para.FirstBox.Top));
			var fourthChild = (StringBox)thirdChild.Next;
			Assert.That(fourthChild.Text, Is.EqualTo("mixed"));
			Assert.That(fourthChild.Top, Is.GreaterThan(thirdChild.Top));
			var fifthChild = (StringBox)fourthChild.Next;
			Assert.That(fifthChild.Text, Is.EqualTo("text"));
			Assert.That(fifthChild.Top, Is.EqualTo(fourthChild.Top));
		}
示例#7
0
		public void RtlPara()
		{
			var styles = new AssembledStyles();
			var layoutInfo = MakeLayoutInfo();
			var root = new RootBoxFdo(styles);

			var engine = new FakeRenderEngine() { Ws = 34, SegmentHeight = 13 };
			var factory = new FakeRendererFactory();
			engine.RightToLeft = true;
			factory.SetRenderer(34, engine);
			var engine2 = new FakeRenderEngine() { Ws = 35, SegmentHeight = 13 };
			engine2.RightToLeft = true;
			factory.SetRenderer(35, engine);

			root.Builder.Show(Paragraph.Containing(Display.Of("this is ", 34),
				Display.Of("mixed ", 35), Display.Of("text", 34)).RightToLeft(true));
			var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			var para = (ParaBox) root.FirstBox;
			int left1 = para.FirstBox.Left;
			int left2 = para.FirstBox.Next.Left;
			int left3 = para.FirstBox.Next.Next.Left;
			Assert.That(left3, Is.LessThan(left2));
			Assert.That(left2, Is.LessThan(left1));
		}
示例#8
0
        public void DragCopyRtf()
        {
            var stylesheet  = new MockStylesheet();
            var styleFirst  = stylesheet.AddStyle("first", false);
            var styleSecond = stylesheet.AddStyle("second", false);
            var propsTrue   = new MockStyleProp <bool>()
            {
                Value = true, ValueIsSet = true
            };
            var charInfo = new MockCharStyleInfo();

            styleFirst.DefaultCharacterStyleInfo = charInfo;
            charInfo.Bold = propsTrue;
            // Todo: make styleSecond have pretty much everything else.
            var charInfo2 = new MockCharStyleInfo();

            styleSecond.DefaultCharacterStyleInfo = charInfo2;
            charInfo2.FontColor      = MakeColorProp(Color.Red);
            charInfo2.BackColor      = MakeColorProp(Color.Yellow);
            charInfo2.UnderlineColor = MakeColorProp(Color.Green);
            charInfo2.Italic         = propsTrue;
            charInfo2.FontName       = new MockStyleProp <string>()
            {
                Value = "Arial", ValueIsSet = true
            };

            var styles = new AssembledStyles(stylesheet);
            var root   = new RootBoxFdo(styles);
            var mock1  = new MockData1(23, 23);

            mock1.SimpleThree = "This is";
            var mock2 = new MockData1(23, 23);

            mock2.SimpleThree = " the day";
            var mock3 = new MockData1(23, 23);

            mock3.SimpleThree = " that the";
            var engine = new FakeRenderEngine()
            {
                Ws = 23, SegmentHeight = 13
            };
            var factory = new FakeRendererFactory();
            var wsf     = new MockWsf();

            engine.WritingSystemFactory = wsf;
            var wsEngine = wsf.MakeMockEngine(23, "en", engine);

            factory.SetRenderer(23, engine);
            root.Builder.Show(
                Paragraph.Containing(
                    Display.Of(() => mock1.SimpleThree, 23).Style("first"),
                    Display.Of(() => mock2.SimpleThree, 23).Style("second"),
                    Display.Of(() => mock3.SimpleThree, 23).Style("first")
                    ));
            var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);

            root.Layout(layoutArgs);
            PaintTransform ptrans = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96);
            MockSite       site   = new MockSite();

            site.m_transform  = ptrans;
            site.m_vwGraphics = m_gm.VwGraphics;
            root.Site         = site;

            SelectionBuilder.In(root).Offset("This ".Length).To.Offset("This is the day that".Length).Install();
            int indent = FakeRenderEngine.SimulatedWidth("This ");

            root.OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, indent + 5, 4, 0), Keys.None, m_gm.VwGraphics, ptrans);
            root.OnMouseMove(new MouseEventArgs(MouseButtons.Left, 1, indent + 5, 4, 0), Keys.None, m_gm.VwGraphics, ptrans);
            Assert.That(GetStringDropData(site), Is.EqualTo("is the day that"));
            // The order of the font and colors in the color table is arbitrary. This happens to be what the code does now. For some reason
            // Color.Green has green only 128.
            // The order of items in the definition of a style is arbitrary.
            // We're not doing anything yet for background color. \highlightN can specify background color for a character run,
            // but it can't be part of a style definition.
            Assert.That(GetRtfDropData(site), Is.EqualTo(
                            RangeSelection.RtfPrefix
                            + @"{\fonttbl{\f0 MockFont;}{\f1 Arial;}}"
                            + @"{\colortbl ;\red0\green0\blue0;\red255\green255\blue255;\red255\green0\blue0;\red255\green255\blue0;\red0\green128\blue0;}"
                            + @"{\stylesheet{\*\cs1\b\additive first;\*\cs2\i\f1\cf3\ulc5\additive second;}}"
                            + RangeSelection.RtfDataPrefix
                            + @"{\*\cs1\b is}{\*\cs2\i\f1\cf3\ulc5\highlight4  the day}{\*\cs1\b  that\par}"
                            + @"}"));

            // Todo: handle styles that depend on WS
            // Todo: handle more than two runs
            // Todo: handle runs where actual formatting differs from style-specified formatting
            // Todo: handle multiple paragraphs
            // Todo: handle paragraph styles
        }
示例#9
0
        public void BasicDragMove()
        {
            var styles = new AssembledStyles();
            var root   = new RootBoxFdo(styles);
            var mock1  = new MockData1(23, 23);

            mock1.SimpleThree = "This is the day";
            var engine = new FakeRenderEngine()
            {
                Ws = 23, SegmentHeight = 13
            };
            var factory = new FakeRendererFactory();

            factory.SetRenderer(23, engine);
            root.Builder.Show(Display.Of(() => mock1.SimpleThree, 23));
            var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);

            root.Layout(layoutArgs);
            PaintTransform ptrans = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96);
            MockSite       site   = new MockSite();

            site.m_transform  = ptrans;
            site.m_vwGraphics = m_gm.VwGraphics;
            root.Site         = site;

            SelectionBuilder.In(root).Offset("This ".Length).To.Offset("This is ".Length).Install();

            var dataObj  = new DataObject(DataFormats.StringFormat, "is ");
            int x        = FakeRenderEngine.SimulatedWidth("This is the ") + 2;
            var location = new Point(x, 8);

            // A drag to where we can drop, allowing both copy and move, no keys held
            var dragArgs = new DragEventArgs(dataObj, (int)DragDropKeyStates.None, 200, 300,
                                             DragDropEffects.Copy | DragDropEffects.Move,
                                             DragDropEffects.None);

            root.OnDragEnter(dragArgs, location, m_gm.VwGraphics, ptrans);
            Assert.That(dragArgs.Effect, Is.EqualTo(DragDropEffects.Move));
            Assert.That(root.DragState, Is.EqualTo(WindowDragState.DraggingHere));

            var qcdArgs = new QueryContinueDragEventArgs((int)DragDropKeyStates.None, false, DragAction.Drop);

            root.OnQueryContinueDrag(qcdArgs);
            Assert.That(root.DragState, Is.EqualTo(WindowDragState.InternalMove));
            root.OnDragLeave();
            Assert.That(root.DragState, Is.EqualTo(WindowDragState.InternalMove), "DragLeave should not clear InternalMove");

            root.OnDragDrop(dragArgs, location, m_gm.VwGraphics, ptrans);
            Assert.That(mock1.SimpleThree, Is.EqualTo("This the is day"));
            Assert.That(root.DragState, Is.EqualTo(WindowDragState.None));

            // Now let's drag the 'is' out to another window.
            SelectionBuilder.In(root).Offset("This the ".Length).To.Offset("This the is ".Length).Install();
            qcdArgs = new QueryContinueDragEventArgs((int)DragDropKeyStates.None, false, DragAction.Drop);
            root.OnQueryContinueDrag(qcdArgs);
            Assert.That(root.DragState, Is.EqualTo(WindowDragState.None),
                        "We should only set InternalMove if this window is the destination");
            Assert.That(mock1.SimpleThree, Is.EqualTo("This the day"));

            // Check that we can't drag inside our own selection.
            SelectionBuilder.In(root).Offset("This ".Length).To.Offset("This the".Length).Install();
            x        = FakeRenderEngine.SimulatedWidth("This t") + 2;
            location = new Point(x, 8);
            dragArgs = new DragEventArgs(dataObj, (int)DragDropKeyStates.None, 200, 300,
                                         DragDropEffects.Copy | DragDropEffects.Move,
                                         DragDropEffects.None);
            root.DragState = WindowDragState.InternalMove;
            root.OnDragDrop(dragArgs, location, m_gm.VwGraphics, ptrans);
            Assert.That(dragArgs.Effect, Is.EqualTo(DragDropEffects.None));
            Assert.That(mock1.SimpleThree, Is.EqualTo("This the day"));
        }
示例#10
0
        public void SubParaSequenceTest()
        {
            var owner      = new MockData1(55, 77);
            var styles     = new AssembledStyles();
            var root       = new RootBoxFdo(styles);
            var layoutInfo = MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);

            SetupFakeRootSite(root);
            var      engine = layoutInfo.RendererFactory.GetRenderer(55, m_gm.VwGraphics) as FakeRenderEngine;
            MockSite site   = new MockSite();

            root.Site = site;
            PaintTransform ptrans = new PaintTransform(2, 4, 96, 100, 0, 10, 120, 128);

            site.m_transform  = ptrans;
            site.m_vwGraphics = m_gm.VwGraphics;
            root.Builder.Show(Paragraph.Containing(Display.Of(() => owner.ObjSeq1).Using((bldr, md) => bldr.AddString(() => md.SimpleThree, 55))));
            root.Layout(layoutInfo);
            VerifyParagraphs(root, new [] { "" });

            //// Insert the first item into owner.ObjSeq1 and check all the right connections appear
            var child1       = new MockData1(55, 77);
            var child1String = "Hello world, this is a wide string";

            child1.SimpleThree = child1String;
            owner.InsertIntoObjSeq1(0, child1);
            VerifyParagraphs(root, new string[] { child1String });
            Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(1), "Builder.AddString should set up a hookup for the string");
            int invalidateWidth     = FakeRenderEngine.SimulatedWidth(child1String) + 2 * RootBox.InvalidateMargin;
            var expectedInvalidate1 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
                                                    invalidateWidth,
                                                    engine.SegmentHeight + 2 * RootBox.InvalidateMargin);

            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate1));

            // Insert a second item and check again.
            var child2 = new MockData1(55, 77);

            child2.SimpleThree = "Another world";
            invalidateWidth   += FakeRenderEngine.SimulatedWidth("Another world");
            site.RectsInvalidated.Clear();
            owner.InsertIntoObjSeq1(1, child2);
            VerifyParagraphs(root, new string[] { child1String + "Another world" });
            Assert.That(child2.SimpleThreeHookupCount, Is.EqualTo(1), "Builder.AddString should set up a hookup for the string");
            var expectedInvalidate2 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
                                                    invalidateWidth,
                                                    engine.SegmentHeight + 2 * RootBox.InvalidateMargin);

            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate2));

            // Insert a third item between the first two.
            var child3 = new MockData1(55, 77);

            child3.SimpleThree = "Inserted world";
            invalidateWidth   += FakeRenderEngine.SimulatedWidth("Inserted world");
            site.RectsInvalidated.Clear();
            owner.InsertIntoObjSeq1(1, child3);
            VerifyParagraphs(root, new string[] { child1String + "Inserted world" + "Another world" });
            var expectedInvalidate3 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
                                                    invalidateWidth,
                                                    engine.SegmentHeight + 2 * RootBox.InvalidateMargin);

            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate3));

            // Insert a fourth item at the start.
            var child4 = new MockData1(55, 77);

            child4.SimpleThree = "Beginning of world";
            invalidateWidth   += FakeRenderEngine.SimulatedWidth("Beginning of world");
            site.RectsInvalidated.Clear();
            owner.InsertIntoObjSeq1(0, child4);
            VerifyParagraphs(root, new string[] { "Beginning of world" + child1String + "Inserted world" + "Another world" });
            var expectedInvalidate4 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
                                                    invalidateWidth,
                                                    engine.SegmentHeight + 2 * RootBox.InvalidateMargin);

            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate4));

            // Delete the first item.
            site.RectsInvalidated.Clear();
            owner.RemoveAtObjSeq1(0);
            VerifyParagraphs(root, new string[] { child1String + "Inserted world" + "Another world" });
            Assert.That(child4.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for a deleted object should be disposed.");
            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate4));

            // Delete a middle item.
            site.RectsInvalidated.Clear();
            owner.RemoveAtObjSeq1(1);
            VerifyParagraphs(root, new string[] { child1String + "Another world" });
            Assert.That(child3.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for a deleted object should be disposed.");
            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate3));

            // Delete the last item.
            site.RectsInvalidated.Clear();
            owner.RemoveAtObjSeq1(1);
            VerifyParagraphs(root, new string[] { child1String });
            Assert.That(child2.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for a deleted object should be disposed.");
            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate2));

            // Delete the only remaining item.
            site.RectsInvalidated.Clear();
            owner.RemoveAtObjSeq1(0);
            VerifyParagraphs(root, new string[] { "" });
            Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for a deleted object should be disposed.");
            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate1));

            // Eventually add some operations that allow inserting and deleting multiple items.

            // We also need to be able to insert two or more object sequences into the same containing box.
            // That's probably another test, perhaps a view of the root where for each data item,
            // we insert its subitems, then for those insert paragraphs.
            // Let's assume there's always one top-level hookup for the root.
        }
示例#11
0
		public void DrawingBordersandBackground()
		{
			var root = new RootBoxFdo(new AssembledStyles());
			SetupFakeRootSite(root);
			var layoutInfo = HookupTests.MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);
			root.RendererFactory = layoutInfo.RendererFactory;
			var mock1 = new MockData1() {SimpleThree = "This is the first paragraph."};
			// The length of the second paragraph is found by experiment to be enough so that
			// despite its lacking borders it also breaks into 2 lines in the second step.
			var mock2 = new MockData1() {SimpleThree = "Here is another paragraph. It needs to be a bit longer."};
			root.Builder.Show(
				Paragraph.Containing(Display.Of(() => mock1.SimpleThree)).BackColor(Color.Red)
					.Margins(1.Points(), 2.Points(), 3.Points(), 4.Points())
					.Borders(5.Points(), 6.Points(), 7.Points(), 8.Points(), Color.Blue)
					.Pads(9.Points(), 10.Points(), 11.Points(), 12.Points()),
				Paragraph.Containing(Display.Of(() => mock2.SimpleThree)).BackColor(Color.Yellow)
					.Margins(1.Points(), 2.Points(), 3.Points(), 4.Points()));
			root.Layout(layoutInfo);
			// We want to keep track of the sequence of paint operations in all three segments.
			var drawActions = new List<object>();
			var vg = new MockGraphics();
			vg.DrawActions = drawActions;
			var para1 = (ParaBox)root.FirstBox;
			var stringbox1 = (StringBox)para1.FirstBox;
			var seg1 = (FakeSegment)stringbox1.Segment;
			seg1.DrawActions = drawActions;
			var para2 = (ParaBox)para1.Next;
			var stringbox2 = (StringBox)para2.FirstBox;
			var seg2 = (FakeSegment)stringbox2.Segment;
			seg2.DrawActions = drawActions;

			var site = (MockSite)root.Site;
			root.Paint(vg, site.m_transform);
			var paintTrans = site.m_transform;
			int position = 0;

			int red = (int)ColorUtil.ConvertColorToBGR(Color.Red);
			int margLeft = layoutInfo.MpToPixelsX(1000);
			Assert.That(margLeft, Is.EqualTo(1));
			int bordLeft = layoutInfo.MpToPixelsX(5000);
			Assert.That(bordLeft, Is.EqualTo(7));
			int xOffset = 2 - 100; // how far it is pushed over by the offsets of the layoutInfo
			int margTop = layoutInfo.MpToPixelsY(2000);
			Assert.That(margTop, Is.EqualTo(3));
			int bordTop = layoutInfo.MpToPixelsY(6000);
			Assert.That(bordTop, Is.EqualTo(8));
			int yOffset = 2 - 200; // how far it is pushed down by the offsets of the layoutInfo
			int padLeft = layoutInfo.MpToPixelsX(9000);
			Assert.That(padLeft, Is.EqualTo(12));
			int padRight = layoutInfo.MpToPixelsX(11000);
			Assert.That(padRight, Is.EqualTo(15));
			int padTop = layoutInfo.MpToPixelsY(10000);
			Assert.That(padTop, Is.EqualTo(13));
			int padBottom = layoutInfo.MpToPixelsY(12000);
			Assert.That(padBottom, Is.EqualTo(16));
			// First it should draw a background rectangle for the first paragraph.
			// It is indented by the left margin and the left border, and down by the top margin and border.
			// The other side is determined by the size of the embedded box and the two pads.
			VerifyRect(drawActions, ref position, margLeft + bordLeft + xOffset, margTop + bordTop + yOffset,
				margLeft + bordLeft + xOffset + stringbox1.Width + padLeft + padRight,
				margTop + bordTop + yOffset + stringbox1.Height + padTop + padBottom,
				red);
			int bordBottom = layoutInfo.MpToPixelsY(8000);
			Assert.That(bordBottom, Is.EqualTo(11));
			int blue = (int)ColorUtil.ConvertColorToBGR(Color.Blue);
			// It's arbitrary what order we draw the borders, and I wish the test didn't specify it,
			// but in fact the current implementation draws the left border first.
			VerifyRect(drawActions, ref position, margLeft + xOffset, margTop + yOffset,
				margLeft + bordLeft + xOffset,
				margTop + bordTop + yOffset + padTop + stringbox1.Height + padBottom + bordBottom,
				blue);
			int bordRight = layoutInfo.MpToPixelsX(7000);
			Assert.That(bordRight, Is.EqualTo(9));
			// Then the top border
			VerifyRect(drawActions, ref position, margLeft + xOffset, margTop + yOffset,
				margLeft + bordLeft + xOffset + padLeft + stringbox1.Width + padRight + bordRight,
				margTop + bordTop + yOffset,
				blue);
			// Then the right border
			VerifyRect(drawActions, ref position,
				margLeft + bordLeft + xOffset + padLeft + stringbox1.Width + padRight,
				margTop + yOffset,
				margLeft + bordLeft + xOffset + padLeft + stringbox1.Width + padRight + bordRight,
				margTop + bordTop + yOffset + padTop + stringbox1.Height + padBottom + bordBottom,
				blue);
			// Then the bottom border
			VerifyRect(drawActions, ref position,
				margLeft + xOffset,
				margTop + bordTop + yOffset + padTop + stringbox1.Height + padBottom,
				margLeft + bordLeft + xOffset + padLeft + stringbox1.Width + padRight + bordRight,
				margTop + bordTop + yOffset + padTop + stringbox1.Height + padBottom + bordBottom,
				blue);
			// Figure an adjusted y offset for the second paragraph. Everything is down by the height
			// of the first paragraph, except that the top and bottom margins overlap by the
			// height of the smaller.
			int yOffset2 = yOffset + para1.Height - margTop;
			int yellow = (int)ColorUtil.ConvertColorToBGR(Color.Yellow);
			// Next a background block for the second paragraph.
			// (Background color should be reset for the embedded string boxes, so they should not draw their own
			// background.)
			VerifyRect(drawActions, ref position, margLeft + xOffset, margTop + yOffset2,
				margLeft + xOffset + stringbox2.Width,
				margTop + yOffset2 + stringbox2.Height,
				yellow);
			// Verify the position where the text is drawn
			VerifyDraw(drawActions, ref position, seg1, margLeft + bordLeft + padLeft + 2, margTop + bordTop + padTop + 2);
			VerifyDraw(drawActions, ref position, seg2, margLeft + 2, para1.Height + 2); //margTop cancels out
			// And that should be all!
			Assert.That(position, Is.EqualTo(drawActions.Count));

			// Verify that multi-lines in a paragraph are appropriately laid out with margin etc.
			int maxWidth = para1.Width - FakeRenderEngine.SimulatedWidth("paragraph");
			// This maxWidth should force each paragraph to make two segments.
			layoutInfo = HookupTests.MakeLayoutInfo(maxWidth, m_gm.VwGraphics, 55);
			root.Layout(layoutInfo);
			drawActions.Clear();
			position = 0;
			var stringbox1a = (StringBox)para1.FirstBox;
			var seg1a = (FakeSegment)stringbox1a.Segment;
			seg1a.DrawActions = drawActions;
			var stringbox1b = (StringBox)stringbox1a.Next;
			var seg1b = (FakeSegment)stringbox1b.Segment;
			seg1b.DrawActions = drawActions;
			var stringbox2a = (StringBox)para2.FirstBox;
			var seg2a = (FakeSegment)stringbox2a.Segment;
			seg2a.DrawActions = drawActions;
			var stringbox2b = (StringBox)stringbox2a.Next;
			var seg2b = (FakeSegment)stringbox2b.Segment;
			seg2b.DrawActions = drawActions;

			root.Paint(vg, site.m_transform);
			int margRight = layoutInfo.MpToPixelsX(3000);
			Assert.That(margRight, Is.EqualTo(4));
			// First it should draw a background rectangle for the first paragraph.
			// It is indented by the left margin and the left border, and down by the top margin and border.
			// The other side is determined by maxWidth minus the right margin and border.
			int contentHeight1 = stringbox1a.Height + stringbox1b.Height;
			VerifyRect(drawActions, ref position, margLeft + bordLeft + xOffset, margTop + bordTop + yOffset,
				maxWidth - margRight - bordRight + xOffset,
				margTop + bordTop + yOffset + contentHeight1 + padTop + padBottom,
				red);
			// It's arbitrary what order we draw the borders, and I wish the test didn't specify it,
			// but in fact the current implementation draws the left border first.
			VerifyRect(drawActions, ref position, margLeft + xOffset, margTop + yOffset,
				margLeft + bordLeft + xOffset,
				margTop + bordTop + yOffset + padTop + contentHeight1 + padBottom + bordBottom,
				blue);
			// Then the top border
			VerifyRect(drawActions, ref position, margLeft + xOffset, margTop + yOffset,
				maxWidth - margRight + xOffset,
				margTop + bordTop + yOffset,
				blue);
			// Then the right border
			VerifyRect(drawActions, ref position,
				maxWidth - margRight - bordRight + xOffset,
				margTop + yOffset,
				maxWidth - margRight + xOffset,
				margTop + bordTop + yOffset + padTop + contentHeight1 + padBottom + bordBottom,
				blue);
			// Then the bottom border
			VerifyRect(drawActions, ref position,
				margLeft + xOffset,
				margTop + bordTop + yOffset + padTop + contentHeight1 + padBottom,
				maxWidth - margRight + xOffset,
				margTop + bordTop + yOffset + padTop + contentHeight1 + padBottom + bordBottom,
				blue);
			// Figure an adjusted y offset for the second paragraph. Everything is down by the height
			// of the first paragraph, except that the top and bottom margins overlap by the
			// height of the smaller.
			yOffset2 = yOffset + para1.Height - margTop;
			// Next a background block for the second paragraph.
			// (Background color should be reset for the embedded string boxes, so they should not draw their own
			// background.)
			VerifyRect(drawActions, ref position, margLeft + xOffset, margTop + yOffset2,
				maxWidth - margRight + xOffset,
				margTop + yOffset2 + stringbox2a.Height + stringbox2b.Height,
				yellow);
			// Verify the position where the text is drawn
			VerifyDraw(drawActions, ref position, seg1a, margLeft + bordLeft + padLeft + 2, margTop + bordTop + padTop + 2);
			VerifyDraw(drawActions, ref position, seg1b, margLeft + bordLeft + padLeft + 2,
				margTop + bordTop + padTop + 2 + stringbox1a.Height);
			VerifyDraw(drawActions, ref position, seg2a, margLeft + 2, para1.Height + 2); //margTop cancels out
			VerifyDraw(drawActions, ref position, seg2b, margLeft + 2, para1.Height + 2 + stringbox2a.Height); //margTop cancels out
			// And that should be all!
			Assert.That(position, Is.EqualTo(drawActions.Count));

			// A quick check that Relayout puts things in the same places.
			drawActions.Clear();
			position = 0;
			var fixupMap = new Dictionary<Box, Rectangle>();
			fixupMap[para1] = new Rectangle(0, 0, 10, 10);
			var oldstring1aLeft = stringbox1a.Left;
			var oldstring1bTop = stringbox1b.Top;
			using (var lcb = new LayoutCallbacks(root))
				root.Relayout(layoutInfo, fixupMap, lcb);
			Assert.That(drawActions.Count, Is.EqualTo(0));
			Assert.That(para1.FirstBox.Left, Is.EqualTo(oldstring1aLeft));
			Assert.That(para1.FirstBox.Next.Top, Is.EqualTo(oldstring1bTop));
		}
示例#12
0
		public void DragCopyRtf()
		{
			var stylesheet = new MockStylesheet();
			var styleFirst = stylesheet.AddStyle("first", false);
			var styleSecond = stylesheet.AddStyle("second", false);
			var propsTrue = new MockStyleProp<bool>() {Value = true, ValueIsSet = true};
			var charInfo = new MockCharStyleInfo();
			styleFirst.DefaultCharacterStyleInfo = charInfo;
			charInfo.Bold = propsTrue;
			// Todo: make styleSecond have pretty much everything else.
			var charInfo2 = new MockCharStyleInfo();
			styleSecond.DefaultCharacterStyleInfo = charInfo2;
			charInfo2.FontColor = MakeColorProp(Color.Red);
			charInfo2.BackColor = MakeColorProp(Color.Yellow);
			charInfo2.UnderlineColor = MakeColorProp(Color.Green);
			charInfo2.Italic = propsTrue;
			charInfo2.FontName = new MockStyleProp<string>() {Value = "Arial", ValueIsSet = true};

			var styles = new AssembledStyles(stylesheet);
			var root = new RootBoxFdo(styles);
			var mock1 = new MockData1(23, 23);
			mock1.SimpleThree = "This is";
			var mock2 = new MockData1(23, 23);
			mock2.SimpleThree = " the day";
			var mock3 = new MockData1(23, 23);
			mock3.SimpleThree = " that the";
			var engine = new FakeRenderEngine() { Ws = 23, SegmentHeight = 13 };
			var factory = new FakeRendererFactory();
			var wsf = new MockWsf();
			engine.WritingSystemFactory = wsf;
			var wsEngine = wsf.MakeMockEngine(23, "en", engine);
			factory.SetRenderer(23, engine);
			root.Builder.Show(
				Paragraph.Containing(
					Display.Of(() => mock1.SimpleThree, 23).Style("first"),
					Display.Of(() => mock2.SimpleThree, 23).Style("second"),
					Display.Of(() => mock3.SimpleThree, 23).Style("first")
					));
			var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			PaintTransform ptrans = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96);
			MockSite site = new MockSite();
			site.m_transform = ptrans;
			site.m_vwGraphics = m_gm.VwGraphics;
			root.Site = site;

			SelectionBuilder.In(root).Offset("This ".Length).To.Offset("This is the day that".Length).Install();
			int indent = FakeRenderEngine.SimulatedWidth("This ");
			root.OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, indent + 5, 4, 0), Keys.None, m_gm.VwGraphics, ptrans);
			root.OnMouseMove(new MouseEventArgs(MouseButtons.Left, 1, indent + 5, 4, 0), Keys.None, m_gm.VwGraphics, ptrans);
			Assert.That(GetStringDropData(site), Is.EqualTo("is the day that"));
			// The order of the font and colors in the color table is arbitrary. This happens to be what the code does now. For some reason
			// Color.Green has green only 128.
			// The order of items in the definition of a style is arbitrary.
			// We're not doing anything yet for background color. \highlightN can specify background color for a character run,
			// but it can't be part of a style definition.
			Assert.That(GetRtfDropData(site), Is.EqualTo(
				RangeSelection.RtfPrefix
				+ @"{\fonttbl{\f0 MockFont;}{\f1 Arial;}}"
				+ @"{\colortbl ;\red0\green0\blue0;\red255\green255\blue255;\red255\green0\blue0;\red255\green255\blue0;\red0\green128\blue0;}"
				+ @"{\stylesheet{\*\cs1\b\additive first;\*\cs2\i\f1\cf3\ulc5\additive second;}}"
				+ RangeSelection.RtfDataPrefix
				+ @"{\*\cs1\b is}{\*\cs2\i\f1\cf3\ulc5\highlight4  the day}{\*\cs1\b  that\par}"
				+ @"}"));

			// Todo: handle styles that depend on WS
			// Todo: handle more than two runs
			// Todo: handle runs where actual formatting differs from style-specified formatting
			// Todo: handle multiple paragraphs
			// Todo: handle paragraph styles
		}
示例#13
0
        public void ArrowKeys()
        {
            var engine = new FakeRenderEngine()
            {
                Ws = 34, SegmentHeight = 13
            };
            var factory = new FakeRendererFactory();

            factory.SetRenderer(34, engine);
            var styles = new AssembledStyles().WithWs(34);
            var root   = new RootBoxFdo(styles);
            var para1  = AddPara("This i~^s the~ day", styles, root);
            var para2  = AddPara("", styles, root);
            var para3  = AddPara(new string[] { "that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE + " the Lord", "has made" },
                                 styles, root);
            var para4 = AddPara(new string[] { "we will", "", "rejoice" }, styles, root);

            int widthThisIsThe = FakeRenderEngine.SimulatedWidth("This is the");
            var layoutArgs     = MakeLayoutInfo(widthThisIsThe + 2, m_gm.VwGraphics, factory);

            root.Layout(layoutArgs);
            Assert.That(root.Height, Is.EqualTo(13 * 8), "A two-line and a one-line and a three-line and a two-line paragraph");
            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;

            // Simple left movement.
            var ipThisIsTheDay = para1.SelectAtEnd();
            var ipThisIsTheDa  = ipThisIsTheDay.MoveByKey(new KeyEventArgs(Keys.Left));

            VerifyIp(ipThisIsTheDa, para1, "This i~^s the~ da", false, "left from end");
            var ipThisIsTheD = ipThisIsTheDa.MoveByKey(new KeyEventArgs(Keys.Left));

            VerifyIp(ipThisIsTheD, para1, "This i~^s the~ d", false, "left from no special plae");

            // Left from one run into an adjacent non-empty run
            var ipThatTheLord2 = ((TextClientRun)para3.Source.ClientRuns[1]).SelectAt(para3, 0, false);
            var ipThatTheLor   = ipThatTheLord2.MoveByKey(new KeyEventArgs(Keys.Left));

            VerifyIp(ipThatTheLor, para3, "that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE + " the Lor", false, "left from start run2");

            // Left from one run into an adjacent empty run. Is this right or should we skip over it into
            // another run so we actually move a character?
            var ipStartOfRejoice = ((TextClientRun)para4.Source.ClientRuns[2]).SelectAt(para4, 0, false);
            var ipEmptyPara4     = ipStartOfRejoice.MoveByKey(new KeyEventArgs(Keys.Left));

            VerifyIp(ipEmptyPara4, para4, "we will", false, "left from start run into empty");

            // Out of the empty run into the previous one.
            var ipWeWil = ipEmptyPara4.MoveByKey(new KeyEventArgs(Keys.Left));

            VerifyIp(ipWeWil, para4, "we wil", false, "left from empty run");

            // back from one para into another.
            var ipPara2    = para2.SelectAtStart();
            var ipEndPara1 = ipPara2.MoveByKey(new KeyEventArgs(Keys.Left));

            VerifyIp(ipEndPara1, para1, "This i~^s the~ day", true, "left from one para to another");

            // back at the very start.
            var ipStart = para1.SelectAtStart();

            Assert.That(ipStart.MoveByKey(new KeyEventArgs(Keys.Left)), Is.Null);

            // back after a surrogate pair should not stop in the middle.
            var ipThatSurrogate = ((TextClientRun)para3.Source.ClientRuns[0]).SelectAt(para3,
                                                                                       ("that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE).Length, false);
            var ipThat = ipThatSurrogate.MoveByKey(new KeyEventArgs(Keys.Left));

            VerifyIp(ipThat, para3, "that", false, "left over surrogate pair");

            // Back to a place between diacritic and base should not stop.
            var ipThisI_Diacritics = ((TextClientRun)para1.Source.ClientRuns[0]).SelectAt(para1,
                                                                                          "This i~^".Length, false);
            var ipThisSpace = ipThisI_Diacritics.MoveByKey(new KeyEventArgs(Keys.Left));

            VerifyIp(ipThisSpace, para1, "This ", false, "left over diacritics");

            // We can use many of the same ones to check right movement.
            var ipThisIsTheDa_r = ipThisIsTheD.MoveByKey(new KeyEventArgs(Keys.Right));

            VerifyIp(ipThisIsTheDa_r, para1, "This i~^s the~ da", true, "simple right");

            // Move right into an empty paragraph.
            // Review JohnT: should this IP in an empty para associate forward or back?
            var ipStartP2 = ipThisIsTheDay.MoveByKey(new KeyEventArgs(Keys.Right));

            VerifyIp(ipStartP2, para2, "", false, "right into empty para");
            // Should definitely associate with the character following, not the nonexistent preceding one.
            var ipStartP3 = ipStartP2.MoveByKey(new KeyEventArgs(Keys.Right));

            VerifyIp(ipStartP3, para3, "", false, "right to start of non-empty para");

            var ipP3_t = ipStartP3.MoveByKey(new KeyEventArgs(Keys.Right));

            VerifyIp(ipP3_t, para3, "t", true, "simple right");

            var ipThatSurrogate2 = ipThat.MoveByKey(new KeyEventArgs(Keys.Right));

            VerifyIp(ipThatSurrogate2, para3, "that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE, true, "right over surrogate pair");

            var ipThatTheLord_left = ((TextClientRun)para3.Source.ClientRuns[0]).SelectAt(para3,
                                                                                          ("that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE + " the Lord").Length, true);
            var ipThatTheLord_space = ipThatTheLord_left.MoveByKey(new KeyEventArgs(Keys.Right));

            VerifyIp(ipThatTheLord_space, para3, "that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE + " the Lord ", true, "right from end run1");

            var ipEnd = para4.SelectAtEnd();

            Assert.That(ipEnd.MoveByKey(new KeyEventArgs(Keys.Right)), Is.Null);

            // Also can't make range by moving right from end.
            Assert.That(ipEnd.MoveByKey(new KeyEventArgs(Keys.Right | Keys.Shift)), Is.Null);

            var rangeThatSurrogate2 = ipThat.MoveByKey(new KeyEventArgs(Keys.Right | Keys.Shift));

            VerifyRange(rangeThatSurrogate2, para3, "that", para3, "that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE, "shift-right over surrogate pair");

            var rangeThatTha = ipThat.MoveByKey(new KeyEventArgs(Keys.Left | Keys.Shift));

            VerifyRange(rangeThatTha, para3, "that", para3, "tha", "shift-left end before anchor");

            // left from a range puts us at the start of the range
            var ipThat2 = rangeThatSurrogate2.MoveByKey(new KeyEventArgs(Keys.Left));

            VerifyIp(ipThat2, para3, "that", false, "left from range to IP");
            // right from a range puts us at the end of the range
            var ipThatSurrrogate2 = rangeThatSurrogate2.MoveByKey(new KeyEventArgs(Keys.Right));

            VerifyIp(ipThatSurrrogate2, para3, "that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE, true, "right from range");

            // shift-left from a 1-char range collapses it to an IP
            var ipThat3 = rangeThatSurrogate2.MoveByKey(new KeyEventArgs(Keys.Left | Keys.Shift));

            VerifyIp(ipThat3, para3, "that", false, "left over surrogate pair");

            // shift-right from a range makes one with the same anchor but an extended end
            var rangeThatSurrogateSpace = rangeThatSurrogate2.MoveByKey(new KeyEventArgs(Keys.Right | Keys.Shift));

            VerifyRange(rangeThatSurrogateSpace, para3, "that", para3, "that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE + " ", "shift-right from range");

            // shift-right from a range that can't grow returns null.
            var ipWeWillRejoic = (InsertionPoint)ipEnd.MoveByKey(new KeyEventArgs(Keys.Left));
            var range1AtEnd    = new RangeSelection(ipWeWillRejoic, ipEnd);

            Assert.That(range1AtEnd.MoveByKey(new KeyEventArgs(Keys.Right | Keys.Shift)), Is.Null);

            // Home key.
            var ipStartP2_2 = ipThat.MoveByKey(new KeyEventArgs(Keys.Home));

            VerifyIp(ipStartP2_2, para3, "", false, "home in Para 3");

            var ipStart_2 = ipThat.MoveByKey(new KeyEventArgs(Keys.Home | Keys.Control));

            VerifyIp(ipStart_2, para1, "", false, "ctrl-home in Para 3");

            // End key.
            var ipEndP2 = ipThat.MoveByKey(new KeyEventArgs(Keys.End));

            VerifyIp(ipEndP2, para3, "that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE + " the Lord" + "has made",
                     true, "end in Para 3");

            var ipEnd_2 = ipThat.MoveByKey(new KeyEventArgs(Keys.End | Keys.Control));

            VerifyIp(ipEnd_2, para4, "we will" + "rejoice", true, "ctrl-end in Para 3");

            // Down key
            var ipThisIsThe_R = ipStart.MoveByKey(new KeyEventArgs(Keys.Down));

            VerifyIp(ipThisIsThe_R, para1, "This i~^s the~ ", false, "down from start line 1");

            var ipTh           = para1.SelectAt(2, true);
            var ipThisIsTheDa2 = ipTh.MoveByKey(new KeyEventArgs(Keys.Down));

            VerifyIp(ipThisIsTheDa2, para1, "This i~^s the~ da", false, "down from 2 chars into line 1");

            var ipThisIdTh      = para1.SelectAt("This i~^s th".Length, false);
            var ipThisIsTheDay2 = ipThisIdTh.MoveByKey(new KeyEventArgs(Keys.Down));

            VerifyIp(ipThisIsTheDay2, para1, "This i~^s the~ day", true, "down from near end line 1");

            // Empty para: arbitrary which way it associates.
            var ipPara2Down = ipThisIsTheDay2.MoveByKey(new KeyEventArgs(Keys.Down));

            VerifyIp(ipPara2Down, para2, "", true, "down twice from near end line 1");

            // Going on down, we should remember the starting X position and end up about that
            // far into the next full-length line. The 'i' characters in the first line make it
            // a bit iffy; might be closer to the start of the 'e' at the end of 'the'.
            // The other complication is that our fake render engine is not smart about surrogate pairs,
            // and treats the musical semibrevis as two ordinary characters.
            // Omitting the diacritics in the first paragraph, our selection starts 10 characters in.
            // The result string here is 9 characters, since with no narrow letters on this para,
            // we end up closer to the left of the 'e'.
            var ipThatTheSpaceDown = ipPara2Down.MoveByKey(new KeyEventArgs(Keys.Down));

            VerifyIp(ipThatTheSpaceDown, para3, "that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE + " th", false,
                     "down 3x from near end line 1");

            Assert.That(ipEnd.MoveByKey(new KeyEventArgs(Keys.Down)), Is.Null);

            var ipPara2Up = ipThatTheSpaceDown.MoveByKey(new KeyEventArgs(Keys.Up));

            VerifyIp(ipPara2Up, para2, "", true, "back up aligned with near end line 1");

            var ipThisIsTheDayUp = ipPara2Up.MoveByKey(new KeyEventArgs(Keys.Up));

            VerifyIp(ipThisIsTheDayUp, para1, "This i~^s the~ day", true, "up from para2 aligned near end line 1");
            // It's going to be looking for a position right at the boundary...either assocPrev would be
            // reasonable.
            var ipThisIdTh2Up = ipThisIsTheDayUp.MoveByKey(new KeyEventArgs(Keys.Up));

            VerifyIp(ipThisIdTh2Up, para1, "This i~^s th", false, "up from end para 1 aligned near end line 1");

            //var ipPara2_2 = ipThisIsTheDay.MoveByKey(new KeyEventArgs(Keys.Down));
            //VerifyIp(ipPara2_2, para2, "", true, "down from end para 1");

            // Todo:
            // HandleSpecialKey is called from OnKeyDown and should handle at least these:
            //case Keys.PageUp:
            //case Keys.PageDown:
            //case Keys.End:
            //case Keys.Home:
            //case Keys.Left: // done
            //case Keys.Up:
            //case Keys.Right: // done
            //case Keys.Down:
            //case Keys.F7: // the only two function keys currently known to the Views code,
            //case Keys.F8: // used for left and right arrow by string character amounts.
            // Test Left: (done)
            // - char to char in same line
            //	- skipping diacritics
            //	- skipping surrogate pairs
            // - to another line in same paragraph
            // - to previous (empty?) paragraph
            // - at very start (nothing happens)
            // - range collapses to start
            // - anything special to test if there are multiple runs? e.g., at boundary
            // - skip over embedded pictures
            // - eventually drop into embedded boxes that contain text?
            // Similarly right (done)
            // Down:
            // - same para, there is text below
            // - same para, no text immediately below on same line (goes to end of previous line)
            //  - eventually: what should happen if logical and physical end of next line don't coincide?
            // - down again to a longer line: should stay aligned with start position (what resets this??)
            // etc for others.
        }
示例#14
0
        private void BodyofUserPromptTest(MockData1 data1, Flow promptField, Func <string> reader)
        {
            var engine = new FakeRenderEngine()
            {
                Ws = 34, SegmentHeight = 13
            };
            var factory = new FakeRendererFactory();

            factory.SetRenderer(34, engine);
            factory.SetRenderer(35, engine);
            factory.SetRenderer(0, engine);             // for literals
            var styles = new AssembledStyles().WithWs(34);

            var root = new RootBoxFdo(styles);

            root.Builder.Show(
                Paragraph.Containing(
                    Display.Of("lead in ", 34),
                    promptField,
                    Display.Of("trailing", 34)
                    )
                );
            var para = (ParaBox)root.FirstBox;

            Assert.That(para.Source.RenderText, Is.EqualTo("lead in type here trailing"));

            int width      = FakeRenderEngine.SimulatedWidth("lead in type her");        // should make it take 2 lines and split prompt.
            var layoutArgs = MakeLayoutInfo(width, m_gm.VwGraphics, factory);

            root.Layout(layoutArgs);
            MockSite       site   = new MockSite();
            PaintTransform ptrans = new PaintTransform(2, 4, 96, 96, 0, 10, 96, 96);

            site.m_transform  = ptrans;
            site.m_vwGraphics = m_gm.VwGraphics;
            root.Site         = site;

            // Click on "type here" produces an IP in the empty string.
            int leadWidth = FakeRenderEngine.SimulatedWidth("lead in ");
            var mouseArgs = new MouseEventArgs(MouseButtons.Left, 1, 2 + leadWidth + 3, 0, 0);

            root.OnMouseDown(mouseArgs, Keys.None, m_gm.VwGraphics, ptrans);
            var ip = root.Selection as InsertionPoint;

            Assert.That(ip, Is.Not.Null);
            Assert.That(ip.LogicalParaPosition, Is.EqualTo("lead in ".Length));
            Assert.That(ip.StringPosition, Is.EqualTo(0));

            // IP is drawn as range covering "type here"
            ip.Draw(m_gm.VwGraphics, ptrans);
            var first = (StringBox)para.FirstBox;

            VerifyRangeSegmentDrawing(para, first, (FakeSegment)first.Segment, "lead in ".Length, "lead in type here ".Length,
                                      -4, 4 - 10, 4 - 10 + 13);
            var second = (StringBox)first.Next;

            VerifyRangeSegmentDrawing(para, second, (FakeSegment)second.Segment, "lead in ".Length, "lead in type here ".Length,
                                      -4 - 13, 4 - 10 + 13, 4 - 10 + 13 * 2);
            // Check that we get a sensible answer for the selection's containing rectangle.
            ((FakeSegment)first.Segment).LeftPositionOfRangeResult   = 17;
            ((FakeSegment)first.Segment).RightPositionOfRangeResult  = 29;
            ((FakeSegment)second.Segment).LeftPositionOfRangeResult  = 5;
            ((FakeSegment)second.Segment).RightPositionOfRangeResult = 13;
            var rect = ip.GetSelectionLocation(m_gm.VwGraphics, ptrans);

            Assert.That(rect.Top, Is.EqualTo(4 - 10));
            Assert.That(rect.Bottom, Is.EqualTo(4 - 10 + 13 * 2));
            Assert.That(rect.Left, Is.EqualTo(5));
            Assert.That(rect.Right, Is.EqualTo(29));
            VerifyRangeSegmentQuery(para, first, (FakeSegment)first.Segment, "lead in ".Length, "lead in type here ".Length,
                                    -4, 4 - 10, 4 - 10 + 13);
            VerifyRangeSegmentQuery(para, second, (FakeSegment)second.Segment, "lead in ".Length, "lead in type here ".Length,
                                    -4 - 13, 4 - 10 + 13, 4 - 10 + 13 * 2);
            Assert.That(second.IchMin, Is.EqualTo("lead in type ".Length));
            // When the IP is drawn like this, it doesn't flash!
            site.RectsInvalidatedInRoot.Clear();
            site.RectsInvalidated.Clear();
            root.FlashInsertionPoint();             // Call twice just in case somehow only some invalidates worked.
            root.FlashInsertionPoint();
            Assert.That(site.RectsInvalidated, Is.Empty);
            Assert.That(site.RectsInvalidatedInRoot, Is.Empty);
            // Typing something else makes "type here" go away and produces a normal IP after it.
            ip.InsertText("x");
            Assert.That(reader(), Is.EqualTo("x"));
            Assert.That(para.Source.RenderText, Is.EqualTo("lead in xtrailing"));
            ip = root.Selection as InsertionPoint;
            Assert.That(ip, Is.Not.Null);
            Assert.That(ip.ShouldFlash, Is.True);
            Assert.That(ip.LogicalParaPosition, Is.EqualTo("lead in x".Length));
            // Deleting back to empty string makes "type here" reappear.
            ip.Backspace();
            Assert.That(reader(), Is.EqualTo(""));
            Assert.That(para.Source.RenderText, Is.EqualTo("lead in type here trailing"));
            ip = root.Selection as InsertionPoint;
            Assert.That(ip, Is.Not.Null);
            Assert.That(ip.ShouldFlash, Is.False);
            Assert.That(ip.LogicalParaPosition, Is.EqualTo("lead in ".Length));
            Assert.That(ip.LastRenderParaPosition, Is.EqualTo("lead in type here ".Length));
            second = (StringBox)para.FirstBox.Next;
            Assert.That(second.IchMin, Is.EqualTo("lead in type ".Length));
            // Click after "type here" produces an IP at the right place in the following string.
            // We've arranged for the prompt to be split, so this is after the word 'here' on the second line.
            int hereTWidth = FakeRenderEngine.SimulatedWidth("here t");

            mouseArgs = new MouseEventArgs(MouseButtons.Left, 1, 2 + hereTWidth - 1, 4 - 10 + 13 + 2, 0);
            root.OnMouseDown(mouseArgs, Keys.None, m_gm.VwGraphics, ptrans);
            ip = root.Selection as InsertionPoint;
            Assert.That(ip, Is.Not.Null);
            Assert.That(ip.LogicalParaPosition, Is.EqualTo("lead in t".Length));
            Assert.That(ip.AssociatePrevious, Is.True);
            Assert.That(ip.StringPosition, Is.EqualTo(1));
            Assert.That(ip.RenderParaPosition, Is.EqualTo("lead in type here t".Length));
            // Also try a click in the second-line part of the prompt.
            int herWidth = FakeRenderEngine.SimulatedWidth("her");

            mouseArgs = new MouseEventArgs(MouseButtons.Left, 1, 2 + herWidth - 1, 4 - 10 + 13 + 2, 0);
            root.OnMouseDown(mouseArgs, Keys.None, m_gm.VwGraphics, ptrans);
            ip = root.Selection as InsertionPoint;
            Assert.That(ip, Is.Not.Null);
            Assert.That(ip.LogicalParaPosition, Is.EqualTo("lead in ".Length));
            Assert.That(ip.StringPosition, Is.EqualTo(0));
            Assert.That(ip.RenderParaPosition, Is.EqualTo("lead in ".Length));
            Assert.That(ip.LastRenderParaPosition, Is.EqualTo("lead in type here ".Length));
        }
示例#15
0
        public void InsertGrowsPara()
        {
            string contents = "This is the day.";
            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 extraBox = new BlockBox(styles, Color.Red, 50, 72000);
            var root     = new RootBoxFdo(styles);

            root.SizeChanged += root_SizeChanged;
            root.AddBox(para);
            root.AddBox(extraBox);
            var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);

            root.Layout(layoutArgs);
            Assert.IsTrue(m_sizeChangedCalled);
            Assert.That(root.Height, Is.EqualTo(13 + 96));
            Assert.That(root.Width, Is.EqualTo(FakeRenderEngine.SimulatedWidth(contents)));

            int widthThisIsThe = FakeRenderEngine.SimulatedWidth("This is the");

            layoutArgs = MakeLayoutInfo(widthThisIsThe + 2, m_gm.VwGraphics, factory);
            root.Layout(layoutArgs);
            Assert.That(root.Height, Is.EqualTo(26 + 96), "two line para is twice the height");
            Assert.That(root.Width, Is.EqualTo(widthThisIsThe + 2), "two-line para occupies full available width");
            Assert.That(extraBox.Top, Is.EqualTo(26));

            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;
            m_sizeChangedCalled = false;
            var ip = para.SelectAtEnd();

            ip.InsertText(" We will be");
            Assert.That(para.Height, Is.EqualTo(39), "inserted text makes para a line higher");
            Assert.That(root.Height, Is.EqualTo(39 + 96), "root grows when para does");
            Assert.That(root.Width, Is.EqualTo(widthThisIsThe + 2), "three-line para occupies full available width");
            Assert.That(extraBox.Top, Is.EqualTo(39));
            Assert.IsTrue(m_sizeChangedCalled);
        }
示例#16
0
        public void DrawingBordersandBackground()
        {
            var root = new RootBoxFdo(new AssembledStyles());

            SetupFakeRootSite(root);
            var layoutInfo = HookupTests.MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);

            root.RendererFactory = layoutInfo.RendererFactory;
            var mock1 = new MockData1()
            {
                SimpleThree = "This is the first paragraph."
            };
            // The length of the second paragraph is found by experiment to be enough so that
            // despite its lacking borders it also breaks into 2 lines in the second step.
            var mock2 = new MockData1()
            {
                SimpleThree = "Here is another paragraph. It needs to be a bit longer."
            };

            root.Builder.Show(
                Paragraph.Containing(Display.Of(() => mock1.SimpleThree)).BackColor(Color.Red)
                .Margins(1.Points(), 2.Points(), 3.Points(), 4.Points())
                .Borders(5.Points(), 6.Points(), 7.Points(), 8.Points(), Color.Blue)
                .Pads(9.Points(), 10.Points(), 11.Points(), 12.Points()),
                Paragraph.Containing(Display.Of(() => mock2.SimpleThree)).BackColor(Color.Yellow)
                .Margins(1.Points(), 2.Points(), 3.Points(), 4.Points()));
            root.Layout(layoutInfo);
            // We want to keep track of the sequence of paint operations in all three segments.
            var drawActions = new List <object>();
            var vg          = new MockGraphics();

            vg.DrawActions = drawActions;
            var para1      = (ParaBox)root.FirstBox;
            var stringbox1 = (StringBox)para1.FirstBox;
            var seg1       = (FakeSegment)stringbox1.Segment;

            seg1.DrawActions = drawActions;
            var para2      = (ParaBox)para1.Next;
            var stringbox2 = (StringBox)para2.FirstBox;
            var seg2       = (FakeSegment)stringbox2.Segment;

            seg2.DrawActions = drawActions;

            var site = (MockSite)root.Site;

            root.Paint(vg, site.m_transform);
            var paintTrans = site.m_transform;
            int position   = 0;

            int red      = (int)ColorUtil.ConvertColorToBGR(Color.Red);
            int margLeft = layoutInfo.MpToPixelsX(1000);

            Assert.That(margLeft, Is.EqualTo(1));
            int bordLeft = layoutInfo.MpToPixelsX(5000);

            Assert.That(bordLeft, Is.EqualTo(7));
            int xOffset = 2 - 100;             // how far it is pushed over by the offsets of the layoutInfo
            int margTop = layoutInfo.MpToPixelsY(2000);

            Assert.That(margTop, Is.EqualTo(3));
            int bordTop = layoutInfo.MpToPixelsY(6000);

            Assert.That(bordTop, Is.EqualTo(8));
            int yOffset = 2 - 200;             // how far it is pushed down by the offsets of the layoutInfo
            int padLeft = layoutInfo.MpToPixelsX(9000);

            Assert.That(padLeft, Is.EqualTo(12));
            int padRight = layoutInfo.MpToPixelsX(11000);

            Assert.That(padRight, Is.EqualTo(15));
            int padTop = layoutInfo.MpToPixelsY(10000);

            Assert.That(padTop, Is.EqualTo(13));
            int padBottom = layoutInfo.MpToPixelsY(12000);

            Assert.That(padBottom, Is.EqualTo(16));
            // First it should draw a background rectangle for the first paragraph.
            // It is indented by the left margin and the left border, and down by the top margin and border.
            // The other side is determined by the size of the embedded box and the two pads.
            VerifyRect(drawActions, ref position, margLeft + bordLeft + xOffset, margTop + bordTop + yOffset,
                       margLeft + bordLeft + xOffset + stringbox1.Width + padLeft + padRight,
                       margTop + bordTop + yOffset + stringbox1.Height + padTop + padBottom,
                       red);
            int bordBottom = layoutInfo.MpToPixelsY(8000);

            Assert.That(bordBottom, Is.EqualTo(11));
            int blue = (int)ColorUtil.ConvertColorToBGR(Color.Blue);

            // It's arbitrary what order we draw the borders, and I wish the test didn't specify it,
            // but in fact the current implementation draws the left border first.
            VerifyRect(drawActions, ref position, margLeft + xOffset, margTop + yOffset,
                       margLeft + bordLeft + xOffset,
                       margTop + bordTop + yOffset + padTop + stringbox1.Height + padBottom + bordBottom,
                       blue);
            int bordRight = layoutInfo.MpToPixelsX(7000);

            Assert.That(bordRight, Is.EqualTo(9));
            // Then the top border
            VerifyRect(drawActions, ref position, margLeft + xOffset, margTop + yOffset,
                       margLeft + bordLeft + xOffset + padLeft + stringbox1.Width + padRight + bordRight,
                       margTop + bordTop + yOffset,
                       blue);
            // Then the right border
            VerifyRect(drawActions, ref position,
                       margLeft + bordLeft + xOffset + padLeft + stringbox1.Width + padRight,
                       margTop + yOffset,
                       margLeft + bordLeft + xOffset + padLeft + stringbox1.Width + padRight + bordRight,
                       margTop + bordTop + yOffset + padTop + stringbox1.Height + padBottom + bordBottom,
                       blue);
            // Then the bottom border
            VerifyRect(drawActions, ref position,
                       margLeft + xOffset,
                       margTop + bordTop + yOffset + padTop + stringbox1.Height + padBottom,
                       margLeft + bordLeft + xOffset + padLeft + stringbox1.Width + padRight + bordRight,
                       margTop + bordTop + yOffset + padTop + stringbox1.Height + padBottom + bordBottom,
                       blue);
            // Figure an adjusted y offset for the second paragraph. Everything is down by the height
            // of the first paragraph, except that the top and bottom margins overlap by the
            // height of the smaller.
            int yOffset2 = yOffset + para1.Height - margTop;
            int yellow   = (int)ColorUtil.ConvertColorToBGR(Color.Yellow);

            // Next a background block for the second paragraph.
            // (Background color should be reset for the embedded string boxes, so they should not draw their own
            // background.)
            VerifyRect(drawActions, ref position, margLeft + xOffset, margTop + yOffset2,
                       margLeft + xOffset + stringbox2.Width,
                       margTop + yOffset2 + stringbox2.Height,
                       yellow);
            // Verify the position where the text is drawn
            VerifyDraw(drawActions, ref position, seg1, margLeft + bordLeft + padLeft + 2, margTop + bordTop + padTop + 2);
            VerifyDraw(drawActions, ref position, seg2, margLeft + 2, para1.Height + 2);             //margTop cancels out
            // And that should be all!
            Assert.That(position, Is.EqualTo(drawActions.Count));

            // Verify that multi-lines in a paragraph are appropriately laid out with margin etc.
            int maxWidth = para1.Width - FakeRenderEngine.SimulatedWidth("paragraph");

            // This maxWidth should force each paragraph to make two segments.
            layoutInfo = HookupTests.MakeLayoutInfo(maxWidth, m_gm.VwGraphics, 55);
            root.Layout(layoutInfo);
            drawActions.Clear();
            position = 0;
            var stringbox1a = (StringBox)para1.FirstBox;
            var seg1a       = (FakeSegment)stringbox1a.Segment;

            seg1a.DrawActions = drawActions;
            var stringbox1b = (StringBox)stringbox1a.Next;
            var seg1b       = (FakeSegment)stringbox1b.Segment;

            seg1b.DrawActions = drawActions;
            var stringbox2a = (StringBox)para2.FirstBox;
            var seg2a       = (FakeSegment)stringbox2a.Segment;

            seg2a.DrawActions = drawActions;
            var stringbox2b = (StringBox)stringbox2a.Next;
            var seg2b       = (FakeSegment)stringbox2b.Segment;

            seg2b.DrawActions = drawActions;

            root.Paint(vg, site.m_transform);
            int margRight = layoutInfo.MpToPixelsX(3000);

            Assert.That(margRight, Is.EqualTo(4));
            // First it should draw a background rectangle for the first paragraph.
            // It is indented by the left margin and the left border, and down by the top margin and border.
            // The other side is determined by maxWidth minus the right margin and border.
            int contentHeight1 = stringbox1a.Height + stringbox1b.Height;

            VerifyRect(drawActions, ref position, margLeft + bordLeft + xOffset, margTop + bordTop + yOffset,
                       maxWidth - margRight - bordRight + xOffset,
                       margTop + bordTop + yOffset + contentHeight1 + padTop + padBottom,
                       red);
            // It's arbitrary what order we draw the borders, and I wish the test didn't specify it,
            // but in fact the current implementation draws the left border first.
            VerifyRect(drawActions, ref position, margLeft + xOffset, margTop + yOffset,
                       margLeft + bordLeft + xOffset,
                       margTop + bordTop + yOffset + padTop + contentHeight1 + padBottom + bordBottom,
                       blue);
            // Then the top border
            VerifyRect(drawActions, ref position, margLeft + xOffset, margTop + yOffset,
                       maxWidth - margRight + xOffset,
                       margTop + bordTop + yOffset,
                       blue);
            // Then the right border
            VerifyRect(drawActions, ref position,
                       maxWidth - margRight - bordRight + xOffset,
                       margTop + yOffset,
                       maxWidth - margRight + xOffset,
                       margTop + bordTop + yOffset + padTop + contentHeight1 + padBottom + bordBottom,
                       blue);
            // Then the bottom border
            VerifyRect(drawActions, ref position,
                       margLeft + xOffset,
                       margTop + bordTop + yOffset + padTop + contentHeight1 + padBottom,
                       maxWidth - margRight + xOffset,
                       margTop + bordTop + yOffset + padTop + contentHeight1 + padBottom + bordBottom,
                       blue);
            // Figure an adjusted y offset for the second paragraph. Everything is down by the height
            // of the first paragraph, except that the top and bottom margins overlap by the
            // height of the smaller.
            yOffset2 = yOffset + para1.Height - margTop;
            // Next a background block for the second paragraph.
            // (Background color should be reset for the embedded string boxes, so they should not draw their own
            // background.)
            VerifyRect(drawActions, ref position, margLeft + xOffset, margTop + yOffset2,
                       maxWidth - margRight + xOffset,
                       margTop + yOffset2 + stringbox2a.Height + stringbox2b.Height,
                       yellow);
            // Verify the position where the text is drawn
            VerifyDraw(drawActions, ref position, seg1a, margLeft + bordLeft + padLeft + 2, margTop + bordTop + padTop + 2);
            VerifyDraw(drawActions, ref position, seg1b, margLeft + bordLeft + padLeft + 2,
                       margTop + bordTop + padTop + 2 + stringbox1a.Height);
            VerifyDraw(drawActions, ref position, seg2a, margLeft + 2, para1.Height + 2);                      //margTop cancels out
            VerifyDraw(drawActions, ref position, seg2b, margLeft + 2, para1.Height + 2 + stringbox2a.Height); //margTop cancels out
            // And that should be all!
            Assert.That(position, Is.EqualTo(drawActions.Count));

            // A quick check that Relayout puts things in the same places.
            drawActions.Clear();
            position = 0;
            var fixupMap = new Dictionary <Box, Rectangle>();

            fixupMap[para1] = new Rectangle(0, 0, 10, 10);
            var oldstring1aLeft = stringbox1a.Left;
            var oldstring1bTop  = stringbox1b.Top;

            using (var lcb = new LayoutCallbacks(root))
                root.Relayout(layoutInfo, fixupMap, lcb);
            Assert.That(drawActions.Count, Is.EqualTo(0));
            Assert.That(para1.FirstBox.Left, Is.EqualTo(oldstring1aLeft));
            Assert.That(para1.FirstBox.Next.Top, Is.EqualTo(oldstring1bTop));
        }
示例#17
0
        public void PileAndBlock()
        {
            var root = new RootBoxFdo(new AssembledStyles());

            SetupFakeRootSite(root);
            var layoutInfo = HookupTests.MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);

            root.RendererFactory = layoutInfo.RendererFactory;
            var mock1 = new MockData1()
            {
                SimpleThree = "This is the first paragraph."
            };
            // The length of the second paragraph is found by experiment to be enough so that
            // despite its lacking borders it also breaks into 2 lines in the second step.
            var mock2 = new MockData1()
            {
                SimpleThree = "Here is another paragraph. It needs to be a bit longer."
            };

            root.Builder.Show(
                Div.Containing(
                    Display.Block(Color.Red, 25000, 18000).BackColor(Color.Purple)
                    .Margins(3000, 3000, 3000, 3000)
                    .Border(5000, Color.Blue)
                    .Pads(4000, 4000, 4000, 4000),
                    Display.Block(Color.Green, 25000, 18000)
                    ).BackColor(Color.Pink)                     // these apply to div.
                .Margins(1000, 1000, 1000, 1000)
                .Border(2000, Color.Gold)
                .Pads(6000, 6000, 6000, 6000));
            root.Layout(layoutInfo);
            // We want to keep track of the sequence of paint operations in all three segments.
            var drawActions = new List <object>();
            var vg          = new MockGraphics();

            vg.DrawActions = drawActions;

            var site = (MockSite)root.Site;

            root.Paint(vg, site.m_transform);
            var paintTrans = site.m_transform;
            int position   = 0;
            int xOffset    = 2 - 100;          // how far it is pushed over by the offsets of the layoutInfo
            int yOffset    = 2 - 200;          // how far it is pushed down by the offsets of the layoutInfo

            int red    = (int)ColorUtil.ConvertColorToBGR(Color.Red);
            int pink   = (int)ColorUtil.ConvertColorToBGR(Color.Pink);
            int purple = (int)ColorUtil.ConvertColorToBGR(Color.Purple);
            int blue   = (int)ColorUtil.ConvertColorToBGR(Color.Blue);
            int green  = (int)ColorUtil.ConvertColorToBGR(Color.Green);
            int gold   = (int)ColorUtil.ConvertColorToBGR(Color.Gold);
            // Technically we could do different conversions in the two directions, but for this test both dpi are the same.
            int margPile    = layoutInfo.MpToPixelsX(1000);
            int bordPile    = layoutInfo.MpToPixelsX(2000);
            int padPile     = layoutInfo.MpToPixelsX(6000);
            int blockWidth  = layoutInfo.MpToPixelsX(25000);
            int blockHeight = layoutInfo.MpToPixelsX(18000);
            int margBlock   = layoutInfo.MpToPixelsX(3000);
            int bordBlock   = layoutInfo.MpToPixelsX(5000);
            int padBlock    = layoutInfo.MpToPixelsX(4000);

            // First a background rectangle for the whole pile.
            var leftPilePad   = margPile + bordPile + xOffset;
            var topPilePad    = margPile + bordPile + yOffset;
            var rightPilePad  = margPile + bordPile + 2 * padPile + blockWidth + 2 * margBlock + 2 * bordBlock + 2 * padBlock + xOffset;
            var bottomPilePad = margPile + bordPile + 2 * padPile + 2 * blockHeight + 2 * margBlock + 2 * bordBlock + 2 * padBlock + yOffset;

            VerifyRect(drawActions, ref position, leftPilePad, topPilePad, rightPilePad, bottomPilePad, pink);
            // Left border, whole pile
            VerifyRect(drawActions, ref position, leftPilePad - bordPile, topPilePad - bordPile,
                       leftPilePad, bottomPilePad + bordPile, gold);
            // top border, whole pile
            VerifyRect(drawActions, ref position, leftPilePad - bordPile, topPilePad - bordPile,
                       rightPilePad + bordPile, topPilePad, gold);
            // right border, whole pile
            VerifyRect(drawActions, ref position, rightPilePad, topPilePad - bordPile,
                       rightPilePad + bordPile, bottomPilePad + bordPile, gold);
            // bottom border, whole pile
            VerifyRect(drawActions, ref position, leftPilePad - bordPile, bottomPilePad,
                       rightPilePad + bordPile, bottomPilePad + bordPile, gold);

            // background and border for first block.
            var leftBlockPad   = margPile + bordPile + padPile + margBlock + bordBlock + xOffset;
            var topBlockPad    = margPile + bordPile + padPile + margBlock + bordBlock + yOffset;
            var rightBlockPad  = margPile + bordPile + padPile + margBlock + bordBlock + 2 * padBlock + blockWidth + xOffset;
            var bottomBlockPad = margPile + bordPile + padPile + margBlock + bordBlock + 2 * padBlock + blockHeight + yOffset;

            VerifyRect(drawActions, ref position, leftBlockPad, topBlockPad, rightBlockPad, bottomBlockPad, purple);
            // Left border, whole pile
            VerifyRect(drawActions, ref position, leftBlockPad - bordBlock, topBlockPad - bordBlock,
                       leftBlockPad, bottomBlockPad + bordBlock, blue);
            // top border, whole pile
            VerifyRect(drawActions, ref position, leftBlockPad - bordBlock, topBlockPad - bordBlock,
                       rightBlockPad + bordBlock, topBlockPad, blue);
            // right border, whole pile
            VerifyRect(drawActions, ref position, rightBlockPad, topBlockPad - bordBlock,
                       rightBlockPad + bordBlock, bottomBlockPad + bordBlock, blue);
            // bottom border, whole pile
            VerifyRect(drawActions, ref position, leftBlockPad - bordBlock, bottomBlockPad,
                       rightBlockPad + bordBlock, bottomBlockPad + bordBlock, blue);
            // The first block itself.
            VerifyRect(drawActions, ref position, leftBlockPad + padBlock, topBlockPad + padBlock,
                       leftBlockPad + padBlock + blockWidth, topBlockPad + padBlock + blockHeight, red);
            // The second block itself.
            var topBlock2 = bottomBlockPad + bordBlock + margBlock;

            VerifyRect(drawActions, ref position, leftPilePad + padPile, topBlock2,
                       leftPilePad + padPile + blockWidth, topBlock2 + blockHeight, green);
            // And that should be all!
            Assert.That(position, Is.EqualTo(drawActions.Count));

            // A quick check that Relayout puts things in the same places.
            drawActions.Clear();
            var fixupMap = new Dictionary <Box, Rectangle>();
            var div1     = (DivBox)root.FirstBox;
            var block1   = div1.FirstBox;

            fixupMap[div1]   = new Rectangle(0, 0, 10, 10);
            fixupMap[block1] = new Rectangle(0, 0, 10, 10);
            var oldblock1Left = block1.Left;
            var oldblock1bTop = block1.Top;

            using (var lcb = new LayoutCallbacks(root))
                root.Relayout(layoutInfo, fixupMap, lcb);
            Assert.That(drawActions.Count, Is.EqualTo(0));
            Assert.That(div1.FirstBox.Left, Is.EqualTo(oldblock1Left));
            Assert.That(div1.FirstBox.Top, Is.EqualTo(oldblock1bTop));
        }
示例#18
0
		public void BackgroundAndUnderlinePainting()
		{
			var styles = new AssembledStyles();
			RootBox root = new RootBoxFdo(styles);
			SetupFakeRootSite(root);
			var layoutInfo = HookupTests.MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);
			root.RendererFactory = layoutInfo.RendererFactory;
			root.Builder.Show(
				Paragraph.Containing(
					Display.Of("plain"),
					Display.Of("underOnYellow").Underline(FwUnderlineType.kuntSingle).BackColor(Color.Yellow)
					),
				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)
					)
				);
			root.Layout(layoutInfo);

			var para1 = (ParaBox)root.FirstBox;
			var stringBox1 = (StringBox)para1.FirstBox;
			var seg1 = (FakeSegment)stringBox1.Segment;
			// A convenient place to test that literals get Chrp with default user ws.
			LgCharRenderProps chrp;
			int ichMin, ichLim;
			para1.Source.GetCharProps(0, out chrp, out ichMin, out ichLim);
			Assert.That(chrp.ws, Is.EqualTo(layoutInfo.RendererFactory.UserWs));
			// This segment has just one chunk of underline, the second run.
			seg1.NextCharPlacementResults.Add(new FakeSegment.CharPlacementResults()
												{Lefts = new[] {10}, Rights = new[] {20}, Tops = new[] {15}});
			// Todo: add expectations for each run of underlining.

			var para2 = (ParaBox)para1.Next;
			var stringBox2 = (StringBox)para2.FirstBox;
			var seg2 = (FakeSegment)stringBox2.Segment;
			// For the double red underline, we'll pretend there are two line segments.
			seg2.NextCharPlacementResults.Add(new FakeSegment.CharPlacementResults()
				{ Lefts = new[] { 5, 15 }, Rights = new[] { 10, 20 }, Tops = new[] { 15, 16 } });
			seg2.NextCharPlacementResults.Add(new FakeSegment.CharPlacementResults()
				{ Lefts = new[] { 12 }, Rights = new[] { 22 }, Tops = new[] { 13 } });
			seg2.NextCharPlacementResults.Add(new FakeSegment.CharPlacementResults()
				{ Lefts = new[] { 30 }, Rights = new[] { 41 }, Tops = new[] { 12 } });

			var para3 = (ParaBox)para2.Next;
			var stringBox3 = (StringBox)para3.FirstBox;
			var seg3 = (FakeSegment)stringBox3.Segment;
			seg3.NextCharPlacementResults.Add(new FakeSegment.CharPlacementResults()
				{ Lefts = new[] { 0 }, Rights = new[] { 10 }, Tops = new[] { 11 } });
			seg3.NextCharPlacementResults.Add(new FakeSegment.CharPlacementResults()
				{ Lefts = new[] { 10 }, Rights = new[] { 20 }, Tops = new[] { 11 } });
			seg3.NextCharPlacementResults.Add(new FakeSegment.CharPlacementResults()
				{ Lefts = new[] { 30 }, Rights = new[] { 40 }, Tops = new[] { 11 } });

			// We want to keep track of the sequence of paint operations in all three segments.
			var drawActions = new List<object>();
			seg1.DrawActions = seg2.DrawActions = seg3.DrawActions = drawActions;
			var vg = new MockGraphics();
			vg.DrawActions = drawActions;

			var site = (MockSite)root.Site;
			root.Paint(vg, site.m_transform);
			var paintTrans = site.m_transform;

			// We should have asked about each run of distinct underlining.
			VerifyCharPlacementCall(seg1, 0, "plain".Length, "plain".Length + "underOnYellow".Length,
				paintTrans.SourceRect, paintTrans.DestRect, vg, 1);

			// para/seg 2
			Rect srcRect = paintTrans.SourceRect;
			srcRect.top -= para1.Height;
			srcRect.bottom -= para1.Height;
			VerifyCharPlacementCall(seg2, 0, 0, "doubleRedOnPink".Length,
				srcRect, paintTrans.DestRect, vg, 2);
			VerifyCharPlacementCall(seg2, 0, "doubleRedOnPink".Length, "doubleRedOnPink".Length + "dotted".Length,
				srcRect, paintTrans.DestRect, vg, 1);
			VerifyCharPlacementCall(seg2, 0, "doubleRedOnPink".Length + "dotted".Length,
				"doubleRedOnPink".Length + "dotted".Length + "dottedOnYellow".Length,
				srcRect, paintTrans.DestRect, vg, 1);

			// para/seg 3
			srcRect.top -= para2.Height;
			srcRect.bottom -= para2.Height;
			VerifyCharPlacementCall(seg3, 0, 0, "dashed".Length,
				srcRect, paintTrans.DestRect, vg, 1);
			VerifyCharPlacementCall(seg3, 0, "dashed".Length, "dashed".Length + "dashedRed".Length,
				srcRect, paintTrans.DestRect, vg, 1);
			VerifyCharPlacementCall(seg3, 0, "dashed".Length + "dashedRed".Length,
				"dashed".Length + "dashedRed".Length + "squiggle".Length,
				srcRect, paintTrans.DestRect, vg, 1);
			// Todo: eventually arrange a run where ichBase is non-zero, and check what happens.

			// We want to check a lot of things about the drawing.
			// - all the background color and underline drawing should happen before any of the text drawing.
			// - the right stuff should be drawn to construct the underlines
			// - in particular dotted, dashed, and squiggle underlines should have the gaps and alternations
			// aligned, even if in different segments.

			// Todo: check actual line segs drawn

			int position = 0; // in drawActions
			// Normal calls to Draw have the effect of painting the background. All three backgrounds
			// should be painted before the foreground. First we paint seg1 with background, since it has some.
			VerifyDraw(drawActions, ref position, seg1);
			// Next we draw its one horizontal line of underline.
			VerifyHorzLine(drawActions, ref position, 10, 20, 15, 1, new int[] {int.MaxValue}, 10);

			// Then segment 2's background
			VerifyDraw(drawActions, ref position, seg2);
			// And various lots of underline: double takes 2 per segment
			VerifyHorzLine(drawActions, ref position, 5, 10, 17, 1, new int[] { int.MaxValue }, 5);
			VerifyHorzLine(drawActions, ref position, 5, 10, 15, 1, new int[] { int.MaxValue }, 5);
			VerifyHorzLine(drawActions, ref position, 15, 20, 18, 1, new int[] { int.MaxValue }, 15);
			VerifyHorzLine(drawActions, ref position, 15, 20, 16, 1, new int[] { int.MaxValue }, 15);
			// dotted has non-trivial array of dx values (2 pix each)
			VerifyHorzLine(drawActions, ref position, 12, 22, 13, 1, new int[] { 2, 2 }, 12);
			// dotted has non-trivial array of dx values (2 pix each)
			VerifyHorzLine(drawActions, ref position, 30, 41, 12, 1, new int[] { 2, 2 }, 30);
			// No background in para 3, doesn't get a draw background call.
			//VerifyDraw(drawActions, ref position, seg3);
			// But underlines still drawn in the background phase
			// Dashed line
			VerifyHorzLine(drawActions, ref position, 0, 10, 11, 1, new int[] { 6, 3 }, 0);
			VerifyHorzLine(drawActions, ref position, 10, 20, 11, 1, new int[] { 6, 3 }, 10);
			// Todo: verify line segs drawn for squiggle.
			VerifyLine(drawActions, ref position, 30, 12, 32, 10, ColorUtil.ConvertColorToBGR(Color.Black));
			VerifyLine(drawActions, ref position, 32, 10, 34, 12, ColorUtil.ConvertColorToBGR(Color.Black));
			VerifyLine(drawActions, ref position, 34, 12, 36, 10, ColorUtil.ConvertColorToBGR(Color.Black));
			VerifyLine(drawActions, ref position, 36, 10, 38, 12, ColorUtil.ConvertColorToBGR(Color.Black));
			VerifyLine(drawActions, ref position, 38, 12, 40, 10, ColorUtil.ConvertColorToBGR(Color.Black));
			VerifyNbDraw(drawActions, ref position, seg1);
			VerifyNbDraw(drawActions, ref position, seg2);
			VerifyDraw(drawActions, ref position, seg3);
		}
示例#19
0
		public void ParaSequenceTest()
		{
			var owner = new MockData1(55, 77);
			var styles = new AssembledStyles();
			var root = new RootBoxFdo(styles);
			var layoutInfo = MakeLayoutInfo(int.MaxValue/2, m_gm.VwGraphics, 55);
			SetupFakeRootSite(root);
			var engine = layoutInfo.RendererFactory.GetRenderer(55, m_gm.VwGraphics) as FakeRenderEngine;
			MockSite site = new MockSite();
			int topLazy = 0; // top of the part of the root box that is occupied by the lazy stuff, relative to the top of the root box itself.
			root.Site = site;
			PaintTransform ptrans = new PaintTransform(2, 4, 96, 96, 0, 10, 96, 96);
			site.m_transform = ptrans;
			site.m_vwGraphics = m_gm.VwGraphics;
			root.Builder.Show(LazyDisplay.Of(() => owner.ObjSeq1).Using((bldr, md) => bldr.AddString(() => md.SimpleThree, 55)));
			var heightOfOneItem = layoutInfo.MpToPixelsY(LazyBox<MockData1>.DefaultItemHeight * 1000);
			// This does two things: it makes sure the boxes produced by expanding a lazy box item won't be the SAME size,
			// so we'll get nontrivial changes in root box size; and it makes sure we don't have to expand MORE items than
			// expected based on the height estimate, which could throw off our predictions of what gets expanded.
			// Todo: we need a test where we DO have to expand more items after the initial estimate.
			engine.SegmentHeight = heightOfOneItem + 2;
			root.Layout(layoutInfo);
			VerifyParagraphs(root, new string[0]);

			var child1 = new MockData1(55, 77);
			var child1String = "Hello world, this is a wide string";
			child1.SimpleThree = child1String;
			owner.InsertIntoObjSeq1(0, child1);
			Assert.That(root.FirstBox, Is.TypeOf(typeof(LazyBox<MockData1>)));
			var lazyBox = (LazyBox<MockData1>)root.FirstBox;
			Assert.That(lazyBox.Width, Is.EqualTo(int.MaxValue / 2)); // no margins, should equal avail width.
			Assert.That(lazyBox.Height, Is.EqualTo(heightOfOneItem));
			var lazyTop = lazyBox.Top;
			var lazyBottom = lazyBox.Bottom;
			var oldRootHeight = root.Height;
			int invalidateWidth = lazyBox.Width + 2 * RootBox.InvalidateMargin;
			var expectedInvalidate1 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
				invalidateWidth,
				lazyBox.Height + 2 * RootBox.InvalidateMargin);
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate1));
			site.RectsInvalidatedInRoot.Clear();
			var lazyHookup = ((IHookup) lazyBox).ParentHookup as LazyHookup<MockData1>;
			Assert.That(lazyHookup, Is.Not.Null);
			Assert.That(lazyHookup.Children[0], Is.EqualTo(lazyBox));
			Assert.That(lazyHookup.Children, Has.Count.EqualTo(1));
			root.LazyExpanded += root_LazyExpanded;
			using (var lc = new LayoutCallbacks(root))
			{
				root.PrepareToPaint(layoutInfo, null, 0, 200);
			}
			VerifyParagraphs(root, new [] { child1String });
			Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(1), "expanding lazy box should set up a hookup for the string");
			Assert.That(site.RectsInvalidatedInRoot, Is.Empty, "we don't need to invalidate expanding something that's never been painted");
			VerifyExpandArgs(0, lazyTop + 2, lazyBottom + 2, root.Height - oldRootHeight);
			Assert.That(lazyHookup.Children, Has.Count.EqualTo(1));
			Assert.That(lazyHookup.Children[0], Is.TypeOf(typeof(ItemHookup)), "the lazy box standing for item hookups should have been replaced");

			// Now replace that one object with a list of several. I want to be able to expand two at the start, one at the end,
			// and one in the middle, and leave two lazy boxes behind. Then expand the rest and make them go away. So I need six.
			var values = new MockData1[10];
			for (int i = 0; i < 10; i++)
			{
				values[i] = new MockData1(55, 77);
				values[i].SimpleThree = i.ToString();
			}
			var newValues = values.Take(6).ToArray();
			site.RectsInvalidatedInRoot.Clear();
			int phase2RootHeight = root.Height;
			int phase2RootWidth = root.Width;
			owner.ReplaceObjSeq1(newValues);
			var expectedInvalidate2 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
				phase2RootWidth + 2 * RootBox.InvalidateMargin,
				phase2RootHeight + 2 * RootBox.InvalidateMargin);
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate2), "should invalidate the old replaced paragraph.");
			lazyBox = (LazyBox<MockData1>)root.FirstBox;
			Assert.That(lazyBox.Width, Is.EqualTo(int.MaxValue / 2)); // no margins, should equal avail width.
			Assert.That(root.LastBox, Is.EqualTo(lazyBox), "old paragraph should have been replaced");
			Assert.That(lazyHookup.Children[0], Is.EqualTo(lazyBox), "after second replace we just have the lazy box");
			Assert.That(lazyHookup.Children, Has.Count.EqualTo(1), "should not have anything but lazy box after second replace");
			Assert.That(lazyBox.Height, Is.EqualTo(6*heightOfOneItem));

			// Make it expand the first two items.
			site.RectsInvalidatedInRoot.Clear();
			m_expandArgs.Clear();
			oldRootHeight = root.Height;
			using (var lc = new LayoutCallbacks(root))
			{
				root.PrepareToPaint(layoutInfo, null, 0, heightOfOneItem * 2 - 2);
			}
			VerifyParagraphs(root, new[] { "0", "1", null }); // Should have two paras then lazy box
			Assert.That(newValues[0].SimpleThreeHookupCount, Is.EqualTo(1), "expanding lazy box should set up a hookup for the string");
			Assert.That(newValues[1].SimpleThreeHookupCount, Is.EqualTo(1), "expanding lazy box should set up a hookup for the string");
			Assert.That(site.RectsInvalidatedInRoot, Is.Empty, "we don't need to invalidate expanding something that's never been painted");
			Assert.That(root.Height, Is.Not.EqualTo(oldRootHeight));
			VerifyExpandArgs(0, 2, heightOfOneItem * 2 + 2, root.Height - oldRootHeight); // +2's from root layout offset
			Assert.That(lazyHookup.Children, Has.Count.EqualTo(3));
			Assert.That(lazyHookup.Children[0], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the first expanded item should be inserted");
			Assert.That(lazyHookup.Children[1], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the 2nd expanded item should be inserted");
			Assert.That(lazyHookup.Children[2], Is.TypeOf(typeof(LazyBox<MockData1>)), "the lazy box standing for item hookups should still be there");
			lazyBox = root.FirstBox.Next.Next as LazyBox<MockData1>;
			Assert.That(lazyBox, Is.Not.Null);
			Assert.That(lazyBox.Height, Is.EqualTo(heightOfOneItem * 4));

			int topOfLastItem = lazyBox.Bottom - heightOfOneItem + 2;
			// Make it expand the last item.
			site.RectsInvalidatedInRoot.Clear();
			m_expandArgs.Clear();
			oldRootHeight = root.Height;
			using (var lc = new LayoutCallbacks(root))
			{
				root.PrepareToPaint(layoutInfo, null, topOfLastItem + 2, topOfLastItem + 10);
			}
			VerifyParagraphs(root, new[] { "0", "1", null, "5" }); // Should have two paras then lazy box then last para
			Assert.That(newValues[5].SimpleThreeHookupCount, Is.EqualTo(1), "expanding lazy box should set up a hookup for the string");
			Assert.That(site.RectsInvalidatedInRoot, Is.Empty, "we don't need to invalidate expanding something that's never been painted");
			Assert.That(root.Height, Is.Not.EqualTo(oldRootHeight));
			VerifyExpandArgs(0, topOfLastItem, topOfLastItem + heightOfOneItem, root.Height - oldRootHeight);
			Assert.That(lazyHookup.Children, Has.Count.EqualTo(4));
			Assert.That(lazyHookup.Children[0], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the first expanded item should be inserted");
			Assert.That(lazyHookup.Children[1], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the 2nd expanded item should be inserted");
			Assert.That(lazyHookup.Children[2], Is.TypeOf(typeof(LazyBox<MockData1>)), "the lazy box standing for item hookups should still be there");
			Assert.That(lazyHookup.Children[3], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the last expanded item should be inserted");
			lazyBox = root.FirstBox.Next.Next as LazyBox<MockData1>;
			Assert.That(lazyBox, Is.Not.Null);
			Assert.That(lazyBox.Height, Is.EqualTo(heightOfOneItem * 3));

			// Expand middle item in lazy box, leaving two lazy boxes.
			int topOfMiddleItem = lazyBox.Top + heightOfOneItem + 2;
			site.RectsInvalidatedInRoot.Clear();
			m_expandArgs.Clear();
			oldRootHeight = root.Height;
			using (var lc = new LayoutCallbacks(root))
			{
				root.PrepareToPaint(layoutInfo, null, topOfMiddleItem + 2, topOfMiddleItem + 10);
			}
			VerifyParagraphs(root, new[] { "0", "1", null, "3", null, "5" }); // Should have two paras then lazy box then middle para then another lazy then last para
			Assert.That(newValues[3].SimpleThreeHookupCount, Is.EqualTo(1), "expanding lazy box should set up a hookup for the string");
			Assert.That(site.RectsInvalidatedInRoot, Is.Empty, "we don't need to invalidate expanding something that's never been painted");
			Assert.That(root.Height, Is.Not.EqualTo(oldRootHeight));
			VerifyExpandArgs(0, topOfMiddleItem, topOfMiddleItem + heightOfOneItem, root.Height - oldRootHeight);
			Assert.That(lazyHookup.Children, Has.Count.EqualTo(6));
			Assert.That(lazyHookup.Children[0], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the first expanded item should be inserted");
			Assert.That(lazyHookup.Children[1], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the 2nd expanded item should be inserted");
			Assert.That(lazyHookup.Children[2], Is.TypeOf(typeof(LazyBox<MockData1>)), "the lazy box standing for item hookups should still be there");
			Assert.That(lazyHookup.Children[3], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the last expanded item should be inserted");
			Assert.That(lazyHookup.Children[4], Is.TypeOf(typeof(LazyBox<MockData1>)), "the lazy box standing for item hookups should still be there");
			Assert.That(lazyHookup.Children[5], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the last expanded item should be inserted");
			lazyBox = root.FirstBox.Next.Next as LazyBox<MockData1>;
			Assert.That(lazyBox, Is.Not.Null);
			Assert.That(lazyBox.Height, Is.EqualTo(heightOfOneItem));
			var lazyBox2 = lazyBox.Next.Next as LazyBox<MockData1>;
			Assert.That(lazyBox2, Is.Not.Null);
			Assert.That(lazyBox2.Height, Is.EqualTo(heightOfOneItem));
			// Expand lazy box when it is between two other items. (Also verify expanding two lazy boxes in one PrepareToPaint.)
			int topOfFirstLazy = lazyBox.Top + 2;
			int topOfLastLazy = lazyBox2.Top + 2;
			site.RectsInvalidatedInRoot.Clear();
			m_expandArgs.Clear();
			oldRootHeight = root.Height;
			using (var lc = new LayoutCallbacks(root))
			{
				root.PrepareToPaint(layoutInfo, null, topOfFirstLazy + 2, topOfLastLazy + 2);
			}
			VerifyParagraphs(root, new[] { "0", "1", "2", "3", "4", "5" }); // Should have all the real paragraphs now.
			Assert.That(newValues[2].SimpleThreeHookupCount, Is.EqualTo(1), "expanding lazy box should set up a hookup for the string");
			Assert.That(newValues[4].SimpleThreeHookupCount, Is.EqualTo(1), "expanding lazy box should set up a hookup for the string");
			Assert.That(site.RectsInvalidatedInRoot, Is.Empty, "we don't need to invalidate expanding something that's never been painted");
			Assert.That(root.Height, Is.Not.EqualTo(oldRootHeight));
			var delta = engine.SegmentHeight - heightOfOneItem;
			VerifyExpandArgs(0, topOfFirstLazy, topOfFirstLazy + heightOfOneItem, delta);
			VerifyExpandArgs(1, topOfLastLazy + delta, topOfLastLazy + delta + heightOfOneItem, delta);
			Assert.That(lazyHookup.Children, Has.Count.EqualTo(6));
			Assert.That(lazyHookup.Children[0], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the first expanded item should be inserted");
			Assert.That(lazyHookup.Children[1], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the 2nd expanded item should be inserted");
			Assert.That(lazyHookup.Children[2], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the 3rd expanded item should be inserted");
			Assert.That(lazyHookup.Children[3], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the 4th expanded item should be inserted");
			Assert.That(lazyHookup.Children[4], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the 5th expanded item should be inserted");
			Assert.That(lazyHookup.Children[5], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the last expanded item should be inserted");

			// Now try removing the first two items.
			site.RectsInvalidatedInRoot.Clear();
			int heightOfFirst2Paras = root.FirstBox.Next.Bottom - root.FirstBox.Top;
			int phase3RootWidth = root.Width;
			int phase3RootHeight = root.Height;
			var phase3Values = newValues.Skip(2).ToArray();
			owner.ReplaceObjSeq1(phase3Values);
			var expectedInvalidate3 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
				phase3RootWidth + 2 * RootBox.InvalidateMargin,
				phase3RootHeight + 2 * RootBox.InvalidateMargin);
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate3), "should invalidate the whole old root box; everything changes or moves.");
			VerifyParagraphs(root, new[] {"2", "3", "4", "5" }); // Should have last 4 paragraphs now (not made lazy).

			// Now try removing the last item.
			site.RectsInvalidatedInRoot.Clear();
			int phase4RootWidth = root.Width;
			var phase4Values = phase3Values.Take(3).ToArray();
			var topOfPara4 = root.FirstBox.Next.Next.Bottom + topLazy;
			owner.ReplaceObjSeq1(phase4Values);
			var expectedInvalidate4 = new Rectangle(-RootBox.InvalidateMargin, topOfPara4 - RootBox.InvalidateMargin,
				phase4RootWidth + 2 * RootBox.InvalidateMargin,
				root.FirstBox.Height + 2 * RootBox.InvalidateMargin);
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate4), "should invalidate the old replaced paragraphs.");
			VerifyParagraphs(root, new[] { "2", "3", "4" }); // Should have last 3 paragraphs now (not made lazy).

			// Now try removing a middle item.
			site.RectsInvalidatedInRoot.Clear();
			int phase5RootWidth = root.Width;
			var phase5Values = new [] {newValues[2], newValues[4]};
			var topOfPara3 = root.FirstBox.Bottom + topLazy;
			var phase4RootHeight = root.Height;
			owner.ReplaceObjSeq1(phase5Values);
			var expectedInvalidate5 = new Rectangle(-RootBox.InvalidateMargin, topOfPara3 - RootBox.InvalidateMargin,
				phase5RootWidth + 2 * RootBox.InvalidateMargin,
				phase4RootHeight - topOfPara3 + 2 * RootBox.InvalidateMargin);
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate5), "should invalidate the old replaced paragraphs.");
			VerifyParagraphs(root, new[] { "2", "4" }); // Should have remaining 2 paragraphs now (not made lazy).

			// Insert three items at start: 0, 1, 3, 2, 4.
			site.RectsInvalidatedInRoot.Clear();
			int phase6RootWidth = root.Width;
			var phase6Values = new[] {newValues[0], newValues[1], newValues[3], newValues[2], newValues[4] };
			owner.ReplaceObjSeq1(phase6Values);
			int lazyWidth = root.LastLayoutInfo.MaxWidth; // current standard width for lazy boxes.
			var expectedInvalidate6 = new Rectangle(-RootBox.InvalidateMargin, topLazy - RootBox.InvalidateMargin,
				lazyWidth + 2 * RootBox.InvalidateMargin,
				root.Height + 2 * RootBox.InvalidateMargin);
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate6), "should invalidate everything...all moved or added.");
			VerifyParagraphs(root, new[] {null, "2", "4" }); // Should have added lazy box at start.
			VerifyLazyContents(root.FirstBox, new[] {newValues[0], newValues[1], newValues[3]});

			// Insert at end: 0, 1, 3, 2, 4, 9. I think we've tested the invalidate rects enough.
			var phase7Values = new[] { values[0], values[1], values[3], values[2], values[4], values[9] };
			owner.ReplaceObjSeq1(phase7Values);
			VerifyParagraphs(root, new[] { null, "2", "4", null }); // Should have added lazy box at end.
			VerifyLazyContents(root.LastBox, new[] { values[9] });
			// Insert between two non-lazy items: 0, 1, 3, 2, 5, 6, 4, 9.
			var phase8Values = new[] { values[0], values[1], values[3], values[2], values[5], values[6], values[4], values[9] };
			owner.ReplaceObjSeq1(phase8Values);
			VerifyParagraphs(root, new[] { null, "2", null, "4", null }); // Should have added lazy box in middle.
			VerifyLazyContents(root.FirstBox.Next.Next, new[] { values[5], values[6] });
			// Try a more complex overwrite. We'll replace the last item in the first lazy box and the first one in the second
			var phase9Values = new[] { values[0], values[1], values[7], values[2], values[8], values[6], values[4], values[9] };
			owner.ReplaceObjSeq1(phase9Values);
			VerifyParagraphs(root, new[] { null, "4", null }); // Should replace first 3 items with new lazy box.
			VerifyLazyContents(root.FirstBox, new[] { values[0], values[1], values[7], values[2], values[8], values[6] });
		}
示例#20
0
		public void MlsDelete()
		{
			var styles = new AssembledStyles();
			var root = new RootBoxFdo(styles.WithWs(23));
			var mock1 = new MockData1(23, 23);
			mock1.MlSimpleOne = new MultiAccessor(23, 23);
			mock1.MlSimpleOne.set_String(23, TsStrFactoryClass.Create().MakeString("This is it", 23));
			var engine = new FakeRenderEngine() { Ws = 23, SegmentHeight = 13 };
			var factory = new FakeRendererFactory();
			factory.SetRenderer(23, engine);
			root.Builder.Show(Display.Of(() => mock1.MlSimpleOne, 23));
			var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			PaintTransform ptrans = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96);
			MockSite site = new MockSite();
			site.m_transform = ptrans;
			site.m_vwGraphics = m_gm.VwGraphics;
			root.Site = site;

			SelectionBuilder.In(root).Offset("This ".Length).To.Offset("This is ".Length).Install();
			var sel = root.Selection as RangeSelection;
			// This is currently the main test for SelectionBuilder.In(RootBox) and SelectionBuilder.To in TsStrings
			// This verifies that it makes roughly the right range selection.
			Assert.That(sel.Anchor.LogicalParaPosition, Is.EqualTo("This ".Length));
			Assert.That(sel.DragEnd.LogicalParaPosition, Is.EqualTo("This is ".Length));

			Assert.That(sel.CanDelete(), Is.True);
			root.OnDelete();
			ITsString i = mock1.MlSimpleOne.get_String(23);
			Assert.That(mock1.MlSimpleOne.get_String(23).Text, Is.EqualTo("This it"));
			var ip = root.Selection as InsertionPoint;
			Assert.That(ip.LogicalParaPosition, Is.EqualTo("This ".Length));
			// Enhance JohnT: if there is any reason to prefer associatePrevious to be true or false,
			// clamp that and make it so.
			// A fairly rudimentary check on invalidate, since we elsewhere check general string-edit ops.
			Assert.That(site.RectsInvalidatedInRoot, Is.Not.Empty);
		}
示例#21
0
		public void BasicDrop()
		{
			var styles = new AssembledStyles();
			var root = new RootBoxFdo(styles);
			var mock1 = new MockData1(23, 23);
			mock1.SimpleThree = "old contents";
			var engine = new FakeRenderEngine() { Ws = 23, SegmentHeight = 13 };
			var factory = new FakeRendererFactory();
			factory.SetRenderer(23, engine);
			root.Builder.Show(Display.Of(() => mock1.SimpleThree, 23));
			var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			PaintTransform ptrans = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96);
			MockSite site = new MockSite();
			site.m_transform = ptrans;
			site.m_vwGraphics = m_gm.VwGraphics;
			root.Site = site;

			var dataObj = new DataObject(DataFormats.StringFormat, "new ");
			int x = FakeRenderEngine.SimulatedWidth("old ") + 2;
			var location = new Point(x, 8);

			// A drag to where we can drop, allowing both copy and move, no keys held
			var dragArgs = new DragEventArgs(dataObj, (int) DragDropKeyStates.None, 200,300,
				DragDropEffects.Copy | DragDropEffects.Move,
				DragDropEffects.None);
			root.OnDragEnter(dragArgs, location, m_gm.VwGraphics, ptrans);
			Assert.That(dragArgs.Effect, Is.EqualTo(DragDropEffects.Move));
			Assert.That(root.DragState, Is.EqualTo(WindowDragState.DraggingHere));
			root.OnDragLeave();
			Assert.That(root.DragState, Is.EqualTo(WindowDragState.None));

			// Though other factors would favor move, only copy is allowed here.
			dragArgs = new DragEventArgs(dataObj, (int)DragDropKeyStates.None, 200,300,
				DragDropEffects.Copy,
				DragDropEffects.None);
			root.OnDragEnter(dragArgs, location, m_gm.VwGraphics, ptrans);
			Assert.That(dragArgs.Effect, Is.EqualTo(DragDropEffects.Copy));

			// Though otherwise we could copy, there is no text data in the data object.
			dragArgs = new DragEventArgs(new DataObject(), (int)DragDropKeyStates.None, 200,300,
				DragDropEffects.Copy | DragDropEffects.Move,
				DragDropEffects.None);
			root.OnDragEnter(dragArgs, location, m_gm.VwGraphics, ptrans);
			Assert.That(dragArgs.Effect, Is.EqualTo(DragDropEffects.None));

			dragArgs = new DragEventArgs(dataObj, (int)DragDropKeyStates.ControlKey, 200,300,
				DragDropEffects.Copy | DragDropEffects.Move,
				DragDropEffects.None);
			root.OnDragEnter(dragArgs, location, m_gm.VwGraphics, ptrans);
			Assert.That(dragArgs.Effect, Is.EqualTo(DragDropEffects.Copy));

			root.OnDragDrop(dragArgs, location, m_gm.VwGraphics, ptrans);
			Assert.That(mock1.SimpleThree, Is.EqualTo("old new contents"));
		}
示例#22
0
        public void ParaSequenceTest()
        {
            var owner      = new MockData1(55, 77);
            var styles     = new AssembledStyles();
            var root       = new RootBoxFdo(styles);
            var layoutInfo = MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);

            SetupFakeRootSite(root);
            var      engine = layoutInfo.RendererFactory.GetRenderer(55, m_gm.VwGraphics) as FakeRenderEngine;
            MockSite site   = new MockSite();

            root.Site = site;
            PaintTransform ptrans = new PaintTransform(2, 4, 96, 100, 0, 10, 120, 128);

            site.m_transform  = ptrans;
            site.m_vwGraphics = m_gm.VwGraphics;
            root.Builder.Show(Display.Of(() => owner.ObjSeq1).Using((bldr, md) => bldr.AddString(() => md.SimpleThree, 55)));
            root.Layout(layoutInfo);
            VerifyParagraphs(root, new string[0]);
            //var seqHookup = new IndependentSequenceHookup<MockData1>(owner);

            // Tell seqHookup how to make a display of one MockData1:
            //  - make a paragraph
            //  - make it display the SimpleDataThree property of the item (editable)
            //  - Make an item hookup that knows about the paragraph and the StringHookup for SimpleDataThree
            //  - that hookup should be connected to the Item Hookup

            // Tell seqHookup how it relates to the root box
            //  - Somehow the item hookup for each item gets inserted into the right place in seqHookup's children,
            //  - and the paragraph for the item gets inserted into the right place in the rootbox.

            // Tell seqHookup to get its items from ObjSeq1 and to listen for ObjSeq1Changed.

            // (Eventually I'd like to be able to do all the above something like this:
            // root.Builder.AddObjSeq(()=>owner.ObjSeq1, (md, bldr)=>bldr.AddString(()=>md.SimpleThree);

            // Insert the first item into owner.ObjSeq1 and check all the right connections appear
            var child1       = new MockData1(55, 77);
            var child1String = "Hello world, this is a wide string";

            child1.SimpleThree = child1String;
            owner.InsertIntoObjSeq1(0, child1);
            // The first string we insert is deliberately the widest. After that, the width of the pile
            // remains constant, allowing us to test smarter, smaller invalidate rectangles; when the width
            // changes we invalidate the whole pile.
            VerifyParagraphs(root, new string[] { child1String });
            Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(1), "Builder.AddString should set up a hookup for the string");
            int invalidateWidth     = FakeRenderEngine.SimulatedWidth(child1String) + 2 * RootBox.InvalidateMargin;
            var expectedInvalidate1 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
                                                    invalidateWidth,
                                                    engine.SegmentHeight + 2 * RootBox.InvalidateMargin);

            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate1));

            // Insert a second item and check again.
            var child2 = new MockData1(55, 77);

            child2.SimpleThree = "Another world";
            site.RectsInvalidated.Clear();
            owner.InsertIntoObjSeq1(1, child2);
            VerifyParagraphs(root, new string[] { child1String, "Another world" });
            Assert.That(child2.SimpleThreeHookupCount, Is.EqualTo(1), "Builder.AddString should set up a hookup for the string");
            var expectedInvalidate2 = new Rectangle(-RootBox.InvalidateMargin,
                                                    engine.SegmentHeight - RootBox.InvalidateMargin,
                                                    invalidateWidth,
                                                    engine.SegmentHeight + 2 * RootBox.InvalidateMargin);

            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate2));

            // Insert a third item between the first two.
            var child3 = new MockData1(55, 77);

            child3.SimpleThree = "Inserted world";
            owner.InsertIntoObjSeq1(1, child3);
            VerifyParagraphs(root, new string[] { child1String, "Inserted world", "Another world" });
            var expectedInvalidate3 = new Rectangle(-RootBox.InvalidateMargin,
                                                    engine.SegmentHeight - RootBox.InvalidateMargin,
                                                    invalidateWidth,
                                                    engine.SegmentHeight * 2 + 2 * RootBox.InvalidateMargin);

            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate3));

            // Insert a fourth item at the start.
            var child4 = new MockData1(55, 77);

            child4.SimpleThree = "Beginning of world";
            owner.InsertIntoObjSeq1(0, child4);
            VerifyParagraphs(root, new string[] { "Beginning of world", child1String, "Inserted world", "Another world" });
            var expectedInvalidate4 = new Rectangle(-RootBox.InvalidateMargin,
                                                    -RootBox.InvalidateMargin,
                                                    invalidateWidth,
                                                    engine.SegmentHeight * 4 + 2 * RootBox.InvalidateMargin);

            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate4));

            // Delete the first item.
            //var topHookup = root.RootHookup as IndependentSequenceHookup<MockData1>;
            //Assert.That(topHookup, Is.Not.Null);
            owner.RemoveAtObjSeq1(0);
            VerifyParagraphs(root, new string[] { child1String, "Inserted world", "Another world" });
            Assert.That(child4.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for a deleted object should be disposed.");
            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate4));

            // Delete a middle item.
            owner.RemoveAtObjSeq1(1);
            VerifyParagraphs(root, new string[] { child1String, "Another world" });
            Assert.That(child3.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for a deleted object should be disposed.");
            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate3));

            // Delete the last item.
            owner.RemoveAtObjSeq1(1);
            VerifyParagraphs(root, new string[] { child1String });
            Assert.That(child2.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for a deleted object should be disposed.");
            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate2));

            // Delete the only remaining item.
            owner.RemoveAtObjSeq1(0);
            VerifyParagraphs(root, new string[0]);
            Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for a deleted object should be disposed.");
            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate1));

            // Eventually add some operations that allow inserting and deleting multiple items.

            // We also need to be able to insert two or more object sequences into the same containing box.
            // That's probably another test, perhaps a view of the root where for each data item,
            // we insert its subitems, then for those insert paragraphs.
            // Let's assume there's always one top-level hookup for the root.
        }
示例#23
0
		public void ParaObjTest()
		{
			var owner = new MockData1(55, 77);
			var child1 = new MockData1(55, 77);
			var child1String = "Hello world, this is a wide string";
			child1.SimpleThree = child1String;
			owner.SimpleFour = child1;
			var styles = new AssembledStyles();
			var root = new RootBoxFdo(styles);
			var layoutInfo = MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);
			SetupFakeRootSite(root);
			var engine = layoutInfo.RendererFactory.GetRenderer(55, m_gm.VwGraphics) as FakeRenderEngine;
			MockSite site = new MockSite();
			root.Site = site;
			PaintTransform ptrans = new PaintTransform(2, 4, 96, 100, 0, 10, 120, 128);
			site.m_transform = ptrans;
			site.m_vwGraphics = m_gm.VwGraphics;
			root.Builder.Show(Display.OfObj(() => owner.SimpleFour).Using((bldr, md) => bldr.AddString(() => md.SimpleThree, 55)));
			root.Layout(layoutInfo);
			VerifyParagraphs(root, new[] { child1String });

			Assert.That(owner.SimpleFourHookupCount, Is.EqualTo(1), "Builder.AddString should set up a hookup for the string");
			Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(1), "Builder.AddString should set up a hookup for the string");
			int invalidateWidth = FakeRenderEngine.SimulatedWidth(child1String) + 2 * RootBox.InvalidateMargin;

			// Change item and check side effects.
			var child2 = new MockData1(55, 77);
			child2.SimpleThree = "Another world";
			site.RectsInvalidated.Clear();
			owner.SimpleFour = child2;
			VerifyParagraphs(root, new string[] { "Another world" });
			Assert.That(child2.SimpleThreeHookupCount, Is.EqualTo(1), "Builder.AddString should set up a hookup for the string");
			var expectedInvalidate1 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
				invalidateWidth, engine.SegmentHeight + 2 * RootBox.InvalidateMargin);
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate1));
		}
示例#24
0
        public void DiffWS()
        {
            var tsf    = TsStrFactoryClass.Create();
            var styles = new AssembledStyles();
            var root   = new RootBoxFdo(styles);
            var mock1  = new MockData1(23, 23);

            mock1.SimpleTwo = tsf.MakeString("newoldcontents", 23);
            var bldr = mock1.SimpleTwo.GetBldr();

            bldr.SetIntPropValues(3, 6, (int)FwTextPropType.ktptWs,
                                  (int)FwTextPropVar.ktpvDefault, 24);
            bldr.SetIntPropValues(6, 14, (int)FwTextPropType.ktptWs,
                                  (int)FwTextPropVar.ktpvDefault, 25);
            mock1.SimpleTwo = bldr.GetString();
            var engine = new FakeRenderEngine()
            {
                Ws = 23, SegmentHeight = 13
            };
            var factory = new FakeRendererFactory();

            factory.SetRenderer(23, engine);
            root.Builder.Show(Display.Of(() => mock1.SimpleTwo));
            var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);

            root.Layout(layoutArgs);
            PaintTransform ptrans = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96);
            MockSite       site   = new MockSite();

            site.m_transform  = ptrans;
            site.m_vwGraphics = m_gm.VwGraphics;
            root.Site         = site;

            int            x        = FakeRenderEngine.SimulatedWidth("ne") + 2;
            var            location = new Point(x, 8);
            EventArgs      e        = new EventArgs();
            MouseEventArgs m        = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);

            root.OnMouseDown(m, Keys.None, site.m_vwGraphics, site.m_transform);
            root.OnMouseClick(m, Keys.None, site.m_vwGraphics, site.m_transform);
            root.OnDoubleClick(e);
            Assert.That(!root.Selection.IsInsertionPoint, "Should be ranged selection");
            Assert.That((root.Selection as RangeSelection).SelectedText(), Is.EqualTo("new"));

            x        = FakeRenderEngine.SimulatedWidth("new") + 2;
            location = new Point(x, 8);
            m        = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);
            root.OnMouseDown(m, Keys.None, site.m_vwGraphics, site.m_transform);
            root.OnMouseClick(m, Keys.None, site.m_vwGraphics, site.m_transform);
            root.OnDoubleClick(e);
            Assert.That(!root.Selection.IsInsertionPoint, "Should be ranged selection");
            Assert.That((root.Selection as RangeSelection).SelectedText(), Is.EqualTo("old"));

            x        = FakeRenderEngine.SimulatedWidth("newold") + 2;
            location = new Point(x, 8);
            m        = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);
            root.OnMouseDown(m, Keys.None, site.m_vwGraphics, site.m_transform);
            root.OnMouseClick(m, Keys.None, site.m_vwGraphics, site.m_transform);
            root.OnDoubleClick(e);
            Assert.That(!root.Selection.IsInsertionPoint, "Should be ranged selection");
            Assert.That((root.Selection as RangeSelection).SelectedText(), Is.EqualTo("contents"));

            x        = FakeRenderEngine.SimulatedWidth("newold");
            location = new Point(x, 8);             // at the right edge of the d at the end of newold
            m        = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);
            root.OnMouseDown(m, Keys.None, site.m_vwGraphics, site.m_transform);
            root.OnMouseClick(m, Keys.None, site.m_vwGraphics, site.m_transform);
            root.OnDoubleClick(e);
            Assert.That(!root.Selection.IsInsertionPoint, "Should be ranged selection");
            Assert.That((root.Selection as RangeSelection).SelectedText(), Is.EqualTo("old"));
        }
        public void CombinedParaOperations()
        {
            // Set up a simple multi-para layout using the ObjSeq2 and SimpleThree properties of MockData1
            AssembledStyles styles = new AssembledStyles();
            RootBox         root   = new RootBoxFdo(styles);
            var             owner  = new MockData1();
            var             p1     = new MockData1(10, 11);
            var             p2     = new MockData1(10, 11);

            p1.SimpleThree = "Hello World";
            p2.SimpleThree = "This is a test";
            owner.ObjSeq2.Add(p1);
            owner.ObjSeq2.Add(p2);
            var po = new MockReceiveParagraphOperations();

            root.Builder.Show(Display.Of(() => owner.ObjSeq2)
                              .Using((builder, para) => builder.AddString(() => para.SimpleThree, 10))
                              .EditParagraphsUsing(po));
            SetupFakeRootSite(root);
            var layoutInfo = HookupTests.MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);

            root.Layout(layoutInfo);
            var ip = root.FirstBox.SelectAtEnd();

            // Insert at end of paragraph.
            ip.InsertLineBreak();
            Assert.That(owner.ObjSeq2.Count, Is.EqualTo(3));
            Assert.That(owner.ObjSeq2[0], Is.EqualTo(p1));
            Assert.That(owner.ObjSeq2[2], Is.EqualTo(p2));
            var p3 = owner.ObjSeq2[1];             // empty inserted paragraph.

            ((MockSite)root.Site).DoPendingAfterNotificationTasks();
            ip = (InsertionPoint)root.Selection;
            Assert.That(root.FirstBox.Next.Next, Is.Not.Null);
            Assert.That(ip.StringPosition, Is.EqualTo(0));
            Assert.That(ip.Para, Is.EqualTo(root.FirstBox.Next));

            // Insert at start of paragraph. To make it unambiguously the start, give p3 some data,
            // and since that might eventually destroy the selection, reset it.
            var rootHookup = ip.Hookup.ParentHookup.ParentHookup;             // StringHookup, ItemHookup, Sequence

            p3.SimpleThree = "First insert";
            ip             = (InsertionPoint)SelectionBuilder.In(rootHookup)[1].Offset(0).Install();
            ip.InsertLineBreak();
            Assert.That(owner.ObjSeq2.Count, Is.EqualTo(4));
            Assert.That(owner.ObjSeq2[0], Is.EqualTo(p1));
            Assert.That(owner.ObjSeq2[2], Is.EqualTo(p3));
            Assert.That(owner.ObjSeq2[3], Is.EqualTo(p2));
            var p4 = owner.ObjSeq2[1];             // empty inserted paragraph (before p3).

            Assert.That(root.FirstBox.Next.Next.Next, Is.Not.Null);
            ((MockSite)root.Site).DoPendingAfterNotificationTasks();
            ip = (InsertionPoint)root.Selection;
            Assert.That(ip.StringPosition, Is.EqualTo(0));
            Assert.That(ip.Para, Is.EqualTo(root.FirstBox.Next.Next));

            // Split a paragraph.
            var oldObjects = owner.ObjSeq2.ToArray();

            ip = (InsertionPoint)SelectionBuilder.In(rootHookup)[2].Offset("First ".Length).Install();
            ip.InsertLineBreak();
            Assert.That(owner.ObjSeq2.Count, Is.EqualTo(5));
            Assert.That(owner.ObjSeq2[1], Is.EqualTo(oldObjects[1]));
            Assert.That(owner.ObjSeq2[2], Is.EqualTo(oldObjects[2]));
            Assert.That(owner.ObjSeq2[4], Is.EqualTo(oldObjects[3])); // insert between 2 and 3
            var p5 = owner.ObjSeq2[3];                                // inserted paragraph.

            ((MockSite)root.Site).DoPendingAfterNotificationTasks();
            ip = (InsertionPoint)root.Selection;
            Assert.That(ip.StringPosition, Is.EqualTo(0));
            Assert.That(ip.Para, Is.EqualTo(root.FirstBox.Next.Next.Next));
            Assert.That(owner.ObjSeq2[2].SimpleThree, Is.EqualTo("First "));
            Assert.That(owner.ObjSeq2[3].SimpleThree, Is.EqualTo("insert"));

            // Combine two paragraphs by backspace at start of line.
            oldObjects = owner.ObjSeq2.ToArray();
            ip.Backspace();
            Assert.That(owner.ObjSeq2.Count, Is.EqualTo(4));
            Assert.That(owner.ObjSeq2[1], Is.EqualTo(oldObjects[1]));
            Assert.That(owner.ObjSeq2[2], Is.EqualTo(oldObjects[2]));
            Assert.That(owner.ObjSeq2[3], Is.EqualTo(oldObjects[4]));             // delete item 3
            ((MockSite)root.Site).DoPendingAfterNotificationTasks();
            ip = (InsertionPoint)root.Selection;
            Assert.That(ip.StringPosition, Is.EqualTo("First ".Length));
            Assert.That(ip.Para, Is.EqualTo(root.FirstBox.Next.Next));
            Assert.That(owner.ObjSeq2[2].SimpleThree, Is.EqualTo("First insert"));
        }
示例#26
0
		public void ParaSequenceTest()
		{
			var owner = new MockData1(55, 77);
			var styles = new AssembledStyles();
			var root = new RootBoxFdo(styles);
			var layoutInfo = MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);
			SetupFakeRootSite(root);
			var engine = layoutInfo.RendererFactory.GetRenderer(55, m_gm.VwGraphics) as FakeRenderEngine;
			MockSite site = new MockSite();
			root.Site = site;
			PaintTransform ptrans = new PaintTransform(2, 4, 96, 100, 0, 10, 120, 128);
			site.m_transform = ptrans;
			site.m_vwGraphics = m_gm.VwGraphics;
			root.Builder.Show(Display.Of(() => owner.ObjSeq1).Using((bldr, md) => bldr.AddString(() => md.SimpleThree, 55)));
			root.Layout(layoutInfo);
			VerifyParagraphs(root, new string[0]);
			//var seqHookup = new IndependentSequenceHookup<MockData1>(owner);

			// Tell seqHookup how to make a display of one MockData1:
			//  - make a paragraph
			//  - make it display the SimpleDataThree property of the item (editable)
			//  - Make an item hookup that knows about the paragraph and the StringHookup for SimpleDataThree
			//  - that hookup should be connected to the Item Hookup

			// Tell seqHookup how it relates to the root box
			//  - Somehow the item hookup for each item gets inserted into the right place in seqHookup's children,
			//  - and the paragraph for the item gets inserted into the right place in the rootbox.

			// Tell seqHookup to get its items from ObjSeq1 and to listen for ObjSeq1Changed.

			// (Eventually I'd like to be able to do all the above something like this:
			// root.Builder.AddObjSeq(()=>owner.ObjSeq1, (md, bldr)=>bldr.AddString(()=>md.SimpleThree);

			// Insert the first item into owner.ObjSeq1 and check all the right connections appear
			var child1 = new MockData1(55, 77);
			var child1String = "Hello world, this is a wide string";
			child1.SimpleThree = child1String;
			owner.InsertIntoObjSeq1(0, child1);
			// The first string we insert is deliberately the widest. After that, the width of the pile
			// remains constant, allowing us to test smarter, smaller invalidate rectangles; when the width
			// changes we invalidate the whole pile.
			VerifyParagraphs(root, new string[] { child1String });
			Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(1), "Builder.AddString should set up a hookup for the string");
			int invalidateWidth = FakeRenderEngine.SimulatedWidth(child1String) + 2 * RootBox.InvalidateMargin;
			var expectedInvalidate1 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
				invalidateWidth,
				engine.SegmentHeight + 2 * RootBox.InvalidateMargin);
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate1));

			// Insert a second item and check again.
			var child2 = new MockData1(55, 77);
			child2.SimpleThree = "Another world";
			site.RectsInvalidated.Clear();
			owner.InsertIntoObjSeq1(1, child2);
			VerifyParagraphs(root, new string[] { child1String, "Another world" });
			Assert.That(child2.SimpleThreeHookupCount, Is.EqualTo(1), "Builder.AddString should set up a hookup for the string");
			var expectedInvalidate2 = new Rectangle(-RootBox.InvalidateMargin,
							engine.SegmentHeight - RootBox.InvalidateMargin,
							invalidateWidth,
							engine.SegmentHeight + 2 * RootBox.InvalidateMargin);
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate2));

			// Insert a third item between the first two.
			var child3 = new MockData1(55, 77);
			child3.SimpleThree = "Inserted world";
			owner.InsertIntoObjSeq1(1, child3);
			VerifyParagraphs(root, new string[] { child1String, "Inserted world", "Another world" });
			var expectedInvalidate3 = new Rectangle(-RootBox.InvalidateMargin,
							engine.SegmentHeight - RootBox.InvalidateMargin,
							invalidateWidth,
							engine.SegmentHeight * 2 + 2 * RootBox.InvalidateMargin);
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate3));

			// Insert a fourth item at the start.
			var child4 = new MockData1(55, 77);
			child4.SimpleThree = "Beginning of world";
			owner.InsertIntoObjSeq1(0, child4);
			VerifyParagraphs(root, new string[] { "Beginning of world", child1String, "Inserted world", "Another world" });
			var expectedInvalidate4 = new Rectangle(-RootBox.InvalidateMargin,
							- RootBox.InvalidateMargin,
							invalidateWidth,
							engine.SegmentHeight * 4 + 2 * RootBox.InvalidateMargin);
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate4));

			// Delete the first item.
			//var topHookup = root.RootHookup as IndependentSequenceHookup<MockData1>;
			//Assert.That(topHookup, Is.Not.Null);
			owner.RemoveAtObjSeq1(0);
			VerifyParagraphs(root, new string[] { child1String, "Inserted world", "Another world" });
			Assert.That(child4.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for a deleted object should be disposed.");
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate4));

			// Delete a middle item.
			owner.RemoveAtObjSeq1(1);
			VerifyParagraphs(root, new string[] { child1String, "Another world" });
			Assert.That(child3.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for a deleted object should be disposed.");
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate3));

			// Delete the last item.
			owner.RemoveAtObjSeq1(1);
			VerifyParagraphs(root, new string[] { child1String });
			Assert.That(child2.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for a deleted object should be disposed.");
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate2));

			// Delete the only remaining item.
			owner.RemoveAtObjSeq1(0);
			VerifyParagraphs(root, new string[0]);
			Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for a deleted object should be disposed.");
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate1));

			// Eventually add some operations that allow inserting and deleting multiple items.

			// We also need to be able to insert two or more object sequences into the same containing box.
			// That's probably another test, perhaps a view of the root where for each data item,
			// we insert its subitems, then for those insert paragraphs.
			// Let's assume there's always one top-level hookup for the root.
		}
示例#27
0
        public void NumericSurrogates()
        {
            var styles = new AssembledStyles();
            var root   = new RootBoxFdo(styles);
            var mock1  = new MockData1(23, 23);

            mock1.SimpleThree = "new o" + NumericSurrogatePair + "ld contents";
            var engine = new FakeRenderEngine()
            {
                Ws = 23, SegmentHeight = 13
            };
            var factory = new FakeRendererFactory();

            factory.SetRenderer(23, engine);
            root.Builder.Show(Paragraph.Containing(Display.Of(() => mock1.SimpleThree, 23)));
            var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);

            root.Layout(layoutArgs);
            PaintTransform ptrans = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96);
            MockSite       site   = new MockSite();

            site.m_transform  = ptrans;
            site.m_vwGraphics = m_gm.VwGraphics;
            root.Site         = site;

            int            x        = FakeRenderEngine.SimulatedWidth("new ol") + 2;
            var            location = new Point(x, 8);
            EventArgs      e        = new EventArgs();
            MouseEventArgs m        = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);
            string         test     = "o" + NumericSurrogatePair + "ld ";

            root.OnMouseDown(m, Keys.None, site.m_vwGraphics, site.m_transform);
            root.OnMouseClick(m, Keys.None, site.m_vwGraphics, site.m_transform);
            root.OnDoubleClick(e);
            Assert.That(!root.Selection.IsInsertionPoint, "Should be ranged selection");
            Assert.That((root.Selection as RangeSelection).SelectedText(), Is.EqualTo(test));

            x        = FakeRenderEngine.SimulatedWidth("new ") + 2;
            location = new Point(x, 8);
            m        = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);
            root.OnMouseDown(m, Keys.None, site.m_vwGraphics, site.m_transform);
            root.OnMouseClick(m, Keys.None, site.m_vwGraphics, site.m_transform);
            root.OnDoubleClick(e);
            Assert.That(!root.Selection.IsInsertionPoint, "Should be ranged selection");
            Assert.That((root.Selection as RangeSelection).SelectedText(), Is.EqualTo(test));

            x        = FakeRenderEngine.SimulatedWidth("new old") + 2;
            location = new Point(x, 8);
            m        = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);
            root.OnMouseDown(m, Keys.None, site.m_vwGraphics, site.m_transform);
            root.OnMouseClick(m, Keys.None, site.m_vwGraphics, site.m_transform);
            root.OnDoubleClick(e);
            Assert.That(!root.Selection.IsInsertionPoint, "Should be ranged selection");
            Assert.That((root.Selection as RangeSelection).SelectedText(), Is.EqualTo(test));

            mock1.SimpleThree = "new " + NumericSurrogatePair + " contents";
            x        = FakeRenderEngine.SimulatedWidth("new o") + 2;
            location = new Point(x, 8);
            m        = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);
            test     = NumericSurrogatePair + " ";

            root.OnMouseDown(m, Keys.None, site.m_vwGraphics, site.m_transform);
            root.OnMouseClick(m, Keys.None, site.m_vwGraphics, site.m_transform);
            root.OnDoubleClick(e);
            Assert.That(!root.Selection.IsInsertionPoint, "Should be ranged selection");
            Assert.That((root.Selection as RangeSelection).SelectedText(), Is.EqualTo(test));

            x        = FakeRenderEngine.SimulatedWidth("new ") + 2;
            location = new Point(x, 8);
            m        = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);
            root.OnMouseDown(m, Keys.None, site.m_vwGraphics, site.m_transform);
            root.OnMouseClick(m, Keys.None, site.m_vwGraphics, site.m_transform);
            root.OnDoubleClick(e);
            Assert.That(!root.Selection.IsInsertionPoint, "Should be ranged selection");
            Assert.That((root.Selection as RangeSelection).SelectedText(), Is.EqualTo(test));
        }
示例#28
0
		public void ParaSequenceWithInitialContent()
		{
			var owner = new MockData1(55, 77);
			var child1 = new MockData1(55, 77);
			var child2 = new MockData1(55, 77);
			owner.InsertIntoObjSeq1(0, child1);
			owner.InsertIntoObjSeq1(1, child2);
			child1.SimpleThree = "Hello World. ";
			child2.SimpleThree = "This is a test.";

			var styles = new AssembledStyles();
			var root = new RootBoxFdo(styles);
			var layoutInfo = MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);
			SetupFakeRootSite(root);
			root.Builder.Show(Display.Of(() => owner.ObjSeq1).Using((bldr, md) => bldr.AddString(() => md.SimpleThree, 55)));
			root.Layout(layoutInfo);
			// Two children produces two paragraphs.
			Assert.That(root.FirstBox, Is.AssignableTo(typeof(ParaBox)));
			Assert.That(root.FirstBox.Next, Is.AssignableTo(typeof(ParaBox)));
			Assert.That(root.FirstBox.Next.Next, Is.Null);
		}
示例#29
0
        public void DragStartsOnMoveInSelection()
        {
            string contents = "This is the day.";
            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 source   = new TextSource(clientRuns, null);
            var para     = new ParaBox(styles, source);
            var extraBox = new BlockBox(styles, Color.Red, 50, 72000);             // tall, narrow spacer at top
            var root     = new RootBoxFdo(styles);

            root.AddBox(extraBox);
            root.AddBox(para);
            var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);

            root.Layout(layoutArgs);
            Assert.That(root.Height, Is.EqualTo(96 + 13));
            Assert.That(root.Width, Is.EqualTo(FakeRenderEngine.SimulatedWidth(contents)));

            var ip1   = run.SelectAt(para, 5, false);
            var ip2   = run.SelectAt(para, 7, true);
            var range = new RangeSelection(ip1, ip2);

            range.Install();
            PaintTransform ptrans = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96);
            var            sbox   = para.FirstBox as StringBox;
            MockSite       site   = new MockSite();

            site.m_transform  = ptrans;
            site.m_vwGraphics = m_gm.VwGraphics;
            root.Site         = site;
            int indent = FakeRenderEngine.SimulatedWidth("This ");

            root.OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, indent + 5, 100, 0), Keys.None, m_gm.VwGraphics, ptrans);
            root.OnMouseMove(new MouseEventArgs(MouseButtons.Left, 1, indent + 5, 100, 0), Keys.None, m_gm.VwGraphics, ptrans);
            Assert.That(GetStringDropData(site), Is.EqualTo("is"));
            Assert.That(site.LastDoDragDropArgs.AllowedEffects, Is.EqualTo(DragDropEffects.Copy),
                        "editing not possible in this paragraph, we can only copy");
            Assert.That(root.Selection, Is.EqualTo(range), "selection should not be changed by drag drop");
            site.LastDoDragDropArgs = null;
            root.OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, 3, 100, 0), Keys.None, m_gm.VwGraphics, ptrans);
            Assert.That(site.LastDoDragDropArgs, Is.Null, "click outside selection should not initiate drag");

            // Tack on an extra check that a read-only view does not handle drop.
            var dataObj  = new DataObject(DataFormats.StringFormat, "new ");
            var dragArgs = new DragEventArgs(dataObj, (int)DragDropKeyStates.ControlKey, 10, 8,
                                             DragDropEffects.Copy | DragDropEffects.Move,
                                             DragDropEffects.None);

            root.OnDragEnter(dragArgs, new Point(14, 8), m_gm.VwGraphics, ptrans);
            Assert.That(dragArgs.Effect, Is.EqualTo(DragDropEffects.None));
            Assert.That(root.DragState, Is.EqualTo(WindowDragState.DraggingHere));
        }
示例#30
0
		public void SubParaSequenceTest()
		{
			var owner = new MockData1(55, 77);
			var styles = new AssembledStyles();
			var root = new RootBoxFdo(styles);
			var layoutInfo = MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);
			SetupFakeRootSite(root);
			var engine = layoutInfo.RendererFactory.GetRenderer(55, m_gm.VwGraphics) as FakeRenderEngine;
			MockSite site = new MockSite();
			root.Site = site;
			PaintTransform ptrans = new PaintTransform(2, 4, 96, 100, 0, 10, 120, 128);
			site.m_transform = ptrans;
			site.m_vwGraphics = m_gm.VwGraphics;
			root.Builder.Show(Paragraph.Containing(Display.Of(() => owner.ObjSeq1).Using((bldr, md) => bldr.AddString(() => md.SimpleThree, 55))));
			root.Layout(layoutInfo);
			VerifyParagraphs(root, new [] {""});

			//// Insert the first item into owner.ObjSeq1 and check all the right connections appear
			var child1 = new MockData1(55, 77);
			var child1String = "Hello world, this is a wide string";
			child1.SimpleThree = child1String;
			owner.InsertIntoObjSeq1(0, child1);
			VerifyParagraphs(root, new string[] { child1String });
			Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(1), "Builder.AddString should set up a hookup for the string");
			int invalidateWidth = FakeRenderEngine.SimulatedWidth(child1String) + 2 * RootBox.InvalidateMargin;
			var expectedInvalidate1 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
				invalidateWidth,
				engine.SegmentHeight + 2 * RootBox.InvalidateMargin);
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate1));

			// Insert a second item and check again.
			var child2 = new MockData1(55, 77);
			child2.SimpleThree = "Another world";
			invalidateWidth += FakeRenderEngine.SimulatedWidth("Another world");
			site.RectsInvalidated.Clear();
			owner.InsertIntoObjSeq1(1, child2);
			VerifyParagraphs(root, new string[] { child1String + "Another world" });
			Assert.That(child2.SimpleThreeHookupCount, Is.EqualTo(1), "Builder.AddString should set up a hookup for the string");
			var expectedInvalidate2 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
							invalidateWidth,
							engine.SegmentHeight + 2 * RootBox.InvalidateMargin);
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate2));

			// Insert a third item between the first two.
			var child3 = new MockData1(55, 77);
			child3.SimpleThree = "Inserted world";
			invalidateWidth += FakeRenderEngine.SimulatedWidth("Inserted world");
			site.RectsInvalidated.Clear();
			owner.InsertIntoObjSeq1(1, child3);
			VerifyParagraphs(root, new string[] { child1String + "Inserted world" + "Another world" });
			var expectedInvalidate3 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
							invalidateWidth,
							engine.SegmentHeight + 2 * RootBox.InvalidateMargin);
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate3));

			// Insert a fourth item at the start.
			var child4 = new MockData1(55, 77);
			child4.SimpleThree = "Beginning of world";
			invalidateWidth += FakeRenderEngine.SimulatedWidth("Beginning of world");
			site.RectsInvalidated.Clear();
			owner.InsertIntoObjSeq1(0, child4);
			VerifyParagraphs(root, new string[] { "Beginning of world" + child1String + "Inserted world" +"Another world" });
			var expectedInvalidate4 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
							invalidateWidth,
							engine.SegmentHeight + 2 * RootBox.InvalidateMargin);
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate4));

			// Delete the first item.
			site.RectsInvalidated.Clear();
			owner.RemoveAtObjSeq1(0);
			VerifyParagraphs(root, new string[] { child1String + "Inserted world" + "Another world" });
			Assert.That(child4.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for a deleted object should be disposed.");
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate4));

			// Delete a middle item.
			site.RectsInvalidated.Clear();
			owner.RemoveAtObjSeq1(1);
			VerifyParagraphs(root, new string[] { child1String + "Another world" });
			Assert.That(child3.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for a deleted object should be disposed.");
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate3));

			// Delete the last item.
			site.RectsInvalidated.Clear();
			owner.RemoveAtObjSeq1(1);
			VerifyParagraphs(root, new string[] { child1String });
			Assert.That(child2.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for a deleted object should be disposed.");
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate2));

			// Delete the only remaining item.
			site.RectsInvalidated.Clear();
			owner.RemoveAtObjSeq1(0);
			VerifyParagraphs(root, new string[] {""});
			Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for a deleted object should be disposed.");
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate1));

			// Eventually add some operations that allow inserting and deleting multiple items.

			// We also need to be able to insert two or more object sequences into the same containing box.
			// That's probably another test, perhaps a view of the root where for each data item,
			// we insert its subitems, then for those insert paragraphs.
			// Let's assume there's always one top-level hookup for the root.

		}
示例#31
0
        public void BasicDrop()
        {
            var styles = new AssembledStyles();
            var root   = new RootBoxFdo(styles);
            var mock1  = new MockData1(23, 23);

            mock1.SimpleThree = "old contents";
            var engine = new FakeRenderEngine()
            {
                Ws = 23, SegmentHeight = 13
            };
            var factory = new FakeRendererFactory();

            factory.SetRenderer(23, engine);
            root.Builder.Show(Display.Of(() => mock1.SimpleThree, 23));
            var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);

            root.Layout(layoutArgs);
            PaintTransform ptrans = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96);
            MockSite       site   = new MockSite();

            site.m_transform  = ptrans;
            site.m_vwGraphics = m_gm.VwGraphics;
            root.Site         = site;

            var dataObj  = new DataObject(DataFormats.StringFormat, "new ");
            int x        = FakeRenderEngine.SimulatedWidth("old ") + 2;
            var location = new Point(x, 8);

            // A drag to where we can drop, allowing both copy and move, no keys held
            var dragArgs = new DragEventArgs(dataObj, (int)DragDropKeyStates.None, 200, 300,
                                             DragDropEffects.Copy | DragDropEffects.Move,
                                             DragDropEffects.None);

            root.OnDragEnter(dragArgs, location, m_gm.VwGraphics, ptrans);
            Assert.That(dragArgs.Effect, Is.EqualTo(DragDropEffects.Move));
            Assert.That(root.DragState, Is.EqualTo(WindowDragState.DraggingHere));
            root.OnDragLeave();
            Assert.That(root.DragState, Is.EqualTo(WindowDragState.None));

            // Though other factors would favor move, only copy is allowed here.
            dragArgs = new DragEventArgs(dataObj, (int)DragDropKeyStates.None, 200, 300,
                                         DragDropEffects.Copy,
                                         DragDropEffects.None);
            root.OnDragEnter(dragArgs, location, m_gm.VwGraphics, ptrans);
            Assert.That(dragArgs.Effect, Is.EqualTo(DragDropEffects.Copy));

            // Though otherwise we could copy, there is no text data in the data object.
            dragArgs = new DragEventArgs(new DataObject(), (int)DragDropKeyStates.None, 200, 300,
                                         DragDropEffects.Copy | DragDropEffects.Move,
                                         DragDropEffects.None);
            root.OnDragEnter(dragArgs, location, m_gm.VwGraphics, ptrans);
            Assert.That(dragArgs.Effect, Is.EqualTo(DragDropEffects.None));

            dragArgs = new DragEventArgs(dataObj, (int)DragDropKeyStates.ControlKey, 200, 300,
                                         DragDropEffects.Copy | DragDropEffects.Move,
                                         DragDropEffects.None);
            root.OnDragEnter(dragArgs, location, m_gm.VwGraphics, ptrans);
            Assert.That(dragArgs.Effect, Is.EqualTo(DragDropEffects.Copy));

            root.OnDragDrop(dragArgs, location, m_gm.VwGraphics, ptrans);
            Assert.That(mock1.SimpleThree, Is.EqualTo("old new contents"));
        }
示例#32
0
		public void NullObjChecker()
		{
			var owner = new MockData1(55, 77);
			var child1 = new MockData1(55, 77);
			child1.SimpleThree = "This is a Test";
			owner.SimpleFour = null;
			var styles = new AssembledStyles();
			var root = new RootBoxFdo(styles);
			var layoutInfo = MakeLayoutInfo(int.MaxValue/2, m_gm.VwGraphics, 55);
			SetupFakeRootSite(root);
			var engine = layoutInfo.RendererFactory.GetRenderer(55, m_gm.VwGraphics) as FakeRenderEngine;
			MockSite site = new MockSite();
			root.Site = site;
			PaintTransform ptrans = new PaintTransform(2, 4, 96, 100, 0, 10, 120, 128);
			site.m_transform = ptrans;
			site.m_vwGraphics = m_gm.VwGraphics;
			root.Builder.Show(Display.OfObj(() => owner.SimpleFour).Using((bldr, md) => bldr.AddString(() => md.SimpleThree, 55)));
			root.Layout(layoutInfo);

			int invalidateWidth1 = FakeRenderEngine.SimulatedWidth(child1.SimpleThree) + 2*RootBox.InvalidateMargin;
			var expectedInvalidate1 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
													invalidateWidth1, engine.SegmentHeight + 2*RootBox.InvalidateMargin);
			VerifyParagraphs(root, new string[0]);
			Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for this unconnected object should not exist");
			Assert.That(owner.SimpleFourHookupCount, Is.EqualTo(1), "The hookup for this null object should exist");

			site.RectsInvalidatedInRoot.Clear();
			owner.SimpleFour = child1;
			int invalidateWidth2 = FakeRenderEngine.SimulatedWidth(child1.SimpleThree) + 2*RootBox.InvalidateMargin;
			var expectedInvalidate2 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
													invalidateWidth2, engine.SegmentHeight + 2*RootBox.InvalidateMargin);
			VerifyParagraphs(root, new[] {child1.SimpleThree});
			Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(1), "The hookup for this object should exist");
			Assert.That(owner.SimpleFourHookupCount, Is.EqualTo(1), "The hookup for this object should exist");
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate2));

			site.RectsInvalidatedInRoot.Clear();
			owner.SimpleFour = null;
			int invalidateWidth3 = FakeRenderEngine.SimulatedWidth(child1.SimpleThree) + 2*RootBox.InvalidateMargin;
			var expectedInvalidate3 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
													invalidateWidth3, engine.SegmentHeight + 2*RootBox.InvalidateMargin);
			VerifyParagraphs(root, new string[0]);
			Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for this unconnected object should not exist");
			Assert.That(owner.SimpleFourHookupCount, Is.EqualTo(1), "The hookup for this null object should exist");
			Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate3));

			site.RectsInvalidatedInRoot.Clear();
			owner.SimpleFour = null;
			int invalidateWidth4 = FakeRenderEngine.SimulatedWidth(child1.SimpleThree) + 2 * RootBox.InvalidateMargin;
			var expectedInvalidate4 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
													invalidateWidth3, engine.SegmentHeight + 2 * RootBox.InvalidateMargin);
			VerifyParagraphs(root, new string[0]);
			Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for this unconnected object should not exist");
			Assert.That(owner.SimpleFourHookupCount, Is.EqualTo(1), "The hookup for this null object should exist");
			Assert.That(site.RectsInvalidatedInRoot, Is.Empty, "Nothing changed, so nothing should be invalidated");
		}
示例#33
0
		public void Backtracking()
		{
			var styles = new AssembledStyles();
			var layoutInfo = MakeLayoutInfo();

			var engine = new FakeRenderEngine() { Ws = 34, SegmentHeight = 13 };
			var factory = new FakeRendererFactory();
			factory.SetRenderer(34, engine);
			var engine2 = new FakeRenderEngine() { Ws = 35, SegmentHeight = 13 };
			factory.SetRenderer(35, engine2);

			// This first test doesn't strictly require backtracking; it is an example of a similar
			// case where all the second client run fits, nothing of the following one fits, but
			// there is a satisfactory break at the end of the last thing that fit.
			var root = new RootBoxFdo(styles);
			root.Builder.Show(Paragraph.Containing(Display.Of("this is ", 34),
				Display.Of("some mixed ", 35), Display.Of("text", 34)));
			int maxWidth = FakeRenderEngine.SimulatedWidth("this is some mixed t");
			var layoutArgs = MakeLayoutInfo(maxWidth, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			var para = (ParaBox)root.FirstBox;
			var secondChild = (StringBox) para.FirstBox.Next;
			Assert.That(secondChild.Text, Is.EqualTo("some mixed "));

			// True backtracking: the second client run fits entirely, but nothing of the following text.
			// We must go back and find the break in the middle of that second run.
			root = new RootBoxFdo(styles);
			root.Builder.Show(Paragraph.Containing(Display.Of("this is ", 34),
				Display.Of("some mixed", 35), Display.Of("text", 34)));
			maxWidth = FakeRenderEngine.SimulatedWidth("this is some mixedte");
			layoutArgs = MakeLayoutInfo(maxWidth, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			para = (ParaBox)root.FirstBox;
			secondChild = (StringBox)para.FirstBox.Next;
			Assert.That(secondChild.Text, Is.EqualTo("some "));

			// Now a harder problem: the second client run fits entirely, but nothing of the following text,
			// and there is no break point in the second client run at all.
			// We must go back and find the break in the first client run.
			root = new RootBoxFdo(styles);
			root.Builder.Show(Paragraph.Containing(Display.Of("this is", 34),
				Display.Of("some", 35), Display.Of("text", 34)));
			maxWidth = FakeRenderEngine.SimulatedWidth("this issomete");
			layoutArgs = MakeLayoutInfo(maxWidth, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			para = (ParaBox)root.FirstBox;
			var firstChild = (StringBox)para.FirstBox;
			Assert.That(firstChild.Text, Is.EqualTo("this "));
			secondChild = (StringBox)para.FirstBox.Next;
			Assert.That(secondChild.Text, Is.EqualTo("is"));
			var thirdChild = (StringBox)secondChild.Next;
			Assert.That(thirdChild.Text, Is.EqualTo("some"));
			var fourthChild = (StringBox)thirdChild.Next;
			Assert.That(fourthChild.Text, Is.EqualTo("text"));
			Assert.That(secondChild.Top > firstChild.Top);
			Assert.That(fourthChild.Top, Is.EqualTo(secondChild.Top));

			// This time the third client run fits entirely, but nothing of the following text,
			// and there is no break point in the second client run at all; but right
			// before that third client run there is a non-text box.
			// We must break following the non-text box.
			root = new RootBoxFdo(styles);
			root.Builder.Show(Paragraph.Containing(Display.Of("this is", 34), Display.Block(Color.Red, 6000, 2000),
				Display.Of("some", 35), Display.Of("text", 34)));
			maxWidth = FakeRenderEngine.SimulatedWidth("this issomete") + layoutArgs.MpToPixelsX(6000);
			layoutArgs = MakeLayoutInfo(maxWidth, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			para = (ParaBox)root.FirstBox;
			firstChild = (StringBox)para.FirstBox;
			Assert.That(firstChild.Text, Is.EqualTo("this is"));
			Assert.That(firstChild.Next, Is.InstanceOf(typeof(BlockBox)));
			thirdChild = (StringBox)firstChild.Next.Next;
			Assert.That(thirdChild.Text, Is.EqualTo("some"));
			fourthChild = (StringBox)thirdChild.Next;
			Assert.That(fourthChild.Text, Is.EqualTo("text"));
			Assert.That(firstChild.Next.Top, Is.EqualTo(firstChild.Top), "The blockbox should be left on the first line");
			Assert.That(thirdChild.Top, Is.GreaterThan(firstChild.Top), "The 'some' run should be on the second line");
			Assert.That(fourthChild.Top, Is.EqualTo(thirdChild.Top), "all the rest of the text should fit on one more line");

			// This time the thing that does not fit IS the block at the end.
			// It should move to the next line, without taking any text with it.
			root = new RootBoxFdo(styles);
			root.Builder.Show(Paragraph.Containing(Display.Of("this is ", 34),
				Display.Of("some text", 35), Display.Block(Color.Red, 6000, 2000)));
			maxWidth = FakeRenderEngine.SimulatedWidth("this is some text") + layoutArgs.MpToPixelsX(2000);
			layoutArgs = MakeLayoutInfo(maxWidth, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			para = (ParaBox)root.FirstBox;
			firstChild = (StringBox)para.FirstBox;
			Assert.That(firstChild.Text, Is.EqualTo("this is "));
			secondChild = (StringBox)para.FirstBox.Next;
			Assert.That(secondChild.Text, Is.EqualTo("some text"));
			Assert.That(secondChild.Next, Is.InstanceOf(typeof(BlockBox)));
			Assert.That(secondChild.Top, Is.EqualTo(firstChild.Top), "The two string boxes should fit on the first line");
			Assert.That(secondChild.Next.Top, Is.GreaterThan(secondChild.Top), "The block should be on the second line");

			// Todo JohnT: should also test that a break can occur after a non-string box.
			// And many other cases (see Backtrack method).
		}
示例#34
0
		public void InsertGrowsPara()
		{
			string contents = "This is the day.";
			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 extraBox = new BlockBox(styles, Color.Red, 50, 72000);
			var root = new RootBoxFdo(styles);
			root.SizeChanged += root_SizeChanged;
			root.AddBox(para);
			root.AddBox(extraBox);
			var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			Assert.IsTrue(m_sizeChangedCalled);
			Assert.That(root.Height, Is.EqualTo(13 + 96));
			Assert.That(root.Width, Is.EqualTo(FakeRenderEngine.SimulatedWidth(contents)));

			int widthThisIsThe = FakeRenderEngine.SimulatedWidth("This is the");
			layoutArgs = MakeLayoutInfo(widthThisIsThe + 2, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			Assert.That(root.Height, Is.EqualTo(26 + 96), "two line para is twice the height");
			Assert.That(root.Width, Is.EqualTo(widthThisIsThe + 2), "two-line para occupies full available width");
			Assert.That(extraBox.Top, Is.EqualTo(26));

			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;
			m_sizeChangedCalled = false;
			var ip = para.SelectAtEnd();

			ip.InsertText(" We will be");
			Assert.That(para.Height, Is.EqualTo(39), "inserted text makes para a line higher");
			Assert.That(root.Height, Is.EqualTo(39 + 96), "root grows when para does");
			Assert.That(root.Width, Is.EqualTo(widthThisIsThe + 2), "three-line para occupies full available width");
			Assert.That(extraBox.Top, Is.EqualTo(39));
			Assert.IsTrue(m_sizeChangedCalled);
		}
示例#35
0
		public void BidiLayout()
		{
			string content1 = "This is the ";
			string contentRtl = "day ";
			string content3 = "that ";

			// Two writing systems
			int wsLtr = 5;
			int wsRtl = 6;

			// Two corresponding renderers
			var factory = new FakeRendererFactory();
			var engineLtr = new FakeRenderEngine() { Ws = wsLtr, SegmentHeight = 13 };
			factory.SetRenderer(wsLtr, engineLtr);
			var engineRtl = new FakeRenderEngine() {Ws = wsRtl, SegmentHeight = 13 };
			engineRtl.RightToLeft = true;
			factory.SetRenderer(wsRtl, engineRtl);

			// Two corresponding styles (and a vanilla one)
			var styles = new AssembledStyles();
			var stylesLtr = new AssembledStyles().WithWs(wsLtr);
			var stylesRtl = new AssembledStyles().WithWs(wsRtl);

			var clientRuns = new List<IClientRun>();
			var run1 = new StringClientRun(content1, stylesLtr);
			clientRuns.Add(run1);
			var runRtl = new StringClientRun(contentRtl, stylesRtl);
			clientRuns.Add(runRtl);
			var run3 = new StringClientRun(content3, stylesLtr);
			clientRuns.Add(run3);

			var root = new RootBoxFdo(styles);

			var source = new TextSource(clientRuns, null);
			var para = new ParaBox(styles, source);
			root.AddBox(para);

			var stylesParaRtl = styles.WithRightToLeft(true);
			var sourceRtl = new TextSource(clientRuns, null);
			var paraRtl = new ParaBox(stylesParaRtl, sourceRtl);
			root.AddBox(paraRtl);

			var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);

			// "day " being upstream should make two distinct boxes.
			// We should get something like
			// "This is the yad that ", where the space between "yad" and "that" is the one that
			// follows the 'y' in "day".
			var box1 = para.FirstBox as StringBox;
			var box2 = box1.Next as StringBox;
			var box3 = box2.Next as StringBox;
			var box4 = box3.Next as StringBox;
			Assert.That(box4, Is.Not.Null);
			Assert.That(box1.Segment.get_Lim(box1.IchMin) == content1.Length);
			Assert.That(box2.Segment.get_Lim(box2.IchMin) == contentRtl.Length - 1);
			Assert.That(box3.Segment.get_Lim(box3.IchMin) == 1);
			Assert.That(box4.Segment.get_Lim(box4.IchMin) == content3.Length);
			Assert.That(box1.Left, Is.LessThan(box2.Left));
			Assert.That(box2.Left, Is.LessThan(box3.Left));
			Assert.That(box3.Left, Is.LessThan(box4.Left));

			// In the second paragraph, the two LRT runs are upstream. We should get boxes
			// "This is the", " ", "day ", "that" and " " (but the final space will have zero width at end of line)
			// The effect should be something like
			// that yad This is the", where the space between "yad" and "This" is the one following "the",
			// and the one between "that" and "yad" is the one following "day", and the space following "that"
			// is invisible at the end of the line to the left of 'that'.
			var boxR1 = paraRtl.FirstBox as StringBox;
			var boxR2 = boxR1.Next as StringBox;
			var boxR3 = boxR2.Next as StringBox;
			var boxR4 = boxR3.Next as StringBox;
			var boxR5 = boxR4.Next as StringBox;
			Assert.That(boxR5, Is.Not.Null);
			Assert.That(boxR1.Segment.get_Lim(boxR1.IchMin) == content1.Length - 1);
			Assert.That(boxR2.Segment.get_Lim(boxR2.IchMin) == 1);
			Assert.That(boxR3.Segment.get_Lim(boxR3.IchMin) == contentRtl.Length);
			Assert.That(boxR4.Segment.get_Lim(boxR4.IchMin) == content3.Length - 1);
			Assert.That(boxR5.Segment.get_Lim(boxR5.IchMin) == 1);
		}
示例#36
0
		private void BodyofUserPromptTest(MockData1 data1, Flow promptField, Func<string> reader)
		{
			var engine = new FakeRenderEngine() { Ws = 34, SegmentHeight = 13 };
			var factory = new FakeRendererFactory();
			factory.SetRenderer(34, engine);
			factory.SetRenderer(35, engine);
			factory.SetRenderer(0, engine); // for literals
			var styles = new AssembledStyles().WithWs(34);

			var root = new RootBoxFdo(styles);
			root.Builder.Show(
				Paragraph.Containing(
					Display.Of("lead in ", 34),
					promptField,
					Display.Of("trailing", 34)
					)
				);
			var para = (ParaBox)root.FirstBox;
			Assert.That(para.Source.RenderText, Is.EqualTo("lead in type here trailing"));

			int width = FakeRenderEngine.SimulatedWidth("lead in type her"); // should make it take 2 lines and split prompt.
			var layoutArgs = MakeLayoutInfo(width, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			MockSite site = new MockSite();
			PaintTransform ptrans = new PaintTransform(2, 4, 96, 96, 0, 10, 96, 96);
			site.m_transform = ptrans;
			site.m_vwGraphics = m_gm.VwGraphics;
			root.Site = site;

			// Click on "type here" produces an IP in the empty string.
			int leadWidth = FakeRenderEngine.SimulatedWidth("lead in ");
			var mouseArgs = new MouseEventArgs(MouseButtons.Left, 1, 2 + leadWidth + 3, 0, 0);
			root.OnMouseDown(mouseArgs, Keys.None, m_gm.VwGraphics, ptrans);
			var ip = root.Selection as InsertionPoint;
			Assert.That(ip, Is.Not.Null);
			Assert.That(ip.LogicalParaPosition, Is.EqualTo("lead in ".Length));
			Assert.That(ip.StringPosition, Is.EqualTo(0));

			// IP is drawn as range covering "type here"
			ip.Draw(m_gm.VwGraphics, ptrans);
			var first = (StringBox)para.FirstBox;
			VerifyRangeSegmentDrawing(para, first, (FakeSegment)first.Segment, "lead in ".Length, "lead in type here ".Length,
				-4, 4 - 10, 4 - 10 + 13);
			var second = (StringBox)first.Next;
			VerifyRangeSegmentDrawing(para, second, (FakeSegment)second.Segment, "lead in ".Length, "lead in type here ".Length,
				-4 - 13, 4 - 10 + 13, 4 - 10 + 13 * 2);
			// Check that we get a sensible answer for the selection's containing rectangle.
			((FakeSegment) first.Segment).LeftPositionOfRangeResult = 17;
			((FakeSegment)first.Segment).RightPositionOfRangeResult = 29;
			((FakeSegment)second.Segment).LeftPositionOfRangeResult = 5;
			((FakeSegment)second.Segment).RightPositionOfRangeResult = 13;
			var rect = ip.GetSelectionLocation(m_gm.VwGraphics, ptrans);
			Assert.That(rect.Top, Is.EqualTo(4 - 10));
			Assert.That(rect.Bottom, Is.EqualTo(4 - 10 + 13*2));
			Assert.That(rect.Left, Is.EqualTo(5));
			Assert.That(rect.Right, Is.EqualTo(29));
			VerifyRangeSegmentQuery(para, first, (FakeSegment)first.Segment, "lead in ".Length, "lead in type here ".Length,
				-4, 4 - 10, 4 - 10 + 13);
			VerifyRangeSegmentQuery(para, second, (FakeSegment)second.Segment, "lead in ".Length, "lead in type here ".Length,
				-4 - 13, 4 - 10 + 13, 4 - 10 + 13 * 2);
			Assert.That(second.IchMin, Is.EqualTo("lead in type ".Length));
			// When the IP is drawn like this, it doesn't flash!
			site.RectsInvalidatedInRoot.Clear();
			site.RectsInvalidated.Clear();
			root.FlashInsertionPoint(); // Call twice just in case somehow only some invalidates worked.
			root.FlashInsertionPoint();
			Assert.That(site.RectsInvalidated, Is.Empty);
			Assert.That(site.RectsInvalidatedInRoot, Is.Empty);
			// Typing something else makes "type here" go away and produces a normal IP after it.
			ip.InsertText("x");
			Assert.That(reader(), Is.EqualTo("x"));
			Assert.That(para.Source.RenderText, Is.EqualTo("lead in xtrailing"));
			ip = root.Selection as InsertionPoint;
			Assert.That(ip, Is.Not.Null);
			Assert.That(ip.ShouldFlash, Is.True);
			Assert.That(ip.LogicalParaPosition, Is.EqualTo("lead in x".Length));
			// Deleting back to empty string makes "type here" reappear.
			ip.Backspace();
			Assert.That(reader(), Is.EqualTo(""));
			Assert.That(para.Source.RenderText, Is.EqualTo("lead in type here trailing"));
			ip = root.Selection as InsertionPoint;
			Assert.That(ip, Is.Not.Null);
			Assert.That(ip.ShouldFlash, Is.False);
			Assert.That(ip.LogicalParaPosition, Is.EqualTo("lead in ".Length));
			Assert.That(ip.LastRenderParaPosition, Is.EqualTo("lead in type here ".Length));
			second = (StringBox)para.FirstBox.Next;
			Assert.That(second.IchMin, Is.EqualTo("lead in type ".Length));
			// Click after "type here" produces an IP at the right place in the following string.
			// We've arranged for the prompt to be split, so this is after the word 'here' on the second line.
			int hereTWidth = FakeRenderEngine.SimulatedWidth("here t");
			mouseArgs = new MouseEventArgs(MouseButtons.Left, 1, 2 + hereTWidth - 1, 4 - 10 + 13 + 2, 0);
			root.OnMouseDown(mouseArgs, Keys.None, m_gm.VwGraphics, ptrans);
			ip = root.Selection as InsertionPoint;
			Assert.That(ip, Is.Not.Null);
			Assert.That(ip.LogicalParaPosition, Is.EqualTo("lead in t".Length));
			Assert.That(ip.AssociatePrevious, Is.True);
			Assert.That(ip.StringPosition, Is.EqualTo(1));
			Assert.That(ip.RenderParaPosition, Is.EqualTo("lead in type here t".Length));
			// Also try a click in the second-line part of the prompt.
			int herWidth = FakeRenderEngine.SimulatedWidth("her");
			mouseArgs = new MouseEventArgs(MouseButtons.Left, 1, 2 + herWidth - 1, 4 - 10 + 13 + 2, 0);
			root.OnMouseDown(mouseArgs, Keys.None, m_gm.VwGraphics, ptrans);
			ip = root.Selection as InsertionPoint;
			Assert.That(ip, Is.Not.Null);
			Assert.That(ip.LogicalParaPosition, Is.EqualTo("lead in ".Length));
			Assert.That(ip.StringPosition, Is.EqualTo(0));
			Assert.That(ip.RenderParaPosition, Is.EqualTo("lead in ".Length));
			Assert.That(ip.LastRenderParaPosition, Is.EqualTo("lead in type here ".Length));
		}
示例#37
0
        public void ParaSequenceTest()
        {
            var owner      = new MockData1(55, 77);
            var styles     = new AssembledStyles();
            var root       = new RootBoxFdo(styles);
            var layoutInfo = MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);

            SetupFakeRootSite(root);
            var      engine  = layoutInfo.RendererFactory.GetRenderer(55, m_gm.VwGraphics) as FakeRenderEngine;
            MockSite site    = new MockSite();
            int      topLazy = 0;        // top of the part of the root box that is occupied by the lazy stuff, relative to the top of the root box itself.

            root.Site = site;
            PaintTransform ptrans = new PaintTransform(2, 4, 96, 96, 0, 10, 96, 96);

            site.m_transform  = ptrans;
            site.m_vwGraphics = m_gm.VwGraphics;
            root.Builder.Show(LazyDisplay.Of(() => owner.ObjSeq1).Using((bldr, md) => bldr.AddString(() => md.SimpleThree, 55)));
            var heightOfOneItem = layoutInfo.MpToPixelsY(LazyBox <MockData1> .DefaultItemHeight * 1000);

            // This does two things: it makes sure the boxes produced by expanding a lazy box item won't be the SAME size,
            // so we'll get nontrivial changes in root box size; and it makes sure we don't have to expand MORE items than
            // expected based on the height estimate, which could throw off our predictions of what gets expanded.
            // Todo: we need a test where we DO have to expand more items after the initial estimate.
            engine.SegmentHeight = heightOfOneItem + 2;
            root.Layout(layoutInfo);
            VerifyParagraphs(root, new string[0]);

            var child1       = new MockData1(55, 77);
            var child1String = "Hello world, this is a wide string";

            child1.SimpleThree = child1String;
            owner.InsertIntoObjSeq1(0, child1);
            Assert.That(root.FirstBox, Is.TypeOf(typeof(LazyBox <MockData1>)));
            var lazyBox = (LazyBox <MockData1>)root.FirstBox;

            Assert.That(lazyBox.Width, Is.EqualTo(int.MaxValue / 2));             // no margins, should equal avail width.
            Assert.That(lazyBox.Height, Is.EqualTo(heightOfOneItem));
            var lazyTop             = lazyBox.Top;
            var lazyBottom          = lazyBox.Bottom;
            var oldRootHeight       = root.Height;
            int invalidateWidth     = lazyBox.Width + 2 * RootBox.InvalidateMargin;
            var expectedInvalidate1 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
                                                    invalidateWidth,
                                                    lazyBox.Height + 2 * RootBox.InvalidateMargin);

            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate1));
            site.RectsInvalidatedInRoot.Clear();
            var lazyHookup = ((IHookup)lazyBox).ParentHookup as LazyHookup <MockData1>;

            Assert.That(lazyHookup, Is.Not.Null);
            Assert.That(lazyHookup.Children[0], Is.EqualTo(lazyBox));
            Assert.That(lazyHookup.Children, Has.Count.EqualTo(1));
            root.LazyExpanded += root_LazyExpanded;
            using (var lc = new LayoutCallbacks(root))
            {
                root.PrepareToPaint(layoutInfo, null, 0, 200);
            }
            VerifyParagraphs(root, new [] { child1String });
            Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(1), "expanding lazy box should set up a hookup for the string");
            Assert.That(site.RectsInvalidatedInRoot, Is.Empty, "we don't need to invalidate expanding something that's never been painted");
            VerifyExpandArgs(0, lazyTop + 2, lazyBottom + 2, root.Height - oldRootHeight);
            Assert.That(lazyHookup.Children, Has.Count.EqualTo(1));
            Assert.That(lazyHookup.Children[0], Is.TypeOf(typeof(ItemHookup)), "the lazy box standing for item hookups should have been replaced");

            // Now replace that one object with a list of several. I want to be able to expand two at the start, one at the end,
            // and one in the middle, and leave two lazy boxes behind. Then expand the rest and make them go away. So I need six.
            var values = new MockData1[10];

            for (int i = 0; i < 10; i++)
            {
                values[i]             = new MockData1(55, 77);
                values[i].SimpleThree = i.ToString();
            }
            var newValues = values.Take(6).ToArray();

            site.RectsInvalidatedInRoot.Clear();
            int phase2RootHeight = root.Height;
            int phase2RootWidth  = root.Width;

            owner.ReplaceObjSeq1(newValues);
            var expectedInvalidate2 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
                                                    phase2RootWidth + 2 * RootBox.InvalidateMargin,
                                                    phase2RootHeight + 2 * RootBox.InvalidateMargin);

            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate2), "should invalidate the old replaced paragraph.");
            lazyBox = (LazyBox <MockData1>)root.FirstBox;
            Assert.That(lazyBox.Width, Is.EqualTo(int.MaxValue / 2));             // no margins, should equal avail width.
            Assert.That(root.LastBox, Is.EqualTo(lazyBox), "old paragraph should have been replaced");
            Assert.That(lazyHookup.Children[0], Is.EqualTo(lazyBox), "after second replace we just have the lazy box");
            Assert.That(lazyHookup.Children, Has.Count.EqualTo(1), "should not have anything but lazy box after second replace");
            Assert.That(lazyBox.Height, Is.EqualTo(6 * heightOfOneItem));

            // Make it expand the first two items.
            site.RectsInvalidatedInRoot.Clear();
            m_expandArgs.Clear();
            oldRootHeight = root.Height;
            using (var lc = new LayoutCallbacks(root))
            {
                root.PrepareToPaint(layoutInfo, null, 0, heightOfOneItem * 2 - 2);
            }
            VerifyParagraphs(root, new[] { "0", "1", null });             // Should have two paras then lazy box
            Assert.That(newValues[0].SimpleThreeHookupCount, Is.EqualTo(1), "expanding lazy box should set up a hookup for the string");
            Assert.That(newValues[1].SimpleThreeHookupCount, Is.EqualTo(1), "expanding lazy box should set up a hookup for the string");
            Assert.That(site.RectsInvalidatedInRoot, Is.Empty, "we don't need to invalidate expanding something that's never been painted");
            Assert.That(root.Height, Is.Not.EqualTo(oldRootHeight));
            VerifyExpandArgs(0, 2, heightOfOneItem * 2 + 2, root.Height - oldRootHeight);             // +2's from root layout offset
            Assert.That(lazyHookup.Children, Has.Count.EqualTo(3));
            Assert.That(lazyHookup.Children[0], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the first expanded item should be inserted");
            Assert.That(lazyHookup.Children[1], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the 2nd expanded item should be inserted");
            Assert.That(lazyHookup.Children[2], Is.TypeOf(typeof(LazyBox <MockData1>)), "the lazy box standing for item hookups should still be there");
            lazyBox = root.FirstBox.Next.Next as LazyBox <MockData1>;
            Assert.That(lazyBox, Is.Not.Null);
            Assert.That(lazyBox.Height, Is.EqualTo(heightOfOneItem * 4));

            int topOfLastItem = lazyBox.Bottom - heightOfOneItem + 2;

            // Make it expand the last item.
            site.RectsInvalidatedInRoot.Clear();
            m_expandArgs.Clear();
            oldRootHeight = root.Height;
            using (var lc = new LayoutCallbacks(root))
            {
                root.PrepareToPaint(layoutInfo, null, topOfLastItem + 2, topOfLastItem + 10);
            }
            VerifyParagraphs(root, new[] { "0", "1", null, "5" });             // Should have two paras then lazy box then last para
            Assert.That(newValues[5].SimpleThreeHookupCount, Is.EqualTo(1), "expanding lazy box should set up a hookup for the string");
            Assert.That(site.RectsInvalidatedInRoot, Is.Empty, "we don't need to invalidate expanding something that's never been painted");
            Assert.That(root.Height, Is.Not.EqualTo(oldRootHeight));
            VerifyExpandArgs(0, topOfLastItem, topOfLastItem + heightOfOneItem, root.Height - oldRootHeight);
            Assert.That(lazyHookup.Children, Has.Count.EqualTo(4));
            Assert.That(lazyHookup.Children[0], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the first expanded item should be inserted");
            Assert.That(lazyHookup.Children[1], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the 2nd expanded item should be inserted");
            Assert.That(lazyHookup.Children[2], Is.TypeOf(typeof(LazyBox <MockData1>)), "the lazy box standing for item hookups should still be there");
            Assert.That(lazyHookup.Children[3], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the last expanded item should be inserted");
            lazyBox = root.FirstBox.Next.Next as LazyBox <MockData1>;
            Assert.That(lazyBox, Is.Not.Null);
            Assert.That(lazyBox.Height, Is.EqualTo(heightOfOneItem * 3));

            // Expand middle item in lazy box, leaving two lazy boxes.
            int topOfMiddleItem = lazyBox.Top + heightOfOneItem + 2;

            site.RectsInvalidatedInRoot.Clear();
            m_expandArgs.Clear();
            oldRootHeight = root.Height;
            using (var lc = new LayoutCallbacks(root))
            {
                root.PrepareToPaint(layoutInfo, null, topOfMiddleItem + 2, topOfMiddleItem + 10);
            }
            VerifyParagraphs(root, new[] { "0", "1", null, "3", null, "5" });             // Should have two paras then lazy box then middle para then another lazy then last para
            Assert.That(newValues[3].SimpleThreeHookupCount, Is.EqualTo(1), "expanding lazy box should set up a hookup for the string");
            Assert.That(site.RectsInvalidatedInRoot, Is.Empty, "we don't need to invalidate expanding something that's never been painted");
            Assert.That(root.Height, Is.Not.EqualTo(oldRootHeight));
            VerifyExpandArgs(0, topOfMiddleItem, topOfMiddleItem + heightOfOneItem, root.Height - oldRootHeight);
            Assert.That(lazyHookup.Children, Has.Count.EqualTo(6));
            Assert.That(lazyHookup.Children[0], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the first expanded item should be inserted");
            Assert.That(lazyHookup.Children[1], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the 2nd expanded item should be inserted");
            Assert.That(lazyHookup.Children[2], Is.TypeOf(typeof(LazyBox <MockData1>)), "the lazy box standing for item hookups should still be there");
            Assert.That(lazyHookup.Children[3], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the last expanded item should be inserted");
            Assert.That(lazyHookup.Children[4], Is.TypeOf(typeof(LazyBox <MockData1>)), "the lazy box standing for item hookups should still be there");
            Assert.That(lazyHookup.Children[5], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the last expanded item should be inserted");
            lazyBox = root.FirstBox.Next.Next as LazyBox <MockData1>;
            Assert.That(lazyBox, Is.Not.Null);
            Assert.That(lazyBox.Height, Is.EqualTo(heightOfOneItem));
            var lazyBox2 = lazyBox.Next.Next as LazyBox <MockData1>;

            Assert.That(lazyBox2, Is.Not.Null);
            Assert.That(lazyBox2.Height, Is.EqualTo(heightOfOneItem));
            // Expand lazy box when it is between two other items. (Also verify expanding two lazy boxes in one PrepareToPaint.)
            int topOfFirstLazy = lazyBox.Top + 2;
            int topOfLastLazy  = lazyBox2.Top + 2;

            site.RectsInvalidatedInRoot.Clear();
            m_expandArgs.Clear();
            oldRootHeight = root.Height;
            using (var lc = new LayoutCallbacks(root))
            {
                root.PrepareToPaint(layoutInfo, null, topOfFirstLazy + 2, topOfLastLazy + 2);
            }
            VerifyParagraphs(root, new[] { "0", "1", "2", "3", "4", "5" });             // Should have all the real paragraphs now.
            Assert.That(newValues[2].SimpleThreeHookupCount, Is.EqualTo(1), "expanding lazy box should set up a hookup for the string");
            Assert.That(newValues[4].SimpleThreeHookupCount, Is.EqualTo(1), "expanding lazy box should set up a hookup for the string");
            Assert.That(site.RectsInvalidatedInRoot, Is.Empty, "we don't need to invalidate expanding something that's never been painted");
            Assert.That(root.Height, Is.Not.EqualTo(oldRootHeight));
            var delta = engine.SegmentHeight - heightOfOneItem;

            VerifyExpandArgs(0, topOfFirstLazy, topOfFirstLazy + heightOfOneItem, delta);
            VerifyExpandArgs(1, topOfLastLazy + delta, topOfLastLazy + delta + heightOfOneItem, delta);
            Assert.That(lazyHookup.Children, Has.Count.EqualTo(6));
            Assert.That(lazyHookup.Children[0], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the first expanded item should be inserted");
            Assert.That(lazyHookup.Children[1], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the 2nd expanded item should be inserted");
            Assert.That(lazyHookup.Children[2], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the 3rd expanded item should be inserted");
            Assert.That(lazyHookup.Children[3], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the 4th expanded item should be inserted");
            Assert.That(lazyHookup.Children[4], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the 5th expanded item should be inserted");
            Assert.That(lazyHookup.Children[5], Is.TypeOf(typeof(ItemHookup)), "a regular item hookup for the last expanded item should be inserted");

            // Now try removing the first two items.
            site.RectsInvalidatedInRoot.Clear();
            int heightOfFirst2Paras = root.FirstBox.Next.Bottom - root.FirstBox.Top;
            int phase3RootWidth     = root.Width;
            int phase3RootHeight    = root.Height;
            var phase3Values        = newValues.Skip(2).ToArray();

            owner.ReplaceObjSeq1(phase3Values);
            var expectedInvalidate3 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
                                                    phase3RootWidth + 2 * RootBox.InvalidateMargin,
                                                    phase3RootHeight + 2 * RootBox.InvalidateMargin);

            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate3), "should invalidate the whole old root box; everything changes or moves.");
            VerifyParagraphs(root, new[] { "2", "3", "4", "5" });            // Should have last 4 paragraphs now (not made lazy).

            // Now try removing the last item.
            site.RectsInvalidatedInRoot.Clear();
            int phase4RootWidth = root.Width;
            var phase4Values    = phase3Values.Take(3).ToArray();
            var topOfPara4      = root.FirstBox.Next.Next.Bottom + topLazy;

            owner.ReplaceObjSeq1(phase4Values);
            var expectedInvalidate4 = new Rectangle(-RootBox.InvalidateMargin, topOfPara4 - RootBox.InvalidateMargin,
                                                    phase4RootWidth + 2 * RootBox.InvalidateMargin,
                                                    root.FirstBox.Height + 2 * RootBox.InvalidateMargin);

            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate4), "should invalidate the old replaced paragraphs.");
            VerifyParagraphs(root, new[] { "2", "3", "4" });             // Should have last 3 paragraphs now (not made lazy).

            // Now try removing a middle item.
            site.RectsInvalidatedInRoot.Clear();
            int phase5RootWidth  = root.Width;
            var phase5Values     = new [] { newValues[2], newValues[4] };
            var topOfPara3       = root.FirstBox.Bottom + topLazy;
            var phase4RootHeight = root.Height;

            owner.ReplaceObjSeq1(phase5Values);
            var expectedInvalidate5 = new Rectangle(-RootBox.InvalidateMargin, topOfPara3 - RootBox.InvalidateMargin,
                                                    phase5RootWidth + 2 * RootBox.InvalidateMargin,
                                                    phase4RootHeight - topOfPara3 + 2 * RootBox.InvalidateMargin);

            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate5), "should invalidate the old replaced paragraphs.");
            VerifyParagraphs(root, new[] { "2", "4" });             // Should have remaining 2 paragraphs now (not made lazy).

            // Insert three items at start: 0, 1, 3, 2, 4.
            site.RectsInvalidatedInRoot.Clear();
            int phase6RootWidth = root.Width;
            var phase6Values    = new[] { newValues[0], newValues[1], newValues[3], newValues[2], newValues[4] };

            owner.ReplaceObjSeq1(phase6Values);
            int lazyWidth           = root.LastLayoutInfo.MaxWidth;   // current standard width for lazy boxes.
            var expectedInvalidate6 = new Rectangle(-RootBox.InvalidateMargin, topLazy - RootBox.InvalidateMargin,
                                                    lazyWidth + 2 * RootBox.InvalidateMargin,
                                                    root.Height + 2 * RootBox.InvalidateMargin);

            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate6), "should invalidate everything...all moved or added.");
            VerifyParagraphs(root, new[] { null, "2", "4" });            // Should have added lazy box at start.
            VerifyLazyContents(root.FirstBox, new[] { newValues[0], newValues[1], newValues[3] });

            // Insert at end: 0, 1, 3, 2, 4, 9. I think we've tested the invalidate rects enough.
            var phase7Values = new[] { values[0], values[1], values[3], values[2], values[4], values[9] };

            owner.ReplaceObjSeq1(phase7Values);
            VerifyParagraphs(root, new[] { null, "2", "4", null });             // Should have added lazy box at end.
            VerifyLazyContents(root.LastBox, new[] { values[9] });
            // Insert between two non-lazy items: 0, 1, 3, 2, 5, 6, 4, 9.
            var phase8Values = new[] { values[0], values[1], values[3], values[2], values[5], values[6], values[4], values[9] };

            owner.ReplaceObjSeq1(phase8Values);
            VerifyParagraphs(root, new[] { null, "2", null, "4", null });             // Should have added lazy box in middle.
            VerifyLazyContents(root.FirstBox.Next.Next, new[] { values[5], values[6] });
            // Try a more complex overwrite. We'll replace the last item in the first lazy box and the first one in the second
            var phase9Values = new[] { values[0], values[1], values[7], values[2], values[8], values[6], values[4], values[9] };

            owner.ReplaceObjSeq1(phase9Values);
            VerifyParagraphs(root, new[] { null, "4", null });             // Should replace first 3 items with new lazy box.
            VerifyLazyContents(root.FirstBox, new[] { values[0], values[1], values[7], values[2], values[8], values[6] });
        }
示例#38
0
		public void ArrowKeys()
		{
			var engine = new FakeRenderEngine() { Ws = 34, SegmentHeight = 13 };
			var factory = new FakeRendererFactory();
			factory.SetRenderer(34, engine);
			var styles = new AssembledStyles().WithWs(34);
			var root = new RootBoxFdo(styles);
			var para1 = AddPara("This i~^s the~ day", styles, root);
			var para2 = AddPara("", styles, root);
			var para3 = AddPara(new string[] {"that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE + " the Lord", "has made"},
				styles, root);
			var para4 = AddPara(new string[] { "we will", "", "rejoice" }, styles, root);

			int widthThisIsThe = FakeRenderEngine.SimulatedWidth("This is the");
			var layoutArgs = MakeLayoutInfo(widthThisIsThe + 2, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			Assert.That(root.Height, Is.EqualTo(13 * 8), "A two-line and a one-line and a three-line and a two-line paragraph");
			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;

			// Simple left movement.
			var ipThisIsTheDay = para1.SelectAtEnd();
			var ipThisIsTheDa = ipThisIsTheDay.MoveByKey(new KeyEventArgs(Keys.Left));
			VerifyIp(ipThisIsTheDa, para1, "This i~^s the~ da", false, "left from end");
			var ipThisIsTheD = ipThisIsTheDa.MoveByKey(new KeyEventArgs(Keys.Left));
			VerifyIp(ipThisIsTheD, para1, "This i~^s the~ d", false, "left from no special plae");

			// Left from one run into an adjacent non-empty run
			var ipThatTheLord2 = ((TextClientRun) para3.Source.ClientRuns[1]).SelectAt(para3, 0, false);
			var ipThatTheLor = ipThatTheLord2.MoveByKey(new KeyEventArgs(Keys.Left));
			VerifyIp(ipThatTheLor, para3, "that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE + " the Lor", false, "left from start run2");

			// Left from one run into an adjacent empty run. Is this right or should we skip over it into
			// another run so we actually move a character?
			var ipStartOfRejoice = ((TextClientRun)para4.Source.ClientRuns[2]).SelectAt(para4, 0, false);
			var ipEmptyPara4 = ipStartOfRejoice.MoveByKey(new KeyEventArgs(Keys.Left));
			VerifyIp(ipEmptyPara4, para4, "we will", false, "left from start run into empty");

			// Out of the empty run into the previous one.
			var ipWeWil = ipEmptyPara4.MoveByKey(new KeyEventArgs(Keys.Left));
			VerifyIp(ipWeWil, para4, "we wil", false, "left from empty run");

			// back from one para into another.
			var ipPara2 = para2.SelectAtStart();
			var ipEndPara1 = ipPara2.MoveByKey(new KeyEventArgs(Keys.Left));
			VerifyIp(ipEndPara1, para1, "This i~^s the~ day", true, "left from one para to another");

			// back at the very start.
			var ipStart = para1.SelectAtStart();
			Assert.That(ipStart.MoveByKey(new KeyEventArgs(Keys.Left)), Is.Null);

			// back after a surrogate pair should not stop in the middle.
			var ipThatSurrogate = ((TextClientRun)para3.Source.ClientRuns[0]).SelectAt(para3,
				("that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE).Length, false);
			var ipThat = ipThatSurrogate.MoveByKey(new KeyEventArgs(Keys.Left));
			VerifyIp(ipThat, para3, "that", false, "left over surrogate pair");

			// Back to a place between diacritic and base should not stop.
			var ipThisI_Diacritics = ((TextClientRun)para1.Source.ClientRuns[0]).SelectAt(para1,
				"This i~^".Length, false);
			var ipThisSpace = ipThisI_Diacritics.MoveByKey(new KeyEventArgs(Keys.Left));
			VerifyIp(ipThisSpace, para1, "This ", false, "left over diacritics");

			// We can use many of the same ones to check right movement.
			var ipThisIsTheDa_r = ipThisIsTheD.MoveByKey(new KeyEventArgs(Keys.Right));
			VerifyIp(ipThisIsTheDa_r, para1, "This i~^s the~ da", true, "simple right");

			// Move right into an empty paragraph.
			// Review JohnT: should this IP in an empty para associate forward or back?
			var ipStartP2 = ipThisIsTheDay.MoveByKey(new KeyEventArgs(Keys.Right));
			VerifyIp(ipStartP2, para2, "", false, "right into empty para");
			// Should definitely associate with the character following, not the nonexistent preceding one.
			var ipStartP3 = ipStartP2.MoveByKey(new KeyEventArgs(Keys.Right));
			VerifyIp(ipStartP3, para3, "", false, "right to start of non-empty para");

			var ipP3_t = ipStartP3.MoveByKey(new KeyEventArgs(Keys.Right));
			VerifyIp(ipP3_t, para3, "t", true, "simple right");

			var ipThatSurrogate2 = ipThat.MoveByKey(new KeyEventArgs(Keys.Right));
			VerifyIp(ipThatSurrogate2, para3, "that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE, true, "right over surrogate pair");

			var ipThatTheLord_left = ((TextClientRun)para3.Source.ClientRuns[0]).SelectAt(para3,
				("that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE + " the Lord").Length, true);
			var ipThatTheLord_space = ipThatTheLord_left.MoveByKey(new KeyEventArgs(Keys.Right));
			VerifyIp(ipThatTheLord_space, para3, "that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE + " the Lord ", true, "right from end run1");

			var ipEnd = para4.SelectAtEnd();
			Assert.That(ipEnd.MoveByKey(new KeyEventArgs(Keys.Right)), Is.Null);

			// Also can't make range by moving right from end.
			Assert.That(ipEnd.MoveByKey(new KeyEventArgs(Keys.Right | Keys.Shift)), Is.Null);

			var rangeThatSurrogate2 = ipThat.MoveByKey(new KeyEventArgs(Keys.Right | Keys.Shift));
			VerifyRange(rangeThatSurrogate2, para3, "that", para3, "that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE, "shift-right over surrogate pair");

			var rangeThatTha = ipThat.MoveByKey(new KeyEventArgs(Keys.Left | Keys.Shift));
			VerifyRange(rangeThatTha, para3, "that", para3, "tha", "shift-left end before anchor");

			// left from a range puts us at the start of the range
			var ipThat2 = rangeThatSurrogate2.MoveByKey(new KeyEventArgs(Keys.Left));
			VerifyIp(ipThat2, para3, "that", false, "left from range to IP");
			// right from a range puts us at the end of the range
			var ipThatSurrrogate2 = rangeThatSurrogate2.MoveByKey(new KeyEventArgs(Keys.Right));
			VerifyIp(ipThatSurrrogate2, para3, "that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE, true, "right from range");

			// shift-left from a 1-char range collapses it to an IP
			var ipThat3 = rangeThatSurrogate2.MoveByKey(new KeyEventArgs(Keys.Left | Keys.Shift));
			VerifyIp(ipThat3, para3, "that", false, "left over surrogate pair");

			// shift-right from a range makes one with the same anchor but an extended end
			var rangeThatSurrogateSpace = rangeThatSurrogate2.MoveByKey(new KeyEventArgs(Keys.Right | Keys.Shift));
			VerifyRange(rangeThatSurrogateSpace, para3, "that", para3, "that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE + " ", "shift-right from range");

			// shift-right from a range that can't grow returns null.
			var ipWeWillRejoic = (InsertionPoint) ipEnd.MoveByKey(new KeyEventArgs(Keys.Left));
			var range1AtEnd = new RangeSelection(ipWeWillRejoic, ipEnd);
			Assert.That(range1AtEnd.MoveByKey(new KeyEventArgs(Keys.Right | Keys.Shift)), Is.Null);

			// Home key.
			var ipStartP2_2 = ipThat.MoveByKey(new KeyEventArgs(Keys.Home));
			VerifyIp(ipStartP2_2, para3, "", false, "home in Para 3");

			var ipStart_2 = ipThat.MoveByKey(new KeyEventArgs(Keys.Home | Keys.Control));
			VerifyIp(ipStart_2, para1, "", false, "ctrl-home in Para 3");

			// End key.
			var ipEndP2 = ipThat.MoveByKey(new KeyEventArgs(Keys.End));
			VerifyIp(ipEndP2, para3, "that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE + " the Lord" + "has made",
				true, "end in Para 3");

			var ipEnd_2 = ipThat.MoveByKey(new KeyEventArgs(Keys.End | Keys.Control));
			VerifyIp(ipEnd_2, para4, "we will" + "rejoice", true, "ctrl-end in Para 3");

			// Down key
			var ipThisIsThe_R = ipStart.MoveByKey(new KeyEventArgs(Keys.Down));
			VerifyIp(ipThisIsThe_R, para1, "This i~^s the~ ", false, "down from start line 1");

			var ipTh = para1.SelectAt(2, true);
			var ipThisIsTheDa2 = ipTh.MoveByKey(new KeyEventArgs(Keys.Down));
			VerifyIp(ipThisIsTheDa2, para1, "This i~^s the~ da", false, "down from 2 chars into line 1");

			var ipThisIdTh = para1.SelectAt("This i~^s th".Length, false);
			var ipThisIsTheDay2 = ipThisIdTh.MoveByKey(new KeyEventArgs(Keys.Down));
			VerifyIp(ipThisIsTheDay2, para1, "This i~^s the~ day", true, "down from near end line 1");

			// Empty para: arbitrary which way it associates.
			var ipPara2Down = ipThisIsTheDay2.MoveByKey(new KeyEventArgs(Keys.Down));
			VerifyIp(ipPara2Down, para2, "", true, "down twice from near end line 1");

			// Going on down, we should remember the starting X position and end up about that
			// far into the next full-length line. The 'i' characters in the first line make it
			// a bit iffy; might be closer to the start of the 'e' at the end of 'the'.
			// The other complication is that our fake render engine is not smart about surrogate pairs,
			// and treats the musical semibrevis as two ordinary characters.
			// Omitting the diacritics in the first paragraph, our selection starts 10 characters in.
			// The result string here is 9 characters, since with no narrow letters on this para,
			// we end up closer to the left of the 'e'.
			var ipThatTheSpaceDown = ipPara2Down.MoveByKey(new KeyEventArgs(Keys.Down));
			VerifyIp(ipThatTheSpaceDown, para3, "that" + MUSICAL_SYMBOL_SEMIBREVIS_WHITE + " th", false,
				"down 3x from near end line 1");

			Assert.That(ipEnd.MoveByKey(new KeyEventArgs(Keys.Down)), Is.Null);

			var ipPara2Up = ipThatTheSpaceDown.MoveByKey(new KeyEventArgs(Keys.Up));
			VerifyIp(ipPara2Up, para2, "", true, "back up aligned with near end line 1");

			var ipThisIsTheDayUp = ipPara2Up.MoveByKey(new KeyEventArgs(Keys.Up));
			VerifyIp(ipThisIsTheDayUp, para1, "This i~^s the~ day", true, "up from para2 aligned near end line 1");
			// It's going to be looking for a position right at the boundary...either assocPrev would be
			// reasonable.
			var ipThisIdTh2Up = ipThisIsTheDayUp.MoveByKey(new KeyEventArgs(Keys.Up));
			VerifyIp(ipThisIdTh2Up, para1, "This i~^s th", false, "up from end para 1 aligned near end line 1");

			//var ipPara2_2 = ipThisIsTheDay.MoveByKey(new KeyEventArgs(Keys.Down));
			//VerifyIp(ipPara2_2, para2, "", true, "down from end para 1");

			// Todo:
			// HandleSpecialKey is called from OnKeyDown and should handle at least these:
				//case Keys.PageUp:
				//case Keys.PageDown:
				//case Keys.End:
				//case Keys.Home:
				//case Keys.Left: // done
				//case Keys.Up:
				//case Keys.Right: // done
				//case Keys.Down:
				//case Keys.F7: // the only two function keys currently known to the Views code,
				//case Keys.F8: // used for left and right arrow by string character amounts.
			// Test Left: (done)
			// - char to char in same line
			//	- skipping diacritics
			//	- skipping surrogate pairs
			// - to another line in same paragraph
			// - to previous (empty?) paragraph
			// - at very start (nothing happens)
			// - range collapses to start
			// - anything special to test if there are multiple runs? e.g., at boundary
			// - skip over embedded pictures
			// - eventually drop into embedded boxes that contain text?
			// Similarly right (done)
			// Down:
			// - same para, there is text below
			// - same para, no text immediately below on same line (goes to end of previous line)
			//  - eventually: what should happen if logical and physical end of next line don't coincide?
			// - down again to a longer line: should stay aligned with start position (what resets this??)
			// etc for others.
		}
示例#39
0
		public void BasicDragMove()
		{
			var styles = new AssembledStyles();
			var root = new RootBoxFdo(styles);
			var mock1 = new MockData1(23, 23);
			mock1.SimpleThree = "This is the day";
			var engine = new FakeRenderEngine() { Ws = 23, SegmentHeight = 13 };
			var factory = new FakeRendererFactory();
			factory.SetRenderer(23, engine);
			root.Builder.Show(Display.Of(() => mock1.SimpleThree, 23));
			var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			PaintTransform ptrans = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96);
			MockSite site = new MockSite();
			site.m_transform = ptrans;
			site.m_vwGraphics = m_gm.VwGraphics;
			root.Site = site;

			SelectionBuilder.In(root).Offset("This ".Length).To.Offset("This is ".Length).Install();

			var dataObj = new DataObject(DataFormats.StringFormat, "is ");
			int x = FakeRenderEngine.SimulatedWidth("This is the ") + 2;
			var location = new Point(x, 8);

			// A drag to where we can drop, allowing both copy and move, no keys held
			var dragArgs = new DragEventArgs(dataObj, (int)DragDropKeyStates.None, 200, 300,
				DragDropEffects.Copy | DragDropEffects.Move,
				DragDropEffects.None);
			root.OnDragEnter(dragArgs, location, m_gm.VwGraphics, ptrans);
			Assert.That(dragArgs.Effect, Is.EqualTo(DragDropEffects.Move));
			Assert.That(root.DragState, Is.EqualTo(WindowDragState.DraggingHere));

			var qcdArgs = new QueryContinueDragEventArgs((int) DragDropKeyStates.None, false, DragAction.Drop);
			root.OnQueryContinueDrag(qcdArgs);
			Assert.That(root.DragState, Is.EqualTo(WindowDragState.InternalMove));
			root.OnDragLeave();
			Assert.That(root.DragState, Is.EqualTo(WindowDragState.InternalMove), "DragLeave should not clear InternalMove");

			root.OnDragDrop(dragArgs, location, m_gm.VwGraphics, ptrans);
			Assert.That(mock1.SimpleThree, Is.EqualTo("This the is day"));
			Assert.That(root.DragState, Is.EqualTo(WindowDragState.None));

			// Now let's drag the 'is' out to another window.
			SelectionBuilder.In(root).Offset("This the ".Length).To.Offset("This the is ".Length).Install();
			qcdArgs = new QueryContinueDragEventArgs((int)DragDropKeyStates.None, false, DragAction.Drop);
			root.OnQueryContinueDrag(qcdArgs);
			Assert.That(root.DragState, Is.EqualTo(WindowDragState.None),
				"We should only set InternalMove if this window is the destination");
			Assert.That(mock1.SimpleThree, Is.EqualTo("This the day"));

			// Check that we can't drag inside our own selection.
			SelectionBuilder.In(root).Offset("This ".Length).To.Offset("This the".Length).Install();
			x = FakeRenderEngine.SimulatedWidth("This t") + 2;
			location = new Point(x, 8);
			dragArgs = new DragEventArgs(dataObj, (int)DragDropKeyStates.None, 200, 300,
							DragDropEffects.Copy | DragDropEffects.Move,
							DragDropEffects.None);
			root.DragState = WindowDragState.InternalMove;
			root.OnDragDrop(dragArgs, location, m_gm.VwGraphics, ptrans);
			Assert.That(dragArgs.Effect, Is.EqualTo(DragDropEffects.None));
			Assert.That(mock1.SimpleThree, Is.EqualTo("This the day"));
		}
示例#40
0
		public void DrawIPMultiRunPara()
		{
			var styles = new AssembledStyles();
			RootBox root = new RootBoxFdo(styles);
			root.Builder.Show(Paragraph.Containing(
				Display.Of("first"), Display.Of("second"), Display.Of("third")));
			SetupFakeRootSite(root);
			var layoutInfo = HookupTests.MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);
			root.Layout(layoutInfo);
			InsertionPoint ip = root.SelectAtEnd();
			ip.Install();
			var para = (ParaBox) root.FirstBox;
			Assert.AreEqual(ip, root.Selection);
			Assert.AreEqual(para, ip.Para, "IP should know about the paragraph it is in");
			Assert.AreEqual("third".Length, ip.StringPosition, "IP position is relative to run");
			Assert.AreEqual(true, ip.AssociatePrevious, "selection at end should always associate previous in non-empty para");


			StringBox sbox = para.FirstBox as StringBox;
			Assert.That(sbox, Is.EqualTo(para.LastBox), "uniform text in infinite width should make one string box");
			var seg = sbox.Segment as FakeSegment;
			Assert.IsNotNull(seg);
			PaintTransform ptrans = new PaintTransform(2, 4, 96, 100, 0, -10, 120, 128);
			ip.Draw(m_gm.VwGraphics, ptrans);
			VerifySegmentDrawing(para, sbox, seg.LastDrawIpCall, -4);

			seg.NextPosIpResult = new MockSegment.PositionsOfIpResults();
			seg.NextPosIpResult.RectPrimary = new Rect(5, 6, 7, 9);
			seg.NextPosIpResult.PrimaryHere = true;
			Rectangle selRect = ip.GetSelectionLocation(m_gm.VwGraphics, ptrans);
			VerifySelLocation(para, sbox, seg.LastPosIpCall, -4);
			Assert.AreEqual(new Rectangle(5, 6, 2, 3), selRect);
		}
示例#41
0
		public void CombinedParaOperationsFdo()
		{
			// Set up a simple multi-para layout using the ObjSeq2 and SimpleThree properties of MockData1
			AssembledStyles styles = new AssembledStyles();
			var root = new RootBoxFdo(styles);
			var text = Cache.ServiceLocator.GetInstance<ITextFactory>().Create();
			//Cache.LangProject.TextsOC.Add(text);
			var owner = Cache.ServiceLocator.GetInstance<IStTextFactory>().Create();
			text.ContentsOA = owner;
			IStTxtPara p1 = MakePara(owner, "Hello World");
			var p2 = MakePara(owner,"This is a test");
			m_actionHandler.EndUndoTask(); // Finish settin up data, we want to control from now on.

			var po = new StTextParagraphOperations(owner);
			root.Builder.Show(Display.Of(() => owner.ParagraphsOS).Using((builder, para) => builder.AddString(()
				=> ((IStTxtPara)para).Contents)).EditParagraphsUsing(po));
			SetupFakeRootSite(root);
			var layoutInfo = HookupTests.MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);
			root.Layout(layoutInfo);
			var ip = root.FirstBox.SelectAtEnd();

			// Insert at end of paragraph.
			m_actionHandler.BeginUndoTask("undo insert line break", "redo insert");
			ip.InsertLineBreak();
			m_actionHandler.EndUndoTask();
			Assert.That(owner.ParagraphsOS.Count, Is.EqualTo(3));
			Assert.That(owner.ParagraphsOS[0], Is.EqualTo(p1));
			Assert.That(owner.ParagraphsOS[2], Is.EqualTo(p2));
			var p3 = (IStTxtPara)owner.ParagraphsOS[1]; // empty inserted paragraph.
			Assert.That(p3.Contents.Length, Is.EqualTo(0));
			Assert.That(p3.Contents.get_WritingSystem(0), Is.EqualTo(Cache.DefaultVernWs));
			((MockSite)root.Site).DoPendingAfterNotificationTasks();
			ip = (InsertionPoint)root.Selection;
			Assert.That(root.FirstBox.Next.Next, Is.Not.Null);
			Assert.That(ip.StringPosition, Is.EqualTo(0));
			Assert.That(ip.Para, Is.EqualTo(root.FirstBox.Next));

			// Insert at start of paragraph. To make it unambiguously the start, give p3 some data,
			// and since that might eventually destroy the selection, reset it.
			var rootHookup = ip.Hookup.ParentHookup.ParentHookup; // StringHookup, ItemHookup, Sequence
			UndoableUnitOfWorkHelper.Do("adjust contents", "redo", m_actionHandler,
				() => p3.Contents = Cache.TsStrFactory.MakeString("First insert", Cache.DefaultVernWs));
			ip = (InsertionPoint)SelectionBuilder.In(rootHookup)[1].Offset(0).Install();
			m_actionHandler.BeginUndoTask("undo insert line break", "redo insert");
			ip.InsertLineBreak();
			m_actionHandler.EndUndoTask();
			Assert.That(owner.ParagraphsOS.Count, Is.EqualTo(4));
			Assert.That(owner.ParagraphsOS[0], Is.EqualTo(p1));
			Assert.That(owner.ParagraphsOS[2], Is.EqualTo(p3));
			Assert.That(owner.ParagraphsOS[3], Is.EqualTo(p2));
			var p4 = (IStTxtPara)owner.ParagraphsOS[1]; // empty inserted paragraph (before p3).
			Assert.That(root.FirstBox.Next.Next.Next, Is.Not.Null);
			Assert.That(p4.Contents.get_WritingSystem(0), Is.EqualTo(Cache.DefaultVernWs));
			((MockSite)root.Site).DoPendingAfterNotificationTasks();
			ip = (InsertionPoint)root.Selection;
			Assert.That(ip.StringPosition, Is.EqualTo(0));
			Assert.That(ip.Para, Is.EqualTo(root.FirstBox.Next.Next));

			// Split a paragraph.
			var oldObjects = owner.ParagraphsOS.ToArray();
			ip = (InsertionPoint)SelectionBuilder.In(rootHookup)[2].Offset("First ".Length).Install();
			m_actionHandler.BeginUndoTask("undo insert line break", "redo insert");
			ip.InsertLineBreak();
			m_actionHandler.EndUndoTask();
			Assert.That(owner.ParagraphsOS.Count, Is.EqualTo(5));
			Assert.That(owner.ParagraphsOS[1], Is.EqualTo(oldObjects[1]));
			Assert.That(owner.ParagraphsOS[2], Is.EqualTo(oldObjects[2]));
			Assert.That(owner.ParagraphsOS[4], Is.EqualTo(oldObjects[3])); // insert between 2 and 3
			var p5 = (IStTxtPara)owner.ParagraphsOS[3]; // inserted paragraph.
			((MockSite)root.Site).DoPendingAfterNotificationTasks();
			ip = (InsertionPoint)root.Selection;
			Assert.That(ip.StringPosition, Is.EqualTo(0));
			Assert.That(ip.Para, Is.EqualTo(root.FirstBox.Next.Next.Next));
			Assert.That(((IStTxtPara)owner.ParagraphsOS[2]).Contents.Text, Is.EqualTo("First "));
			Assert.That(((IStTxtPara)owner.ParagraphsOS[3]).Contents.Text, Is.EqualTo("insert"));

			// Combine two paragraphs by backspace at start of line.
			oldObjects = owner.ParagraphsOS.ToArray();
			m_actionHandler.BeginUndoTask("undo backspace", "redo backspace");
			ip.Backspace();
			m_actionHandler.EndUndoTask();
			Assert.That(owner.ParagraphsOS.Count, Is.EqualTo(4));
			Assert.That(owner.ParagraphsOS[1], Is.EqualTo(oldObjects[1]));
			Assert.That(owner.ParagraphsOS[2], Is.EqualTo(oldObjects[2]));
			Assert.That(owner.ParagraphsOS[3], Is.EqualTo(oldObjects[4])); // delete item 3
			((MockSite)root.Site).DoPendingAfterNotificationTasks();
			ip = (InsertionPoint)root.Selection;
			Assert.That(ip.StringPosition, Is.EqualTo("First ".Length));
			Assert.That(ip.Para, Is.EqualTo(root.FirstBox.Next.Next));
			Assert.That(((IStTxtPara)owner.ParagraphsOS[2]).Contents.Text, Is.EqualTo("First insert"));
		}
示例#42
0
        public void BasicPaste()
        {
            var styles = new AssembledStyles();
            var root   = new RootBoxFdo(styles);
            var mock1  = new MockData1(23, 23);

            mock1.SimpleThree = "old contents";
            var engine = new FakeRenderEngine()
            {
                Ws = 23, SegmentHeight = 13
            };
            var factory = new FakeRendererFactory();

            factory.SetRenderer(23, engine);
            root.Builder.Show(Display.Of(() => mock1.SimpleThree, 23));
            var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);

            root.Layout(layoutArgs);
            PaintTransform ptrans = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96);
            MockSite       site   = new MockSite();

            site.m_transform  = ptrans;
            site.m_vwGraphics = m_gm.VwGraphics;
            root.Site         = site;

            var dataObj  = new DataObject(DataFormats.StringFormat, "new ");
            int x        = FakeRenderEngine.SimulatedWidth("new old ") + 2;
            var location = new Point(x, 8);

            Clipboard.SetDataObject("");

            Assert.That(root.CanPaste(), Is.EqualTo(false), "Should not be able to Paste");
            root.OnEditPaste();
            Assert.That(mock1.SimpleThree, Is.EqualTo("old contents"), "Nothing should have changed");

            MouseEventArgs e = new MouseEventArgs(MouseButtons.Left, 1, 2, location.Y, 0);

            root.OnMouseDown(e, Keys.None, site.m_vwGraphics, site.m_transform);

            Clipboard.SetDataObject(dataObj);
            Assert.That(root.CanPaste(), Is.EqualTo(true), "Should be able to Paste");
            root.OnEditPaste();
            Assert.That(mock1.SimpleThree, Is.EqualTo("new old contents"), "Selected String should be \"new old contents\"");
            Assert.That(Clipboard.GetDataObject().GetData(DataFormats.StringFormat), Is.Not.EqualTo(null), "Selected String should not be null");
            Assert.That(Clipboard.GetDataObject().GetData(DataFormats.StringFormat), Is.EqualTo("new "), "Selected String should be \"new \"");

            dataObj  = new DataObject(DataFormats.StringFormat, "new ");
            x        = FakeRenderEngine.SimulatedWidth("") + 2;
            location = new Point(x, 8);
            e        = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);
            Clipboard.SetDataObject(dataObj);

            root.OnMouseDown(e, Keys.None, site.m_vwGraphics, site.m_transform);
            x        = FakeRenderEngine.SimulatedWidth("new old ") + 2;
            location = new Point(x, 8);
            e        = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);
            root.OnMouseMove(e, Keys.None, site.m_vwGraphics, site.m_transform);

            Assert.That(root.Selection, Is.Not.EqualTo(null), "Selection should now be assigned");
            Assert.That(root.Selection.DragDropData, Is.Not.EqualTo(null), "Selection should now be assigned");
            root.OnEditPaste();
            Assert.That(mock1.SimpleThree, Is.EqualTo("new contents"), "Selected String should be \"new contents\"");
            Assert.That(Clipboard.GetDataObject().GetData(DataFormats.StringFormat), Is.EqualTo("new "), "Selected String should be \"new \"");
        }
示例#43
0
		public void PileAndBlock()
		{
			var root = new RootBoxFdo(new AssembledStyles());
			SetupFakeRootSite(root);
			var layoutInfo = HookupTests.MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);
			root.RendererFactory = layoutInfo.RendererFactory;
			var mock1 = new MockData1() { SimpleThree = "This is the first paragraph." };
			// The length of the second paragraph is found by experiment to be enough so that
			// despite its lacking borders it also breaks into 2 lines in the second step.
			var mock2 = new MockData1() { SimpleThree = "Here is another paragraph. It needs to be a bit longer." };
			root.Builder.Show(
				Div.Containing(
					Display.Block(Color.Red, 25000, 18000).BackColor(Color.Purple)
						.Margins(3000, 3000, 3000, 3000)
						.Border(5000, Color.Blue)
						.Pads(4000, 4000, 4000, 4000),
					Display.Block(Color.Green, 25000, 18000)
					).BackColor(Color.Pink) // these apply to div.
						.Margins(1000, 1000, 1000, 1000)
						.Border(2000, Color.Gold)
						.Pads(6000, 6000, 6000, 6000));
			root.Layout(layoutInfo);
			// We want to keep track of the sequence of paint operations in all three segments.
			var drawActions = new List<object>();
			var vg = new MockGraphics();
			vg.DrawActions = drawActions;

			var site = (MockSite)root.Site;
			root.Paint(vg, site.m_transform);
			var paintTrans = site.m_transform;
			int position = 0;
			int xOffset = 2 - 100; // how far it is pushed over by the offsets of the layoutInfo
			int yOffset = 2 - 200; // how far it is pushed down by the offsets of the layoutInfo

			int red = (int)ColorUtil.ConvertColorToBGR(Color.Red);
			int pink = (int)ColorUtil.ConvertColorToBGR(Color.Pink);
			int purple = (int)ColorUtil.ConvertColorToBGR(Color.Purple);
			int blue = (int)ColorUtil.ConvertColorToBGR(Color.Blue);
			int green = (int)ColorUtil.ConvertColorToBGR(Color.Green);
			int gold = (int)ColorUtil.ConvertColorToBGR(Color.Gold);
			// Technically we could do different conversions in the two directions, but for this test both dpi are the same.
			int margPile = layoutInfo.MpToPixelsX(1000);
			int bordPile = layoutInfo.MpToPixelsX(2000);
			int padPile = layoutInfo.MpToPixelsX(6000);
			int blockWidth = layoutInfo.MpToPixelsX(25000);
			int blockHeight = layoutInfo.MpToPixelsX(18000);
			int margBlock = layoutInfo.MpToPixelsX(3000);
			int bordBlock = layoutInfo.MpToPixelsX(5000);
			int padBlock = layoutInfo.MpToPixelsX(4000);

			// First a background rectangle for the whole pile.
			var leftPilePad = margPile + bordPile + xOffset;
			var topPilePad = margPile + bordPile + yOffset;
			var rightPilePad = margPile + bordPile + 2 * padPile + blockWidth + 2 * margBlock + 2 * bordBlock + 2 * padBlock + xOffset;
			var bottomPilePad = margPile + bordPile + 2 * padPile + 2 * blockHeight + 2 * margBlock + 2 * bordBlock + 2 * padBlock + yOffset;
			VerifyRect(drawActions, ref position, leftPilePad, topPilePad, rightPilePad, bottomPilePad, pink);
			// Left border, whole pile
			VerifyRect(drawActions, ref position, leftPilePad - bordPile, topPilePad - bordPile,
				leftPilePad, bottomPilePad + bordPile, gold);
			// top border, whole pile
			VerifyRect(drawActions, ref position, leftPilePad - bordPile, topPilePad - bordPile,
				rightPilePad + bordPile, topPilePad, gold);
			// right border, whole pile
			VerifyRect(drawActions, ref position, rightPilePad, topPilePad - bordPile,
				rightPilePad + bordPile, bottomPilePad + bordPile, gold);
			// bottom border, whole pile
			VerifyRect(drawActions, ref position, leftPilePad - bordPile, bottomPilePad,
				rightPilePad + bordPile, bottomPilePad + bordPile, gold);

			// background and border for first block.
			var leftBlockPad = margPile + bordPile + padPile + margBlock + bordBlock + xOffset;
			var topBlockPad = margPile + bordPile + padPile + margBlock + bordBlock + yOffset;
			var rightBlockPad = margPile + bordPile + padPile + margBlock + bordBlock + 2 * padBlock + blockWidth + xOffset;
			var bottomBlockPad = margPile + bordPile + padPile + margBlock + bordBlock + 2 * padBlock + blockHeight + yOffset;
			VerifyRect(drawActions, ref position, leftBlockPad, topBlockPad, rightBlockPad, bottomBlockPad, purple);
			// Left border, whole pile
			VerifyRect(drawActions, ref position, leftBlockPad - bordBlock, topBlockPad - bordBlock,
				leftBlockPad, bottomBlockPad + bordBlock, blue);
			// top border, whole pile
			VerifyRect(drawActions, ref position, leftBlockPad - bordBlock, topBlockPad - bordBlock,
				rightBlockPad + bordBlock, topBlockPad, blue);
			// right border, whole pile
			VerifyRect(drawActions, ref position, rightBlockPad, topBlockPad - bordBlock,
				rightBlockPad + bordBlock, bottomBlockPad + bordBlock, blue);
			// bottom border, whole pile
			VerifyRect(drawActions, ref position, leftBlockPad - bordBlock, bottomBlockPad,
				rightBlockPad + bordBlock, bottomBlockPad + bordBlock, blue);
			// The first block itself.
			VerifyRect(drawActions, ref position, leftBlockPad + padBlock, topBlockPad + padBlock,
				leftBlockPad + padBlock + blockWidth, topBlockPad + padBlock + blockHeight, red);
			// The second block itself.
			var topBlock2 = bottomBlockPad + bordBlock + margBlock;
			VerifyRect(drawActions, ref position, leftPilePad + padPile, topBlock2,
				leftPilePad + padPile + blockWidth, topBlock2 + blockHeight, green);
			// And that should be all!
			Assert.That(position, Is.EqualTo(drawActions.Count));

			// A quick check that Relayout puts things in the same places.
			drawActions.Clear();
			var fixupMap = new Dictionary<Box, Rectangle>();
			var div1 = (DivBox) root.FirstBox;
			var block1 = div1.FirstBox;
			fixupMap[div1] = new Rectangle(0, 0, 10, 10);
			fixupMap[block1] = new Rectangle(0, 0, 10, 10);
			var oldblock1Left = block1.Left;
			var oldblock1bTop = block1.Top;
			using (var lcb = new LayoutCallbacks(root))
				root.Relayout(layoutInfo, fixupMap, lcb);
			Assert.That(drawActions.Count, Is.EqualTo(0));
			Assert.That(div1.FirstBox.Left, Is.EqualTo(oldblock1Left));
			Assert.That(div1.FirstBox.Top, Is.EqualTo(oldblock1bTop));
		}
示例#44
0
        public void MultiParaPaste()
        {
            var styles = new AssembledStyles();
            var root   = new RootBoxFdo(styles);
            var owner  = new MockData1(23, 23);
            var mock1  = new MockData1(23, 23);

            owner.InsertIntoObjSeq1(0, mock1);
            mock1.SimpleThree = "This has made";
            var engine = new FakeRenderEngine()
            {
                Ws = 23, SegmentHeight = 13
            };
            var factory = new FakeRendererFactory();

            factory.SetRenderer(23, engine);
            var            layoutInfo = HookupTests.MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 23);
            PaintTransform ptrans     = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96);
            MockSite       site       = new MockSite();

            site.m_transform  = ptrans;
            site.m_vwGraphics = m_gm.VwGraphics;
            root.Site         = site;
            var po = new MockReceiveParagraphOperations();

            root.Builder.Show(Display.Of(() => owner.ObjSeq1).Using((bldr, md) => bldr.AddString(() => md.SimpleThree, 23))
                              .EditParagraphsUsing(po));
            var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);

            root.Layout(layoutArgs);

            int x        = FakeRenderEngine.SimulatedWidth("This ") + 2;
            var location = new Point(x, 8);

            Clipboard.SetDataObject("is the\r\nday that the\r\nLord ");

            MouseEventArgs e = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);

            root.OnMouseDown(e, Keys.None, site.m_vwGraphics, site.m_transform);
            Assert.That(root.CanPaste(), Is.EqualTo(true), "Should be able to paste");
            root.OnEditPaste();
            Assert.That(Clipboard.GetDataObject().GetData(DataFormats.StringFormat),
                        Is.EqualTo("is the\r\nday that the\r\nLord "),
                        "Selected String should be \"is the\nday that the\nLord \"");
            Assert.That(owner.ObjSeq1[0].SimpleThree + owner.ObjSeq1[1].SimpleThree + owner.ObjSeq1[2].SimpleThree,
                        Is.EqualTo("This is the" + "day that the" + "Lord has made"));


            x        = FakeRenderEngine.SimulatedWidth("") + 2;
            location = new Point(x, 8);
            e        = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);
            root.OnMouseDown(e, Keys.None, site.m_vwGraphics, site.m_transform);

            mock1.SimpleThree = "";
            owner             = new MockData1();
            owner.InsertIntoObjSeq1(0, mock1);
            root.Builder.Show(
                Display.Of(() => owner.ObjSeq1).Using((bldr, md) => bldr.AddString(() => md.SimpleThree, 23)).EditParagraphsUsing(po));
            root.Layout(layoutArgs);

            Clipboard.SetDataObject(
                "\r\nThis is the\r\n\r\n\r\nDay that the\r\nLord\r\n\r\nHas\r\n\r\n\r\nMade\r\nW\r\n");

            Assert.That(root.CanPaste(), Is.EqualTo(true), "Should be able to paste");
            root.OnEditPaste();
            string testString = "";

            foreach (MockData1 obj in owner.ObjSeq1)
            {
                string nextString = obj.SimpleThree;
                testString += "\r\n";
                testString += nextString;
            }
            Assert.That(testString,
                        Is.EqualTo("\r\nThis is the\r\n\r\n\r\nDay that the\r\nLord\r\n\r\nHas\r\n\r\n\r\nMade\r\nW\r\n\r\n"));
        }
示例#45
0
		public void DiffWS()
		{
			var tsf = TsStrFactoryClass.Create();
			var styles = new AssembledStyles();
			var root = new RootBoxFdo(styles);
			var mock1 = new MockData1(23, 23);
			mock1.SimpleTwo = tsf.MakeString("newoldcontents", 23);
			var bldr = mock1.SimpleTwo.GetBldr();
			bldr.SetIntPropValues(3, 6, (int)FwTextPropType.ktptWs,
				(int)FwTextPropVar.ktpvDefault, 24);
			bldr.SetIntPropValues(6, 14, (int)FwTextPropType.ktptWs,
				(int)FwTextPropVar.ktpvDefault, 25);
			mock1.SimpleTwo = bldr.GetString();
			var engine = new FakeRenderEngine() { Ws = 23, SegmentHeight = 13 };
			var factory = new FakeRendererFactory();
			factory.SetRenderer(23, engine);
			root.Builder.Show(Display.Of(() => mock1.SimpleTwo));
			var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			PaintTransform ptrans = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96);
			MockSite site = new MockSite();
			site.m_transform = ptrans;
			site.m_vwGraphics = m_gm.VwGraphics;
			root.Site = site;

			int x = FakeRenderEngine.SimulatedWidth("ne") + 2;
			var location = new Point(x, 8);
			EventArgs e = new EventArgs();
			MouseEventArgs m = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);

			root.OnMouseDown(m, Keys.None, site.m_vwGraphics, site.m_transform);
			root.OnMouseClick(m, Keys.None, site.m_vwGraphics, site.m_transform);
			root.OnDoubleClick(e);
			Assert.That(!root.Selection.IsInsertionPoint, "Should be ranged selection");
			Assert.That((root.Selection as RangeSelection).SelectedText(), Is.EqualTo("new"));

			x = FakeRenderEngine.SimulatedWidth("new") + 2;
			location = new Point(x, 8);
			m = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);
			root.OnMouseDown(m, Keys.None, site.m_vwGraphics, site.m_transform);
			root.OnMouseClick(m, Keys.None, site.m_vwGraphics, site.m_transform);
			root.OnDoubleClick(e);
			Assert.That(!root.Selection.IsInsertionPoint, "Should be ranged selection");
			Assert.That((root.Selection as RangeSelection).SelectedText(), Is.EqualTo("old"));

			x = FakeRenderEngine.SimulatedWidth("newold") + 2;
			location = new Point(x, 8);
			m = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);
			root.OnMouseDown(m, Keys.None, site.m_vwGraphics, site.m_transform);
			root.OnMouseClick(m, Keys.None, site.m_vwGraphics, site.m_transform);
			root.OnDoubleClick(e);
			Assert.That(!root.Selection.IsInsertionPoint, "Should be ranged selection");
			Assert.That((root.Selection as RangeSelection).SelectedText(), Is.EqualTo("contents"));

			x = FakeRenderEngine.SimulatedWidth("newold");
			location = new Point(x, 8); // at the right edge of the d at the end of newold
			m = new MouseEventArgs(MouseButtons.Left, 1, location.X, location.Y, 0);
			root.OnMouseDown(m, Keys.None, site.m_vwGraphics, site.m_transform);
			root.OnMouseClick(m, Keys.None, site.m_vwGraphics, site.m_transform);
			root.OnDoubleClick(e);
			Assert.That(!root.Selection.IsInsertionPoint, "Should be ranged selection");
			Assert.That((root.Selection as RangeSelection).SelectedText(), Is.EqualTo("old"));
		}
示例#46
0
        public void CombinedParaOperationsFdo()
        {
            // Set up a simple multi-para layout using the ObjSeq2 and SimpleThree properties of MockData1
            AssembledStyles styles = new AssembledStyles();
            var             root   = new RootBoxFdo(styles);
            var             text   = Cache.ServiceLocator.GetInstance <ITextFactory>().Create();
            //Cache.LangProject.TextsOC.Add(text);
            var owner = Cache.ServiceLocator.GetInstance <IStTextFactory>().Create();

            text.ContentsOA = owner;
            IStTxtPara p1 = MakePara(owner, "Hello World");
            var        p2 = MakePara(owner, "This is a test");

            m_actionHandler.EndUndoTask();             // Finish settin up data, we want to control from now on.

            var po = new StTextParagraphOperations(owner);

            root.Builder.Show(Display.Of(() => owner.ParagraphsOS).Using((builder, para) => builder.AddString(()
                                                                                                              => ((IStTxtPara)para).Contents)).EditParagraphsUsing(po));
            SetupFakeRootSite(root);
            var layoutInfo = HookupTests.MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);

            root.Layout(layoutInfo);
            var ip = root.FirstBox.SelectAtEnd();

            // Insert at end of paragraph.
            m_actionHandler.BeginUndoTask("undo insert line break", "redo insert");
            ip.InsertLineBreak();
            m_actionHandler.EndUndoTask();
            Assert.That(owner.ParagraphsOS.Count, Is.EqualTo(3));
            Assert.That(owner.ParagraphsOS[0], Is.EqualTo(p1));
            Assert.That(owner.ParagraphsOS[2], Is.EqualTo(p2));
            var p3 = (IStTxtPara)owner.ParagraphsOS[1];             // empty inserted paragraph.

            Assert.That(p3.Contents.Length, Is.EqualTo(0));
            Assert.That(p3.Contents.get_WritingSystem(0), Is.EqualTo(Cache.DefaultVernWs));
            ((MockSite)root.Site).DoPendingAfterNotificationTasks();
            ip = (InsertionPoint)root.Selection;
            Assert.That(root.FirstBox.Next.Next, Is.Not.Null);
            Assert.That(ip.StringPosition, Is.EqualTo(0));
            Assert.That(ip.Para, Is.EqualTo(root.FirstBox.Next));

            // Insert at start of paragraph. To make it unambiguously the start, give p3 some data,
            // and since that might eventually destroy the selection, reset it.
            var rootHookup = ip.Hookup.ParentHookup.ParentHookup;             // StringHookup, ItemHookup, Sequence

            UndoableUnitOfWorkHelper.Do("adjust contents", "redo", m_actionHandler,
                                        () => p3.Contents = Cache.TsStrFactory.MakeString("First insert", Cache.DefaultVernWs));
            ip = (InsertionPoint)SelectionBuilder.In(rootHookup)[1].Offset(0).Install();
            m_actionHandler.BeginUndoTask("undo insert line break", "redo insert");
            ip.InsertLineBreak();
            m_actionHandler.EndUndoTask();
            Assert.That(owner.ParagraphsOS.Count, Is.EqualTo(4));
            Assert.That(owner.ParagraphsOS[0], Is.EqualTo(p1));
            Assert.That(owner.ParagraphsOS[2], Is.EqualTo(p3));
            Assert.That(owner.ParagraphsOS[3], Is.EqualTo(p2));
            var p4 = (IStTxtPara)owner.ParagraphsOS[1];             // empty inserted paragraph (before p3).

            Assert.That(root.FirstBox.Next.Next.Next, Is.Not.Null);
            Assert.That(p4.Contents.get_WritingSystem(0), Is.EqualTo(Cache.DefaultVernWs));
            ((MockSite)root.Site).DoPendingAfterNotificationTasks();
            ip = (InsertionPoint)root.Selection;
            Assert.That(ip.StringPosition, Is.EqualTo(0));
            Assert.That(ip.Para, Is.EqualTo(root.FirstBox.Next.Next));

            // Split a paragraph.
            var oldObjects = owner.ParagraphsOS.ToArray();

            ip = (InsertionPoint)SelectionBuilder.In(rootHookup)[2].Offset("First ".Length).Install();
            m_actionHandler.BeginUndoTask("undo insert line break", "redo insert");
            ip.InsertLineBreak();
            m_actionHandler.EndUndoTask();
            Assert.That(owner.ParagraphsOS.Count, Is.EqualTo(5));
            Assert.That(owner.ParagraphsOS[1], Is.EqualTo(oldObjects[1]));
            Assert.That(owner.ParagraphsOS[2], Is.EqualTo(oldObjects[2]));
            Assert.That(owner.ParagraphsOS[4], Is.EqualTo(oldObjects[3])); // insert between 2 and 3
            var p5 = (IStTxtPara)owner.ParagraphsOS[3];                    // inserted paragraph.

            ((MockSite)root.Site).DoPendingAfterNotificationTasks();
            ip = (InsertionPoint)root.Selection;
            Assert.That(ip.StringPosition, Is.EqualTo(0));
            Assert.That(ip.Para, Is.EqualTo(root.FirstBox.Next.Next.Next));
            Assert.That(((IStTxtPara)owner.ParagraphsOS[2]).Contents.Text, Is.EqualTo("First "));
            Assert.That(((IStTxtPara)owner.ParagraphsOS[3]).Contents.Text, Is.EqualTo("insert"));

            // Combine two paragraphs by backspace at start of line.
            oldObjects = owner.ParagraphsOS.ToArray();
            m_actionHandler.BeginUndoTask("undo backspace", "redo backspace");
            ip.Backspace();
            m_actionHandler.EndUndoTask();
            Assert.That(owner.ParagraphsOS.Count, Is.EqualTo(4));
            Assert.That(owner.ParagraphsOS[1], Is.EqualTo(oldObjects[1]));
            Assert.That(owner.ParagraphsOS[2], Is.EqualTo(oldObjects[2]));
            Assert.That(owner.ParagraphsOS[3], Is.EqualTo(oldObjects[4]));             // delete item 3
            ((MockSite)root.Site).DoPendingAfterNotificationTasks();
            ip = (InsertionPoint)root.Selection;
            Assert.That(ip.StringPosition, Is.EqualTo("First ".Length));
            Assert.That(ip.Para, Is.EqualTo(root.FirstBox.Next.Next));
            Assert.That(((IStTxtPara)owner.ParagraphsOS[2]).Contents.Text, Is.EqualTo("First insert"));
        }
示例#47
0
        public void BackgroundAndUnderlinePainting()
        {
            var     styles = new AssembledStyles();
            RootBox root   = new RootBoxFdo(styles);

            SetupFakeRootSite(root);
            var layoutInfo = HookupTests.MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);

            root.RendererFactory = layoutInfo.RendererFactory;
            root.Builder.Show(
                Paragraph.Containing(
                    Display.Of("plain"),
                    Display.Of("underOnYellow").Underline(FwUnderlineType.kuntSingle).BackColor(Color.Yellow)
                    ),
                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)
                    )
                );
            root.Layout(layoutInfo);

            var para1      = (ParaBox)root.FirstBox;
            var stringBox1 = (StringBox)para1.FirstBox;
            var seg1       = (FakeSegment)stringBox1.Segment;
            // A convenient place to test that literals get Chrp with default user ws.
            LgCharRenderProps chrp;
            int ichMin, ichLim;

            para1.Source.GetCharProps(0, out chrp, out ichMin, out ichLim);
            Assert.That(chrp.ws, Is.EqualTo(layoutInfo.RendererFactory.UserWs));
            // This segment has just one chunk of underline, the second run.
            seg1.NextCharPlacementResults.Add(new FakeSegment.CharPlacementResults()
            {
                Lefts = new[] { 10 }, Rights = new[] { 20 }, Tops = new[] { 15 }
            });
            // Todo: add expectations for each run of underlining.

            var para2      = (ParaBox)para1.Next;
            var stringBox2 = (StringBox)para2.FirstBox;
            var seg2       = (FakeSegment)stringBox2.Segment;

            // For the double red underline, we'll pretend there are two line segments.
            seg2.NextCharPlacementResults.Add(new FakeSegment.CharPlacementResults()
            {
                Lefts = new[] { 5, 15 }, Rights = new[] { 10, 20 }, Tops = new[] { 15, 16 }
            });
            seg2.NextCharPlacementResults.Add(new FakeSegment.CharPlacementResults()
            {
                Lefts = new[] { 12 }, Rights = new[] { 22 }, Tops = new[] { 13 }
            });
            seg2.NextCharPlacementResults.Add(new FakeSegment.CharPlacementResults()
            {
                Lefts = new[] { 30 }, Rights = new[] { 41 }, Tops = new[] { 12 }
            });

            var para3      = (ParaBox)para2.Next;
            var stringBox3 = (StringBox)para3.FirstBox;
            var seg3       = (FakeSegment)stringBox3.Segment;

            seg3.NextCharPlacementResults.Add(new FakeSegment.CharPlacementResults()
            {
                Lefts = new[] { 0 }, Rights = new[] { 10 }, Tops = new[] { 11 }
            });
            seg3.NextCharPlacementResults.Add(new FakeSegment.CharPlacementResults()
            {
                Lefts = new[] { 10 }, Rights = new[] { 20 }, Tops = new[] { 11 }
            });
            seg3.NextCharPlacementResults.Add(new FakeSegment.CharPlacementResults()
            {
                Lefts = new[] { 30 }, Rights = new[] { 40 }, Tops = new[] { 11 }
            });

            // We want to keep track of the sequence of paint operations in all three segments.
            var drawActions = new List <object>();

            seg1.DrawActions = seg2.DrawActions = seg3.DrawActions = drawActions;
            var vg = new MockGraphics();

            vg.DrawActions = drawActions;

            var site = (MockSite)root.Site;

            root.Paint(vg, site.m_transform);
            var paintTrans = site.m_transform;

            // We should have asked about each run of distinct underlining.
            VerifyCharPlacementCall(seg1, 0, "plain".Length, "plain".Length + "underOnYellow".Length,
                                    paintTrans.SourceRect, paintTrans.DestRect, vg, 1);

            // para/seg 2
            Rect srcRect = paintTrans.SourceRect;

            srcRect.top    -= para1.Height;
            srcRect.bottom -= para1.Height;
            VerifyCharPlacementCall(seg2, 0, 0, "doubleRedOnPink".Length,
                                    srcRect, paintTrans.DestRect, vg, 2);
            VerifyCharPlacementCall(seg2, 0, "doubleRedOnPink".Length, "doubleRedOnPink".Length + "dotted".Length,
                                    srcRect, paintTrans.DestRect, vg, 1);
            VerifyCharPlacementCall(seg2, 0, "doubleRedOnPink".Length + "dotted".Length,
                                    "doubleRedOnPink".Length + "dotted".Length + "dottedOnYellow".Length,
                                    srcRect, paintTrans.DestRect, vg, 1);

            // para/seg 3
            srcRect.top    -= para2.Height;
            srcRect.bottom -= para2.Height;
            VerifyCharPlacementCall(seg3, 0, 0, "dashed".Length,
                                    srcRect, paintTrans.DestRect, vg, 1);
            VerifyCharPlacementCall(seg3, 0, "dashed".Length, "dashed".Length + "dashedRed".Length,
                                    srcRect, paintTrans.DestRect, vg, 1);
            VerifyCharPlacementCall(seg3, 0, "dashed".Length + "dashedRed".Length,
                                    "dashed".Length + "dashedRed".Length + "squiggle".Length,
                                    srcRect, paintTrans.DestRect, vg, 1);
            // Todo: eventually arrange a run where ichBase is non-zero, and check what happens.

            // We want to check a lot of things about the drawing.
            // - all the background color and underline drawing should happen before any of the text drawing.
            // - the right stuff should be drawn to construct the underlines
            // - in particular dotted, dashed, and squiggle underlines should have the gaps and alternations
            // aligned, even if in different segments.

            // Todo: check actual line segs drawn

            int position = 0;             // in drawActions

            // Normal calls to Draw have the effect of painting the background. All three backgrounds
            // should be painted before the foreground. First we paint seg1 with background, since it has some.
            VerifyDraw(drawActions, ref position, seg1);
            // Next we draw its one horizontal line of underline.
            VerifyHorzLine(drawActions, ref position, 10, 20, 15, 1, new int[] { int.MaxValue }, 10);

            // Then segment 2's background
            VerifyDraw(drawActions, ref position, seg2);
            // And various lots of underline: double takes 2 per segment
            VerifyHorzLine(drawActions, ref position, 5, 10, 17, 1, new int[] { int.MaxValue }, 5);
            VerifyHorzLine(drawActions, ref position, 5, 10, 15, 1, new int[] { int.MaxValue }, 5);
            VerifyHorzLine(drawActions, ref position, 15, 20, 18, 1, new int[] { int.MaxValue }, 15);
            VerifyHorzLine(drawActions, ref position, 15, 20, 16, 1, new int[] { int.MaxValue }, 15);
            // dotted has non-trivial array of dx values (2 pix each)
            VerifyHorzLine(drawActions, ref position, 12, 22, 13, 1, new int[] { 2, 2 }, 12);
            // dotted has non-trivial array of dx values (2 pix each)
            VerifyHorzLine(drawActions, ref position, 30, 41, 12, 1, new int[] { 2, 2 }, 30);
            // No background in para 3, doesn't get a draw background call.
            //VerifyDraw(drawActions, ref position, seg3);
            // But underlines still drawn in the background phase
            // Dashed line
            VerifyHorzLine(drawActions, ref position, 0, 10, 11, 1, new int[] { 6, 3 }, 0);
            VerifyHorzLine(drawActions, ref position, 10, 20, 11, 1, new int[] { 6, 3 }, 10);
            // Todo: verify line segs drawn for squiggle.
            VerifyLine(drawActions, ref position, 30, 12, 32, 10, ColorUtil.ConvertColorToBGR(Color.Black));
            VerifyLine(drawActions, ref position, 32, 10, 34, 12, ColorUtil.ConvertColorToBGR(Color.Black));
            VerifyLine(drawActions, ref position, 34, 12, 36, 10, ColorUtil.ConvertColorToBGR(Color.Black));
            VerifyLine(drawActions, ref position, 36, 10, 38, 12, ColorUtil.ConvertColorToBGR(Color.Black));
            VerifyLine(drawActions, ref position, 38, 12, 40, 10, ColorUtil.ConvertColorToBGR(Color.Black));
            VerifyNbDraw(drawActions, ref position, seg1);
            VerifyNbDraw(drawActions, ref position, seg2);
            VerifyDraw(drawActions, ref position, seg3);
        }
示例#48
0
        public void NullObjChecker()
        {
            var owner  = new MockData1(55, 77);
            var child1 = new MockData1(55, 77);

            child1.SimpleThree = "This is a Test";
            owner.SimpleFour   = null;
            var styles     = new AssembledStyles();
            var root       = new RootBoxFdo(styles);
            var layoutInfo = MakeLayoutInfo(int.MaxValue / 2, m_gm.VwGraphics, 55);

            SetupFakeRootSite(root);
            var      engine = layoutInfo.RendererFactory.GetRenderer(55, m_gm.VwGraphics) as FakeRenderEngine;
            MockSite site   = new MockSite();

            root.Site = site;
            PaintTransform ptrans = new PaintTransform(2, 4, 96, 100, 0, 10, 120, 128);

            site.m_transform  = ptrans;
            site.m_vwGraphics = m_gm.VwGraphics;
            root.Builder.Show(Display.OfObj(() => owner.SimpleFour).Using((bldr, md) => bldr.AddString(() => md.SimpleThree, 55)));
            root.Layout(layoutInfo);

            int invalidateWidth1    = FakeRenderEngine.SimulatedWidth(child1.SimpleThree) + 2 * RootBox.InvalidateMargin;
            var expectedInvalidate1 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
                                                    invalidateWidth1, engine.SegmentHeight + 2 * RootBox.InvalidateMargin);

            VerifyParagraphs(root, new string[0]);
            Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for this unconnected object should not exist");
            Assert.That(owner.SimpleFourHookupCount, Is.EqualTo(1), "The hookup for this null object should exist");

            site.RectsInvalidatedInRoot.Clear();
            owner.SimpleFour = child1;
            int invalidateWidth2    = FakeRenderEngine.SimulatedWidth(child1.SimpleThree) + 2 * RootBox.InvalidateMargin;
            var expectedInvalidate2 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
                                                    invalidateWidth2, engine.SegmentHeight + 2 * RootBox.InvalidateMargin);

            VerifyParagraphs(root, new[] { child1.SimpleThree });
            Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(1), "The hookup for this object should exist");
            Assert.That(owner.SimpleFourHookupCount, Is.EqualTo(1), "The hookup for this object should exist");
            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate2));

            site.RectsInvalidatedInRoot.Clear();
            owner.SimpleFour = null;
            int invalidateWidth3    = FakeRenderEngine.SimulatedWidth(child1.SimpleThree) + 2 * RootBox.InvalidateMargin;
            var expectedInvalidate3 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
                                                    invalidateWidth3, engine.SegmentHeight + 2 * RootBox.InvalidateMargin);

            VerifyParagraphs(root, new string[0]);
            Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for this unconnected object should not exist");
            Assert.That(owner.SimpleFourHookupCount, Is.EqualTo(1), "The hookup for this null object should exist");
            Assert.That(site.RectsInvalidatedInRoot, Has.Member(expectedInvalidate3));

            site.RectsInvalidatedInRoot.Clear();
            owner.SimpleFour = null;
            int invalidateWidth4    = FakeRenderEngine.SimulatedWidth(child1.SimpleThree) + 2 * RootBox.InvalidateMargin;
            var expectedInvalidate4 = new Rectangle(-RootBox.InvalidateMargin, -RootBox.InvalidateMargin,
                                                    invalidateWidth3, engine.SegmentHeight + 2 * RootBox.InvalidateMargin);

            VerifyParagraphs(root, new string[0]);
            Assert.That(child1.SimpleThreeHookupCount, Is.EqualTo(0), "The hookup for this unconnected object should not exist");
            Assert.That(owner.SimpleFourHookupCount, Is.EqualTo(1), "The hookup for this null object should exist");
            Assert.That(site.RectsInvalidatedInRoot, Is.Empty, "Nothing changed, so nothing should be invalidated");
        }