예제 #1
0
        public void GetOrderedValue_extraVoElements_sameSequence()
        {
            // Setup
            AppendTestItemToList("Second");
            AppendTestItemToList("Third");
            var initialSeq = m_testList.PossibilitiesOS.Cast <ICmObject>();
            var myvo       = CreateTestVO(initialSeq);

            // Make sure test setup worked
            Assert.AreEqual(1, m_voRepo.Count, "There ought to be one VO object.");
            Assert.AreEqual(3, myvo.ItemsRS.Count, "Wrong number of items in VO.");
            // Delete an element from the 'testing' sequence.
            var newList = m_testList.PossibilitiesOS.ToList();

            newList.RemoveAt(0);
            var newSeq = newList.Cast <ICmObject>();

            // SUT
            var resultSeq = VirtualOrderingServices.GetOrderedValue(m_testList, possibilitiesFlid, newSeq);

            // Verify
            Assert.AreEqual(1, m_voRepo.Count, "There ought to still be one VO object.");
            Assert.AreEqual(2, resultSeq.Count(), "Wrong number of items in result.");
            Assert.AreEqual(newSeq, resultSeq, "Hvo lists differ.");
        }
예제 #2
0
        public void GetOrderedValue_extraNativeAndExtraVoElements()
        {
            // Setup
            AppendTestItemToList("Second");
            AppendTestItemToList("Third");
            var initialSeq = m_testList.PossibilitiesOS.Cast <ICmObject>();

            CreateTestVO(initialSeq);
            // Make sure test setup worked
            Assert.AreEqual(1, m_voRepo.Count, "There ought to be one VO object.");
            // Make a sequence in a different order
            AppendTestItemToList("Fourth");
            var newList = m_testList.PossibilitiesOS.Reverse().ToList();

            // remove 'First' (which is now at the end)
            newList.RemoveAt(newList.Count - 1);
            var newSeq = newList.Cast <ICmObject>();

            // SUT
            var resultSeq = VirtualOrderingServices.GetOrderedValue(m_testList, possibilitiesFlid, newSeq);

            // Verify
            Assert.AreEqual(1, m_voRepo.Count, "There ought to still be one VO object.");
            // result should be (Second, Third, Fourth) (or reverse of newSeq)
            var actualList = newSeq.Reverse().ToList();

            Assert.AreEqual(actualList, resultSeq, "Hvo lists differ.");
        }
예제 #3
0
        public void GetOrderedValue_extraVoElements_diffSequence()
        {
            // Setup
            AppendTestItemToList("Second");
            AppendTestItemToList("Third");
            var initialSeq = m_testList.PossibilitiesOS.Cast <ICmObject>();

            CreateTestVO(initialSeq);
            // Make sure test setup worked
            Assert.AreEqual(1, m_voRepo.Count, "There ought to be one VO object.");
            // Make a sequence in a different order
            var newList = m_testList.PossibilitiesOS.Reverse().ToList();

            newList.RemoveAt(0);
            var newSeq = newList.Cast <ICmObject>();


            // SUT
            var resultSeq = VirtualOrderingServices.GetOrderedValue(m_testList, possibilitiesFlid, newSeq);

            // Verify
            Assert.AreEqual(1, m_voRepo.Count, "There ought to still be one VO object.");
            var resultList = new List <ICmObject>(resultSeq);            // makes it easier to verify results

            Assert.AreEqual(2, resultList.Count);
            Assert.AreEqual("First", ((ICmPossibility)resultList[0]).Name.AnalysisDefaultWritingSystem.Text,
                            "Wrong element at beginning of result sequence.");
            Assert.AreEqual("Second", ((ICmPossibility)resultList[1]).Name.AnalysisDefaultWritingSystem.Text,
                            "Wrong element at end of result sequence.");
        }
예제 #4
0
        public void ReferringSenses()
        {
            // Verify that if we make three lex entries whose senses all refer to niño,
            // that the reversal index shows them in alphabetical order: boy, child, girl.
            var girl       = (LexEntry)MakeEntry("girl", "niño");
            var senseGirl  = girl.SensesOS.First();
            var boy        = (LexEntry)MakeEntry("boy", "niño");
            var senseBoy   = boy.SensesOS.First();
            var child      = (LexEntry)MakeEntry("child", "niño");
            var senseChild = child.SensesOS.First();

            var lexDb = Cache.ServiceLocator.GetInstance <ILexDbRepository>().Singleton;
            var ri    = Cache.ServiceLocator.GetInstance <IReversalIndexFactory>().Create();

            lexDb.ReversalIndexesOC.Add(ri);
            var rie = MakeReversalIndexReference(senseGirl, "niño", ri);

            senseBoy.ReversalEntriesRC.Add(rie);
            senseChild.ReversalEntriesRC.Add(rie);

            Assert.That(rie.ReferringSenses.First(), Is.EqualTo(senseBoy));
            Assert.That(rie.ReferringSenses.Skip(1).First(), Is.EqualTo(senseChild));
            Assert.That(rie.ReferringSenses.Last(), Is.EqualTo(senseGirl));

            // we now manually reorder the senses
            var flid = Cache.MetaDataCacheAccessor.GetFieldId2(ReversalIndexEntryTags.kClassId, "ReferringSenses", false);

            VirtualOrderingServices.SetVO(rie, flid, new ICmObject[] { senseGirl, senseChild, senseBoy });
            Assert.That(rie.ReferringSenses.First(), Is.EqualTo(senseGirl));
            Assert.That(rie.ReferringSenses.Skip(1).First(), Is.EqualTo(senseChild));
            Assert.That(rie.ReferringSenses.Last(), Is.EqualTo(senseBoy));
        }
예제 #5
0
        public void SetExistingVO_diffSequence()
        {
            // Setup
            AppendTestItemToList("Second");
            AppendTestItemToList("Third");
            var initialSeq = m_testList.PossibilitiesOS.Cast <ICmObject>();

            CreateTestVO(initialSeq);
            // Make sure test setup worked
            Assert.AreEqual(1, m_voRepo.Count, "There ought to be one VO object.");
            // Make a sequence in a different order
            var newSeq = m_testList.PossibilitiesOS.Reverse().Cast <ICmObject>();

            // SUT
            VirtualOrderingServices.SetVO(m_testList, possibilitiesFlid, newSeq);

            // Verify
            Assert.AreEqual(1, m_voRepo.Count, "There ought to still be one VO object.");
            var myvo = m_voRepo.AllInstances().First();

            Assert.AreEqual(m_testList.Hvo, myvo.SourceRA.Hvo, "Got wrong Source object!");
            Assert.AreEqual(possName, myvo.Field, "VO is on the wrong field!");
            var voList = myvo.ItemsRS;

            Assert.AreEqual(newSeq, voList, "Hvo lists differ.");
        }
예제 #6
0
        public void VisibleComplexFormBackRefs()
        {
            // Verify that if we make lex entries blackboard and blackbird, blackboard correctly comes first.
            var black        = (LexEntry)MakeEntry("black", "nonreflecting");
            var blackbird    = (LexEntry)MakeEntry("blackbird", "dark avian");
            var blackboard   = (LexEntry)MakeEntry("blackboard", "something to write on");
            var lerBlackbird = MakeComplexEntryRef(blackbird);

            lerBlackbird.ComponentLexemesRS.Add(black);
            lerBlackbird.ShowComplexFormsInRS.Add(black);
            Assert.That(black.VisibleComplexFormBackRefs.First(), Is.EqualTo(lerBlackbird));

            var lerBlackboard = MakeComplexEntryRef(blackboard);

            lerBlackboard.ComponentLexemesRS.Add(black);
            lerBlackboard.ShowComplexFormsInRS.Add(black);
            Assert.That(black.VisibleComplexFormBackRefs.First(), Is.EqualTo(lerBlackbird), "although added later, blackbird is sorted first");
            Assert.That(black.VisibleComplexFormBackRefs.Skip(1).First(), Is.EqualTo(lerBlackboard));

            var flid = Cache.MetaDataCacheAccessor.GetFieldId2(LexEntryTags.kClassId, "VisibleComplexFormBackRefs", false);

            VirtualOrderingServices.SetVO(black, flid, new ICmObject[] { lerBlackboard, lerBlackbird });
            Assert.That(black.VisibleComplexFormBackRefs.First(), Is.EqualTo(lerBlackboard), "although added later, blackbird is sorted first");
            Assert.That(black.VisibleComplexFormBackRefs.Skip(1).First(), Is.EqualTo(lerBlackbird));
        }
예제 #7
0
        private IVirtualOrdering CreateTestVO(IEnumerable <ICmObject> desiredSeq)
        {
            VirtualOrderingServices.SetVO(m_testList, possibilitiesFlid, desiredSeq);
            var result = m_voRepo.AllInstances().Where(vo => vo.SourceRA == m_testList &&
                                                       vo.Field == possName);

            return(result.FirstOrDefault());
        }
예제 #8
0
 private void ReorderItems(List <ICmObject> vals)
 {
     if (RootPropertyIsRealRefSequence())
     {
         // Since we are re-ordering, presume all objects are replaced by the entire new value.
         Cache.DomainDataByFlid.Replace(m_rootObj.Hvo, m_rootFlid, 0, vals.Count,
                                        vals.Select(obj => obj.Hvo).ToArray(), vals.Count);
     }
     else
     {
         VirtualOrderingServices.SetVO(m_rootObj, m_rootFlid, vals);
     }
 }
예제 #9
0
        public void SetVO_nullSequence()
        {
            // Setup
            AppendTestItemToList("Second");
            // For this test, just keep the same order.
            var desiredSeq = m_testList.PossibilitiesOS.Cast <ICmObject>();
            var myvo       = CreateTestVO(desiredSeq);

            // Make sure test setup worked
            Assert.AreEqual(1, m_voRepo.Count, "There ought to be one VO object.");

            // SUT
            VirtualOrderingServices.SetVO(m_testList, possibilitiesFlid, null);

            // Verify
            Assert.AreEqual(0, m_voRepo.Count, "Test should have deleted the only VO object.");
        }
예제 #10
0
        public void VirtualPropTest()
        {
            // Setup
            CreateFakeGenreList();             // creates fake list of 4 genres on LangProj
            var testText   = CreateTestText(); // creates IText on LangProj with its IStText.
            var testStText = testText.ContentsOA;
            // Get LP Fake Genre list
            var entireGenreList = Cache.LangProject.GenreListOA.PossibilitiesOS.ToList();

            testText.GenresRC.Add(entireGenreList[1]);             // Second
            testText.GenresRC.Add(entireGenreList[2]);             // Third
            var initialSeq = testText.GenresRC.ToList();

            // Verify that setup affects our chosen virtual property
            Assert.AreEqual(2, testStText.GenreCategories.Count,
                            "Wrong number of items on virtual property.");
            var mdc      = Cache.MetaDataCacheAccessor;
            int virtFlid = mdc.GetFieldId2(testStText.ClassID, "GenreCategories", true);

            // SUT1
            VirtualOrderingServices.SetVO(testStText, virtFlid, initialSeq.Cast <ICmObject>());
            // Make sure SUT1 worked
            Assert.AreEqual(1, m_voRepo.Count, "There ought to be one VO object.");

            // Setup for SUT2
            // Make a sequence in a different order and with an extra item, but missing an original.
            var newList = new List <ICmObject>(entireGenreList.Cast <ICmObject>());

            newList.Reverse();             // now has (Fourth, Third, Second, First)
            // remove 'Second' (which is now at index=2)
            newList.RemoveAt(2);           // now has (Fourth, Third, First)

            // SUT2
            var resultSeq = VirtualOrderingServices.GetOrderedValue(testStText, virtFlid, newList);

            // Verify
            Assert.AreEqual(1, m_voRepo.Count, "There ought to still be one VO object.");
            // result should be (Third, Fourth, First)
            var actualList = new List <ICmPossibility> {
                entireGenreList[2], entireGenreList[3], entireGenreList[0]
            };
            var actualAsObj = actualList.Cast <ICmObject>();

            Assert.AreEqual(actualAsObj, resultSeq, "Hvo lists differ.");
        }
예제 #11
0
        public void GetOrderedValue_nonexistentVO()
        {
            // Setup
            AppendTestItemToList("Second");
            var initialSeq = m_testList.PossibilitiesOS.Cast <ICmObject>();

            // Make sure test setup worked
            Assert.AreEqual(0, m_voRepo.Count, "There shouldn't be an existing VO object.");
            // Make a sequence in a different order
            var newSeq = m_testList.PossibilitiesOS.Reverse().Cast <ICmObject>();

            // SUT
            var resultSeq = VirtualOrderingServices.GetOrderedValue(m_testList, possibilitiesFlid, newSeq);

            // Verify
            Assert.AreEqual(0, m_voRepo.Count, "There ought to still not be a VO object.");
            Assert.AreEqual(newSeq, resultSeq, "Hvo lists differ.");
        }
예제 #12
0
        public void GetOrderedValue_completeOverlap_diffSequence()
        {
            // Setup
            AppendTestItemToList("Second");
            AppendTestItemToList("Third");
            var initialSeq = m_testList.PossibilitiesOS.Cast <ICmObject>();

            CreateTestVO(initialSeq);
            // Make sure test setup worked
            Assert.AreEqual(1, m_voRepo.Count, "There ought to be one VO object.");
            // Make a sequence in a different order
            var newSeq = m_testList.PossibilitiesOS.Reverse().Cast <ICmObject>();

            // SUT
            var resultSeq = VirtualOrderingServices.GetOrderedValue(m_testList, possibilitiesFlid, newSeq);

            // Verify
            Assert.AreEqual(1, m_voRepo.Count, "There ought to still be one VO object.");
            Assert.AreEqual(3, resultSeq.Count(), "Wrong number of items in result.");
            Assert.AreEqual(initialSeq, resultSeq, "Hvo lists differ.");
        }
예제 #13
0
        public void GetOrderedValue_extraNativeElements_diffSequence()
        {
            // Setup
            AppendTestItemToList("Second");
            var initialSeq = m_testList.PossibilitiesOS.Cast <ICmObject>();

            CreateTestVO(initialSeq);
            // Make sure test setup worked
            Assert.AreEqual(1, m_voRepo.Count, "There ought to be one VO object.");
            // Make a sequence in a different order with an extra element
            AppendTestItemToList("Third");
            var newSeq = m_testList.PossibilitiesOS.Reverse().Cast <ICmObject>().ToList();

            // SUT
            var resultSeq = VirtualOrderingServices.GetOrderedValue(m_testList, possibilitiesFlid, newSeq);

            // Verify
            Assert.AreEqual(1, m_voRepo.Count, "There ought to still be one VO object.");
            newSeq.Reverse();             // the resulting sequence should be the reverse of what was fed in.
            Assert.AreEqual(newSeq, resultSeq, "Hvo lists differ.");
        }
예제 #14
0
        public void GetOrderedValue_extraNativeElements_sameSequence()
        {
            // Setup
            AppendTestItemToList("Second");
            var initialSeq = m_testList.PossibilitiesOS.Cast <ICmObject>();

            CreateTestVO(initialSeq);
            // Make sure test setup worked
            Assert.AreEqual(1, m_voRepo.Count, "There ought to be one VO object.");
            // Add to the 'testing' sequence
            AppendTestItemToList("Third");
            var newSeq = m_testList.PossibilitiesOS.Cast <ICmObject>();

            // SUT
            var resultSeq = VirtualOrderingServices.GetOrderedValue(m_testList, possibilitiesFlid, newSeq);

            // Verify
            Assert.AreEqual(1, m_voRepo.Count, "There ought to still be one VO object.");
            Assert.AreEqual(3, resultSeq.Count(), "Wrong number of items in result.");
            Assert.AreEqual(newSeq, resultSeq, "Hvo lists differ.");
            Assert.AreEqual("Third", ((ICmPossibility)resultSeq.Last()).Name.AnalysisDefaultWritingSystem.Text,
                            "Wrong element at end of result sequence.");
        }
예제 #15
0
        public void GetOrderedValue_completeOverlap_sameSequence()
        {
            // Setup
            AppendTestItemToList("Second");
            AppendTestItemToList("Third");
            var initialSeq = m_testList.PossibilitiesOS.Cast <ICmObject>();

            CreateTestVO(initialSeq);
            // Make sure test setup worked
            Assert.AreEqual(1, m_voRepo.Count, "There ought to be one VO object.");

            // SUT
            var resultSeq = VirtualOrderingServices.GetOrderedValue(m_testList, possibilitiesFlid, initialSeq);

            // Verify
            Assert.AreEqual(1, m_voRepo.Count, "There ought to still be one VO object.");
            var myvo = m_voRepo.AllInstances().First();

            Assert.AreEqual(m_testList.Hvo, myvo.SourceRA.Hvo, "Got wrong Source object!");
            Assert.AreEqual(possName, myvo.Field, "VO is on the wrong field!");
            var voList = myvo.ItemsRS;

            Assert.AreEqual(initialSeq, voList, "Hvo lists differ.");
        }
예제 #16
0
 internal void RemoveOrdering()
 {
     UndoableUnitOfWorkHelper.Do(DetailControlsStrings.ksUndoAlphabeticalOrder, DetailControlsStrings.ksRedoAlphabeticalOrder,
                                 Cache.ActionHandlerAccessor,
                                 () => VirtualOrderingServices.ResetVO(m_rootObj, m_rootFlid));
 }
예제 #17
0
        /// <summary>
        /// The main entry point to do the work of the original method.
        /// </summary>
        internal void Display(ref ITsString tssDelayedNumber)
        {
            MainCallerDisplayCommand dispInfo;

            if (!m_viewConstructor.CanGetMainCallerDisplayCommand(m_frag, out dispInfo))
            {
                // Shouldn't be possible, but just in case...
                Debug.Assert(true, "No MainCallerDisplayCommand!");
                return;
            }

            XmlNode listDelimitNode;             // has the list seps attrs like 'sep'
            XmlNode specialAttrsNode;            // has the more exotic ones like 'excludeHvo'

            listDelimitNode = specialAttrsNode = dispInfo.MainNode;
            // 'inheritSeps' attr means to use the 'caller' (the part ref node)
            // to get the separator information.
            if (XmlUtils.GetOptionalBooleanAttributeValue(listDelimitNode, "inheritSeps", false))
            {
                listDelimitNode = dispInfo.Caller;
            }
            //
            // 1. get number of items in vector
            //
            var chvo = m_sda.get_VecSize(m_hvo, m_flid);

            if (chvo == 0)
            {
                // We may want to do something special for empty vectors.  See LT-9687.
                ProcessEmptyVector(m_vwEnv, m_hvo, m_flid);
                return;
            }
            //
            // 2. for each item in the vector,
            //		a) print leading number if desired.
            //		b) call AddObj
            //		c) print separator if desired and needed
            //
            int[] rghvo = GetVector(m_sda, m_hvo, m_flid);
            Debug.Assert(chvo == rghvo.Length);
            //
            // Define some special boolean flags.
            //
            // Note that we deliberately don't use the listDelimitNode here.
            // These three props are not currently configurable, and they belong on the 'seq' element,
            // not the part ref.
            var fCheckForEmptyItems = XmlUtils.GetOptionalBooleanAttributeValue(specialAttrsNode,
                                                                                "checkForEmptyItems", false);
            string exclude    = XmlUtils.GetOptionalAttributeValue(specialAttrsNode, "excludeHvo", null);
            var    fFirstOnly = XmlUtils.GetOptionalBooleanAttributeValue(specialAttrsNode, "firstOnly", false);

            XmlAttribute xaNum;
            var          fNumber = SetNumberFlagIncludingSingleOption(listDelimitNode, chvo, out xaNum);

            ApplySortingIfSpecified(rghvo, specialAttrsNode);

            // Determine if sequence should be filtered by a stored list of Guids.
            // Note that if we filter, we replace rghvo with the filtered list.
            if (m_viewConstructor.ShouldFilterByGuid)
            {              // order by vector item type guids
                // Don't reorder LexEntry VisibleComplexFormBackRefs vector if the user overrode it manually.
                var obj = m_cache.ServiceLocator.GetObject(m_hvo);
                if (obj is ILexEntry)
                {
                    var lexEntry = obj as ILexEntry;
                    if (m_flid == m_cache.MetaDataCacheAccessor.GetFieldId("LexEntry", "VisibleComplexFormBackRefs", false))
                    {
                        if (!VirtualOrderingServices.HasVirtualOrdering(lexEntry, "VisibleComplexFormBackRefs"))
                        {
                            chvo = ApplyFilterToSequence(ref rghvo);
                        }
                    }
                    else
                    {
                        chvo = ApplyFilterToSequence(ref rghvo);
                    }
                }
                else
                {
                    chvo = ApplyFilterToSequence(ref rghvo);
                }
            }

            // Check whether the user wants the grammatical information to appear only once, preceding any
            // sense numbers, if there is only one set of grammatical information, and all senses refer to
            // it.  See LT-9663.
            var childFrag            = m_frag;
            var fSingleGramInfoFirst = false;

            if (m_flid == LexEntryTags.kflidSenses)
            {
                fSingleGramInfoFirst = XmlUtils.GetOptionalBooleanAttributeValue(listDelimitNode, "singlegraminfofirst", false);
            }

            // This groups senses by placing graminfo before the number, and omitting it if the same as the
            // previous sense in the entry.  This isn't yet supported by the UI, but may well be requested in
            // the future.  (See LT-9663.)
            //bool fGramInfoBeforeNumber = XmlUtils.GetOptionalBooleanAttributeValue(listDelimitNode, "graminfobeforenumber", false);

            // Setup text properties for any numbering
            int          wsEng        = m_cache.WritingSystemFactory.GetWsFromStr(strEng);
            ITsTextProps ttpNum       = null;
            var          fDelayNumber = false;

            if (fNumber)
            {
                ttpNum       = SetNumberTextProperties(wsEng, listDelimitNode);
                fDelayNumber = XmlUtils.GetOptionalBooleanAttributeValue(specialAttrsNode, "numdelay", false);
            }

            // A vector may be conditionally configured to display its objects as separate paragraphs
            // in dictionary (document) configuration.  See LT-9667.
            var fShowAsParagraphsInInnerPile = XmlUtils.GetOptionalBooleanAttributeValue(listDelimitNode,
                                                                                         "showasindentedpara", false);
            // We have (this is probably bad) two ways to do this. The better one is setting the flowType to divInPara.
            // When we do this for a vector, and configure properties that require us to insert numbering and so forth,
            // we currently force a paragraph for each item. It's too hard otherwise to get the numbers etc. into the paragraph.
            // This means that the X_AsPara layout which the configure dialog causes to be invoked when setting up sense-as-para
            // has to be configured NOT to make a paragraph. It also means we can't readily configure a view that has more than one
            // paragraph, except when doing another layer of inserting paragraphs into what is usually a single one. I don't like
            // this much but it does what we need for now and making it better looks very messy.
            var       fShowAsParagraphsInDivInPara = XmlUtils.GetOptionalAttributeValue(listDelimitNode, "flowType", null) == "divInPara";
            ITsString tssBefore  = null;
            string    sParaStyle = null;

            if (fShowAsParagraphsInInnerPile && chvo > 0)
            {
                sParaStyle = XmlUtils.GetOptionalAttributeValue(listDelimitNode, "style");
                tssBefore  = SetBeforeString(specialAttrsNode, listDelimitNode);
                // We need a line break here to force the inner pile of paragraphs to begin at
                // the margin, rather than somewhere in the middle of the line.
                m_vwEnv.AddString(m_cache.TsStrFactory.MakeString(StringUtils.kChHardLB.ToString(),
                                                                  m_cache.ServiceLocator.WritingSystems.DefaultAnalysisWritingSystem.Handle));
                m_vwEnv.OpenInnerPile();
            }
            else if (fShowAsParagraphsInDivInPara)
            {
                sParaStyle = XmlUtils.GetOptionalAttributeValue(listDelimitNode, "parastyle", "");
            }

            // Setup and run actual internal vector loop
            var tsf            = m_cache.TsStrFactory;
            var xattrSeparator = listDelimitNode.Attributes["sep"];
            var fFirst         = true;     // May actually mean first non-empty.

            for (var ihvo = 0; ihvo < chvo; ++ihvo)
            {
                if (IsExcluded(exclude, ihvo, rghvo))
                {
                    continue;
                }

                if (fCheckForEmptyItems && IsItemEmpty(rghvo[ihvo], childFrag))
                {
                    continue;
                }

                if (fShowAsParagraphsInInnerPile || fShowAsParagraphsInDivInPara)
                {
                    SetupParagraph(sParaStyle, (fFirst ? tssBefore : null), listDelimitNode);
                }

                // This needs to happen AFTER we wet up the paragraph that we want it to be part of
                // and any 'before' stuff that goes ahead of the whole sequence, but BEFORE we add any other stuff to the para.
                if (fFirst && fNumber && fSingleGramInfoFirst)
                {
                    var fAllMsaSame = SetAllMsaSameFlag(chvo, rghvo);
                    if (fAllMsaSame)
                    {
                        DisplayFirstChildPOS(rghvo[0], childFrag);
                    }

                    // Exactly if we put out the grammatical info at the start, we need to NOT put it out
                    // as part of each item. Note that we must not set this flag before we put out the one-and-only
                    // gram info, or that will be suppressed too!
                    m_viewConstructor.ShouldIgnoreGramInfo = fAllMsaSame;
                }

                if (!fShowAsParagraphsInInnerPile && !fShowAsParagraphsInDivInPara)
                {
                    AddSeparatorIfNeeded(fFirst, xattrSeparator, listDelimitNode, wsEng);
                }

                // add the numbering if needed.
                if (fNumber)
                {
                    var sTag = CalculateAndFormatSenseLabel(rghvo, ihvo, xaNum);

                    ITsStrBldr tsb = tsf.GetBldr();
                    tsb.Replace(0, 0, sTag, ttpNum);
                    ITsString tss = tsb.GetString();
                    m_numberPartRef = listDelimitNode;
                    AddNumberingNowOrDelayed(fDelayNumber, tss, out tssDelayedNumber);
                }

                // add the object.
                Debug.Assert(ihvo < rghvo.Length);
                m_vwEnv.AddObj(rghvo[ihvo], m_viewConstructor, childFrag);

                // Close Paragraph if displaying paragraphs
                if (fShowAsParagraphsInInnerPile || fShowAsParagraphsInDivInPara)
                {
                    m_vwEnv.CloseParagraph();
                }

                fFirst = false;
                if (fFirstOnly)
                {
                    break;
                }
            }             // end of sequence 'for' loop

            // Close Inner Pile if displaying paragraphs
            if (fShowAsParagraphsInInnerPile && chvo > 0)
            {
                m_vwEnv.CloseInnerPile();
            }

            // Reset the flag for ignoring grammatical information after the first if it was set
            // earlier in this method.
            if (fSingleGramInfoFirst)
            {
                m_viewConstructor.ShouldIgnoreGramInfo = false;
            }

            // Reset the flag for delaying displaying a number.
            if (m_viewConstructor.DelayNumFlag && m_hvo == m_hvoDelayedNumber)
            {
                m_viewConstructor.DelayNumFlag = false;
                tssDelayedNumber = null;
            }

            // end of Display method
        }
예제 #18
0
        /// <summary>
        /// The main entry point to do the work of the original method.
        /// </summary>
        internal void Display(ref ITsString tssDelayedNumber)
        {
            MainCallerDisplayCommand dispInfo;

            if (!m_viewConstructor.CanGetMainCallerDisplayCommand(m_frag, out dispInfo))
            {
                // Shouldn't be possible, but just in case...
                Debug.Assert(true, "No MainCallerDisplayCommand!");
                return;
            }

            XmlNode listDelimitNode;             // has the list seps attrs like 'sep'
            XmlNode specialAttrsNode;            // has the more exotic ones like 'excludeHvo'

            listDelimitNode = specialAttrsNode = dispInfo.MainNode;
            // 'inheritSeps' attr means to use the 'caller' (the part ref node)
            // to get the separator information.
            if (XmlUtils.GetOptionalBooleanAttributeValue(listDelimitNode, "inheritSeps", false))
            {
                listDelimitNode = dispInfo.Caller;
            }

            //
            // 1. get number of items in vector
            //
            var chvo = m_sda.get_VecSize(m_hvo, m_flid);

            if (chvo == 0)
            {
                // We may want to do something special for empty vectors.  See LT-9687.
                ProcessEmptyVector(m_vwEnv, m_hvo, m_flid);
                return;
            }
            //
            // 2. for each item in the vector,
            //		a) print leading number if desired.
            //		b) call AddObj
            //		c) print separator if desired and needed
            //
            int[] rghvo = GetVector(m_sda, m_hvo, m_flid);
            Debug.Assert(chvo == rghvo.Length);
            //
            // Define some special boolean flags.
            //
            // Note that we deliberately don't use the listDelimitNode here.
            // These three props are not currently configurable, and they belong on the 'seq' element,
            // not the part ref.
            var fCheckForEmptyItems = XmlUtils.GetOptionalBooleanAttributeValue(specialAttrsNode,
                                                                                "checkForEmptyItems", false);
            string exclude    = XmlUtils.GetOptionalAttributeValue(specialAttrsNode, "excludeHvo", null);
            var    fFirstOnly = XmlUtils.GetOptionalBooleanAttributeValue(specialAttrsNode, "firstOnly", false);

            XmlAttribute xaNum;
            var          fNumber = SetNumberFlagIncludingSingleOption(listDelimitNode, chvo, out xaNum);

            ApplySortingIfSpecified(rghvo, specialAttrsNode);

            // Determine if sequence should be filtered by a stored list of Guids.
            // Note that if we filter, we replace rghvo with the filtered list.
            if (m_viewConstructor.ShouldFilterByGuid)
            {              // order by vector item type guids
                // Don't reorder LexEntry VisibleComplexFormBackRefs vector if the user overrode it manually.
                var obj = m_cache.ServiceLocator.GetObject(m_hvo);
                if (obj is ILexEntry)
                {
                    var lexEntry = obj as ILexEntry;
                    if (m_flid == m_cache.MetaDataCacheAccessor.GetFieldId("LexEntry", "VisibleComplexFormBackRefs", false))
                    {
                        if (!VirtualOrderingServices.HasVirtualOrdering(lexEntry, "VisibleComplexFormBackRefs"))
                        {
                            chvo = ApplyFilterToSequence(ref rghvo);
                        }
                    }
                    else
                    {
                        chvo = ApplyFilterToSequence(ref rghvo);
                    }
                }
                else
                {
                    chvo = ApplyFilterToSequence(ref rghvo);
                }
            }

            // Check whether the user wants the grammatical information to appear only once, preceding any
            // sense numbers, if there is only one set of grammatical information, and all senses refer to
            // it.  See LT-9663.
            var childFrag            = m_frag;
            var fSingleGramInfoFirst = false;

            if (m_flid == LexEntryTags.kflidSenses)
            {
                fSingleGramInfoFirst = XmlUtils.GetOptionalBooleanAttributeValue(listDelimitNode, "singlegraminfofirst", false);
            }

            // This groups senses by placing graminfo before the number, and omitting it if the same as the
            // previous sense in the entry.  This isn't yet supported by the UI, but may well be requested in
            // the future.  (See LT-9663.)
            //bool fGramInfoBeforeNumber = XmlUtils.GetOptionalBooleanAttributeValue(listDelimitNode, "graminfobeforenumber", false);

            // Setup text properties for any numbering
            int          wsEng        = m_cache.WritingSystemFactory.GetWsFromStr(strEng);
            ITsTextProps ttpNum       = null;
            var          fDelayNumber = false;

            if (fNumber)
            {
                ttpNum       = SetNumberTextProperties(wsEng, listDelimitNode);
                fDelayNumber = XmlUtils.GetOptionalBooleanAttributeValue(specialAttrsNode, "numdelay", false);
            }

            // A vector may be conditionally configured to display its objects as separate paragraphs
            // in dictionary (document) configuration.  See LT-9667.
            var fShowAsParagraphsInInnerPile = XmlUtils.GetOptionalBooleanAttributeValue(listDelimitNode,
                                                                                         "showasindentedpara", false);
            // We have (this is probably bad) two ways to do this. The better one is setting the flowType to divInPara.
            // When we do this for a vector, and configure properties that require us to insert numbering and so forth,
            // we currently force a paragraph for each item. It's too hard otherwise to get the numbers etc. into the paragraph.
            // This means that the X_AsPara layout which the configure dialog causes to be invoked when setting up sense-as-para
            // has to be configured NOT to make a paragraph. It also means we can't readily configure a view that has more than one
            // paragraph, except when doing another layer of inserting paragraphs into what is usually a single one. I don't like
            // this much but it does what we need for now and making it better looks very messy.
            var       fShowAsParagraphsInDivInPara = XmlUtils.GetOptionalAttributeValue(listDelimitNode, "flowType", null) == "divInPara";
            ITsString tssBefore  = null;
            string    sParaStyle = null;

            if (fShowAsParagraphsInInnerPile && chvo > 0)
            {
                sParaStyle = XmlUtils.GetOptionalAttributeValue(listDelimitNode, "style");
                tssBefore  = SetBeforeString(specialAttrsNode, listDelimitNode);
                // We need a line break here to force the inner pile of paragraphs to begin at
                // the margin, rather than somewhere in the middle of the line.
                m_vwEnv.AddString(TsStringUtils.MakeString(StringUtils.kChHardLB.ToString(),
                                                           m_cache.ServiceLocator.WritingSystems.DefaultAnalysisWritingSystem.Handle));
                m_vwEnv.OpenInnerPile();
            }
            else if (fShowAsParagraphsInDivInPara)
            {
                sParaStyle = XmlUtils.GetOptionalAttributeValue(listDelimitNode, "parastyle", "");
            }

            // Setup and run actual internal vector loop
            var xattrSeparator = listDelimitNode.Attributes["sep"];
            var fFirst         = true;     // May actually mean first non-empty.
            WrapParagraphDisplayCommand tempCommand = null;
            int tempId = 0;

            if (fShowAsParagraphsInInnerPile || fShowAsParagraphsInDivInPara)
            {
                // We make a temporary command object, whose purpose is to wrap the paragraphs we want to create
                // here for each item and any embellishments we add INSIDE the display of each individual item.
                // This ensures that if we break those paragraphs (e.g., for subentries of a sense), all the
                // paragraphs for the outer object are still correctly nested inside the item.
                // This is especially important for XML export, where if the paragraph and object elements are
                // not correctly nested, we don't even have valid XML.
                // The command object's lifetime is only as long as this XmlVcDisplayVec,
                // because it references this XmlVcDisplayVec object and even updates some of its member variables.
                // I'm not sure it really has to do that, but I was trying to make a minimal change to the code
                // that had to be wrapped in the command object so it could be invoked by the AddObj call.
                // It is possible we could make a more permanent and reusable command object, but it would
                // require extensive analysis of at least how the member variables it modifies are used to make
                // sure it is safe. At this point I'm going for the safest change I can. This whole area of the
                // system is likely to be rewritten sometime.
                tempCommand = new WrapParagraphDisplayCommand(childFrag, this, sParaStyle, tssBefore,
                                                              listDelimitNode, fNumber, fDelayNumber, xaNum, ttpNum);
                tempId = m_viewConstructor.GetId(tempCommand);
                tempCommand.DelayedNumber = tssDelayedNumber;
            }
            for (var ihvo = 0; ihvo < chvo; ++ihvo)
            {
                if (IsExcluded(exclude, ihvo, rghvo))
                {
                    continue;
                }

                if (fCheckForEmptyItems && IsItemEmpty(rghvo[ihvo], childFrag))
                {
                    continue;
                }

                Debug.Assert(ihvo < rghvo.Length);
                if (fShowAsParagraphsInInnerPile || fShowAsParagraphsInDivInPara)
                {
                    // Passing tempId causes it to use the tempCommand we made above, which does
                    // much the same as the code in the else branch, except for wrapping the content
                    // of the object in a paragraph (and not inserting separators). In general we want to keep
                    // them the same, which is why the common code is wrapped in the AddItemEmbellishments
                    // method. The critical thing is that the paragraph must be part of the object,
                    // even though it is caused by the listDelimitNode attributes rather than by those
                    // of the XML that directly controls the display of the object.
                    m_vwEnv.AddObj(rghvo[ihvo], m_viewConstructor, tempId);
                }
                else
                {
                    // not part of add embellishments because never used with either showAsParagraphs option
                    AddSeparatorIfNeeded(fFirst, xattrSeparator, listDelimitNode, wsEng);
                    AddItemEmbellishments(listDelimitNode, fNumber, rghvo[ihvo], ihvo, xaNum, ttpNum, fDelayNumber, ref tssDelayedNumber);
                    m_vwEnv.AddObj(rghvo[ihvo], m_viewConstructor, childFrag);
                    fFirst = false;
                }

                if (fFirstOnly)
                {
                    break;
                }
            }             // end of sequence 'for' loop
            if (tempCommand != null)
            {
                tssDelayedNumber = tempCommand.DelayedNumber;                 // recover the end result of how it was modified.
                m_viewConstructor.RemoveCommand(tempCommand, tempId);
            }

            // Close Inner Pile if displaying paragraphs
            if (fShowAsParagraphsInInnerPile && chvo > 0)
            {
                m_vwEnv.CloseInnerPile();
            }

            // Reset the flag for ignoring grammatical information after the first if it was set
            // earlier in this method.
            if (fSingleGramInfoFirst)
            {
                m_viewConstructor.ShouldIgnoreGramInfo = false;
            }

            // Reset the flag for delaying displaying a number.
            if (m_viewConstructor.DelayNumFlag && m_hvo == m_hvoDelayedNumber)
            {
                m_viewConstructor.DelayNumFlag = false;
                tssDelayedNumber = null;
            }

            // end of Display method
        }