private void TestFeatureStructureContent(IFsFeatStruc featStruct)
        {
            IFdoOwningCollection <IFsFeatureSpecification> specCol = featStruct.FeatureSpecsOC;

            Assert.AreEqual(1, specCol.Count, "Count of top level feature specs");
            foreach (IFsFeatureSpecification spec in specCol)
            {
                IFsComplexValue complex = spec as IFsComplexValue;
                Assert.IsNotNull(complex, "complex feature value is null and should not be");
                Assert.AreEqual("subject agreement", complex.FeatureRA.Name.AnalysisDefaultWritingSystem.Text, "Expected complex feature name");
                IFsFeatStruc fsNested = complex.ValueOA as IFsFeatStruc;
                IFdoOwningCollection <IFsFeatureSpecification> fsNestedCol = fsNested.FeatureSpecsOC;
                Assert.AreEqual(2, fsNestedCol.Count, "Nested fs has one feature");
                foreach (IFsFeatureSpecification specNested in fsNestedCol)
                {
                    IFsClosedValue closed = specNested as IFsClosedValue;
                    Assert.IsNotNull(closed, "closed feature value is null and should not be");
                    if (!(((closed.FeatureRA.Name.AnalysisDefaultWritingSystem.Text == "gender") &&
                           (closed.ValueRA.Name.AnalysisDefaultWritingSystem.Text == "feminine gender")) ||
                          ((closed.FeatureRA.Name.AnalysisDefaultWritingSystem.Text == "person") &&
                           (closed.ValueRA.Name.AnalysisDefaultWritingSystem.Text == "first person"))))
                    {
                        Assert.Fail("Unexpected value found: {0}:{1}",
                                    closed.FeatureRA.Name.AnalysisDefaultWritingSystem.Text,
                                    closed.ValueRA.Name.AnalysisDefaultWritingSystem.Text);
                    }
                }
            }
        }
		/// <summary>
		///
		/// </summary>
		/// <param name="parent"></param>
		public override void Install(DataTree parent)
		{
			CheckDisposed();

			base.Install(parent);

			var ctrl = (PhonologicalFeatureListDlgLauncher)Control;

			m_flid = GetFlid(m_configurationNode, m_obj);
			if (m_flid != 0)
				m_fs = GetFeatureStructureFromOwner(m_obj, m_flid);
			else
			{
				m_fs = m_obj as IFsFeatStruc;
				m_flid = FsFeatStrucTags.kflidFeatureSpecs;
			}

			ctrl.Initialize((FdoCache)Mediator.PropertyTable.GetValue("cache"),
				m_fs,
				m_flid,
				"Name",
				m_persistenceProvider,
				Mediator,
				"Name",
				XmlUtils.GetOptionalAttributeValue(m_configurationNode, "ws", "analysis")); // TODO: Get better default 'best ws'.
		}
Beispiel #3
0
        protected void CreateFeatureStructureNodes(XmlDocument doc, XmlNode msaNode, IFsFeatStruc fs, int id, string sFSName)
        {
            if (fs == null)
            {
                return;
            }
            XmlNode fsNode = CreateXmlElement(doc, sFSName, msaNode);

            CreateXmlAttribute(doc, "id", id.ToString(), fsNode);
            foreach (IFsFeatureSpecification spec in fs.FeatureSpecsOC)
            {
                XmlNode feature = CreateXmlElement(doc, "feature", fsNode);
                XmlNode name    = CreateXmlElement(doc, "name", feature);
                name.InnerText = spec.FeatureRA.Abbreviation.BestAnalysisAlternative.Text;
                XmlNode        fvalue = CreateXmlElement(doc, "value", feature);
                IFsClosedValue cv     = spec as IFsClosedValue;
                if (cv != null)
                {
                    fvalue.InnerText = cv.ValueRA.Abbreviation.BestAnalysisAlternative.Text;
                }
                else
                {
                    IFsComplexValue complex = spec as IFsComplexValue;
                    if (complex == null)
                    {
                        continue;                         // skip this one since we're not dealing with it yet
                    }
                    IFsFeatStruc nestedFs = complex.ValueOA as IFsFeatStruc;
                    if (nestedFs != null)
                    {
                        CreateFeatureStructureNodes(doc, fvalue, nestedFs, 0, "fs");
                    }
                }
            }
        }
Beispiel #4
0
        private static FeatureStruct GetFeatureStruct(FeatureSystem featSys, IMoMorphSynAnalysis msa)
        {
            IFsFeatStruc fs      = null;
            var          stemMsa = msa as IMoStemMsa;

            if (stemMsa != null)
            {
                fs = stemMsa.MsFeaturesOA;
            }
            else
            {
                var inflMsa = msa as IMoInflAffMsa;
                if (inflMsa != null)
                {
                    fs = inflMsa.InflFeatsOA;
                }
                else
                {
                    var dervMsa = msa as IMoDerivAffMsa;
                    if (dervMsa != null)
                    {
                        fs = dervMsa.ToMsFeaturesOA;
                    }
                }
            }

            if (fs != null && !fs.IsEmpty)
            {
                return(GetFeatureStruct(featSys, fs));
            }

            return(null);
        }
Beispiel #5
0
        private static FeatureStruct GetFeatureStruct(FeatureSystem featSys, IFsFeatStruc fs)
        {
            var featStruct = new FeatureStruct();

            foreach (IFsFeatureSpecification featSpec in fs.FeatureSpecsOC)
            {
                var complexVal = featSpec as IFsComplexValue;
                if (complexVal != null)
                {
                    var cfs = complexVal.ValueOA as IFsFeatStruc;
                    if (complexVal.FeatureRA != null && cfs != null && !cfs.IsEmpty)
                    {
                        featStruct.AddValue(featSys.GetFeature(complexVal.FeatureRA.Hvo.ToString(CultureInfo.InvariantCulture)), GetFeatureStruct(featSys, cfs));
                    }
                }
                else
                {
                    var closedVal = featSpec as IFsClosedValue;
                    if (closedVal != null && closedVal.FeatureRA != null)
                    {
                        var           symFeat = featSys.GetFeature <SymbolicFeature>(closedVal.FeatureRA.Hvo.ToString(CultureInfo.InvariantCulture));
                        FeatureSymbol symbol;
                        if (symFeat.PossibleSymbols.TryGetValue(closedVal.ValueRA.Hvo.ToString(CultureInfo.InvariantCulture), out symbol))
                        {
                            featStruct.AddValue(symFeat, symbol);
                        }
                    }
                }
            }
            return(featStruct);
        }
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            //Debug.WriteLineIf(!disposing, "****************** " + GetType().Name + " 'disposing' is false. ******************");
            // Must not be run more than once.
            if (IsDisposed)
            {
                return;
            }

            base.Dispose(disposing);

            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
                if (m_vc != null)
                {
                    m_vc.Dispose();
                }
                m_sda.RemoveNotification(this);
            }
            m_vc  = null;
            m_fs  = null;
            m_sda = null;
        }
        private IMoMorphSynAnalysis GetMsaAndMoForm(ILexEntry entry, Guid slotType, IPartOfSpeech pos, FS inflFS, out IMoForm form)
        {
            IFsFeatStruc        fs = inflFS == null ? null : Cache.ServiceLocator.GetInstance <IFsFeatStrucFactory>().Create();
            IMoMorphSynAnalysis msa;

            if (slotType == MoMorphTypeTags.kguidMorphStem)
            {
                form = Cache.ServiceLocator.GetInstance <IMoStemAllomorphFactory>().Create();
                var stemMsa = Cache.ServiceLocator.GetInstance <IMoStemMsaFactory>().Create();
                msa = stemMsa;
                entry.MorphoSyntaxAnalysesOC.Add(msa);
                stemMsa.PartOfSpeechRA = pos;
                if (inflFS != null)
                {
                    stemMsa.MsFeaturesOA = fs;
                }
            }
            else
            {
                form = Cache.ServiceLocator.GetInstance <IMoAffixAllomorphFactory>().Create();
                var affixMsa = Cache.ServiceLocator.GetInstance <IMoInflAffMsaFactory>().Create();
                msa = affixMsa;
                entry.MorphoSyntaxAnalysesOC.Add(msa);
                affixMsa.PartOfSpeechRA = pos;
                if (inflFS != null)
                {
                    affixMsa.InflFeatsOA = fs;
                }
            }
            if (inflFS != null)
            {
                CreateFeatStruc(m_inflType, fs, inflFS);
            }
            return(msa);
        }
Beispiel #8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="parent"></param>
        public override void Install(DataTree parent)
        {
            CheckDisposed();

            base.Install(parent);

            MsaInflectionFeatureListDlgLauncher ctrl = (MsaInflectionFeatureListDlgLauncher)Control;

            m_flid = MsaInflectionFeatureListDlgLauncherSlice.GetFlid(m_configurationNode, m_obj);
            if (m_flid != 0)
            {
                m_fs = MsaInflectionFeatureListDlgLauncherSlice.GetFeatureStructureFromMSA(m_obj, m_flid);
            }
            else
            {
                m_fs   = m_obj as IFsFeatStruc;
                m_flid = FsFeatStrucTags.kflidFeatureSpecs;
            }

            ctrl.Initialize(m_propertyTable.GetValue <LcmCache>("cache"),
                            m_fs,
                            m_flid,
                            "Name",
                            ContainingDataTree.PersistenceProvder,
                            Mediator,
                            m_propertyTable,
                            "Name",
                            XmlUtils.GetOptionalAttributeValue(m_configurationNode, "ws", "analysis"));     // TODO: Get better default 'best ws'.
        }
Beispiel #9
0
        /// <summary>
        /// Load the tree items if the starting point is a feature structure.
        /// </summary>
        /// <param name="fs"></param>
        private void LoadPhonFeats(IFsFeatStruc fs)
        {
            m_flidDummyValue = DummyVirtualHandler.InstallDummyHandler(m_cache.VwCacheDaAccessor, "FsClosedFeature", "DummyValue",
                                                                       (int)CellarModuleDefns.kcptReferenceAtom).Tag;
            IVwCacheDa cda = m_cache.VwCacheDaAccessor;

            foreach (int hvoClosedFeature in m_cache.LangProject.PhFeatureSystemOA.FeaturesOC.HvoArray)
            {
                if (fs != null)
                {
                    IFsClosedValue closedValue = fs.FindClosedValue(hvoClosedFeature);
                    if (closedValue != null)
                    {
                        cda.CacheObjProp(hvoClosedFeature, m_flidDummyValue, closedValue.ValueRAHvo);
                    }
                    else
                    {                      // set the value to zero so nothing shows
                        cda.CacheObjProp(hvoClosedFeature, m_flidDummyValue, 0);
                    }
                }
                else
                {
                    // set the value to zero so nothing shows
                    cda.CacheObjProp(hvoClosedFeature, m_flidDummyValue, 0);
                }
            }
        }
        private void CreateFeatStruc(IFsFeatStrucType type, IFsFeatStruc fs, FS featVals)
        {
            fs.TypeRA = type;
            foreach (KeyValuePair <IFsFeatDefn, object> featVal in featVals)
            {
                var closedFeat = featVal.Key as IFsClosedFeature;
                if (closedFeat != null)
                {
                    var            sym = (IFsSymFeatVal)featVal.Value;
                    IFsClosedValue cv  = Cache.ServiceLocator.GetInstance <IFsClosedValueFactory>().Create();
                    fs.FeatureSpecsOC.Add(cv);
                    cv.FeatureRA = closedFeat;
                    cv.ValueRA   = sym;
                }
                else
                {
                    var             complexFeat = (IFsComplexFeature)featVal.Key;
                    IFsComplexValue cv          = Cache.ServiceLocator.GetInstance <IFsComplexValueFactory>().Create();
                    fs.FeatureSpecsOC.Add(cv);

                    IFsFeatStruc childFS = Cache.ServiceLocator.GetInstance <IFsFeatStrucFactory>().Create();
                    cv.FeatureRA = complexFeat;
                    cv.ValueOA   = childFS;
                    CreateFeatStruc(complexFeat.TypeRA, childFS, (FS)featVal.Value);
                }
            }
        }
        /// <summary>
        /// Listen for change to basic IPA symbol
        /// If description and/or features are empty, try to supply the values associated with the symbol
        /// </summary>
        /// <param name="hvo"></param>
        /// <param name="tag"></param>
        /// <param name="ivMin"></param>
        /// <param name="cvIns"></param>
        /// <param name="cvDel"></param>
        public void PropChanged(int hvo, int tag, int ivMin, int cvIns, int cvDel)
        {
            if (hvo == 0)
            {
                return;
            }
            // We only want to do something when the basic IPA symbol changes
            if ((tag != PhPhonemeTags.kflidFeatures) && (tag != FsFeatStrucTags.kflidFeatureSpecs))
            {
                return;
            }
            if (tag == FsFeatStrucTags.kflidFeatureSpecs)
            {
                IFsFeatStruc featStruc = m_fdoCache.ServiceLocator.GetInstance <IFsFeatStrucRepository>().GetObject(hvo);
                // only want to do something when the feature structure is part of a IPhPhoneme))
                if (featStruc.OwningFlid != PhPhonemeTags.kflidFeatures)
                {
                    return;
                }
            }
            if (tag == PhPhonemeTags.kflidFeatures && Phoneme != null && hvo == Phoneme.Hvo)
            {
                m_fs = Phoneme.FeaturesOA;
                if (m_fs != null && m_rootb != null)
                {
                    m_rootb.SetRootObject(m_fs.Hvo, m_vc, (int)VcFrags.kfragName, m_rootb.Stylesheet);
                }
            }

            if (m_rootb != null)
            {
                m_rootb.Reconstruct();
            }
        }
Beispiel #12
0
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            System.Diagnostics.Debug.WriteLineIf(!disposing, "****** Missing Dispose() call for " + GetType().Name + ". ****** ");
            // Must not be run more than once.
            if (IsDisposed)
            {
                return;
            }

            if (disposing)
            {
                if (m_helpProvider != null)
                {
                    m_helpProvider.Dispose();
                }
            }
            m_cache       = null;
            m_fs          = null;
            m_mediator    = null;
            m_cache       = null;
            m_bvList      = null;
            m_valuesCombo = null;

            base.Dispose(disposing);
        }
Beispiel #13
0
        /// <summary>
        /// If OK, then make FS have the selected feature value(s).
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void PhonologicalFeatureChooserDlg_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (DialogResult == DialogResult.OK)
            {
                Cursor = Cursors.WaitCursor;
                if (m_fs == null)
                {
                    // Didn't have one to begin with. See whether we want to create one.
                    if (m_hvoOwner != 0 && CheckFeatureStructure())
                    {
                        // The last argument is meaningless since we expect this property to be owning
                        // or collection.
                        int hvoFs = m_cache.CreateObject(FsFeatStruc.kClassId, m_hvoOwner, m_owningFlid, 0);
                        m_fs = (IFsFeatStruc)FsFeatStruc.CreateFromDBObject(m_cache, hvoFs, false);
                    }
                }

                if (m_fs != null)
                {
                    // clean out any extant features in the feature structure
                    foreach (IFsFeatureSpecification spec in m_fs.FeatureSpecsOC)
                    {
                        m_fs.FeatureSpecsOC.Remove(spec);
                    }
                    UpdateFeatureStructure();
                }
            }

            if (m_mediator != null)
            {
                m_mediator.PropertyTable.SetProperty("phonFeatListDlgLocation", Location);
                m_mediator.PropertyTable.SetProperty("phonFeatListDlgSize", Size);
            }
            Cursor = Cursors.Default;
        }
 private void AddNode(IFsFeatStruc fs, FeatureTreeNode parentNode)
 {
     foreach (IFsFeatureSpecification spec in fs.FeatureSpecsOC)
     {
         AddNode(spec, parentNode);
     }
 }
        /// <summary>
        /// Listen for change to basic IPA symbol
        /// If description and/or features are empty, try to supply the values associated with the symbol
        /// </summary>
        /// <param name="hvo"></param>
        /// <param name="tag"></param>
        /// <param name="ivMin"></param>
        /// <param name="cvIns"></param>
        /// <param name="cvDel"></param>
        public void PropChanged(int hvo, int tag, int ivMin, int cvIns, int cvDel)
        {
            if (hvo == 0)
            {
                return;
            }
            // We only want to do something when the basic IPA symbol changes
            if ((tag != (int)PhPhoneme.PhPhonemeTags.kflidFeatures) && (tag != (int)FsFeatStruc.FsFeatStrucTags.kflidFeatureSpecs))
            {
                return;
            }
            if (tag == (int)FsFeatStruc.FsFeatStrucTags.kflidFeatureSpecs)
            {
                // only want to do something when the feature structure is part of a PhPhoneme
                if (Cache.GetOwningFlidOfObject(hvo) != (int)PhPhoneme.PhPhonemeTags.kflidFeatures)
                {
                    return;
                }
            }
            if (tag == (int)PhPhoneme.PhPhonemeTags.kflidFeatures && Phoneme != null && hvo == Phoneme.Hvo)
            {
                m_fs = Phoneme.FeaturesOA;
                m_rootb.SetRootObject(Phoneme.FeaturesOAHvo, m_vc, (int)VcFrags.kfragName, m_rootb.Stylesheet);
            }

            if (m_rootb != null)
            {
                m_rootb.Reconstruct();
            }
        }
Beispiel #16
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="parent"></param>
        public override void Install(DataTree parent)
        {
            CheckDisposed();

            base.Install(parent);

            var ctrl = (PhonologicalFeatureListDlgLauncher)Control;

            m_flid = GetFlid(m_configurationNode, m_obj);
            if (m_flid != 0)
            {
                m_fs = GetFeatureStructureFromOwner(m_obj, m_flid);
            }
            else
            {
                m_fs   = m_obj as IFsFeatStruc;
                m_flid = FsFeatStrucTags.kflidFeatureSpecs;
            }

            ctrl.Initialize((FdoCache)Mediator.PropertyTable.GetValue("cache"),
                            m_fs,
                            m_flid,
                            "Name",
                            m_persistenceProvider,
                            Mediator,
                            "Name",
                            XmlUtils.GetOptionalAttributeValue(m_configurationNode, "ws", "analysis"));     // TODO: Get better default 'best ws'.
        }
Beispiel #17
0
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            //Debug.WriteLineIf(!disposing, "****************** " + GetType().Name + " 'disposing' is false. ******************");
            // Must not be run more than once.
            if (IsDisposed)
            {
                return;
            }

            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            m_cache       = null;
            m_fs          = null;
            m_mediator    = null;
            m_cache       = null;
            m_bvList      = null;
            m_valuesCombo = null;

            base.Dispose(disposing);
        }
Beispiel #18
0
        protected static IFsFeatStruc GetFeatureStructureFromMSA(ICmObject obj, int flid)
        {
            //IFsFeatStruc fs = obj.GetObjectInAtomicField(flid) as IFsFeatStruc;
            IFsFeatStruc fs = obj.Cache.GetAtomicPropObject(obj.Cache.DomainDataByFlid.get_ObjectProp(obj.Hvo, flid)) as IFsFeatStruc;

            return(fs);
        }
Beispiel #19
0
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            System.Diagnostics.Debug.WriteLineIf(!disposing, "****** Missing Dispose() call for " + GetType().Name + ". ****** ");
            // Must not be run more than once.
            if (IsDisposed)
            {
                return;
            }

            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }

                if (helpProvider != null)
                {
                    helpProvider.Dispose();
                }
            }
            m_cache      = null;
            m_fs         = null;
            m_highestPOS = null;
            m_poses      = null;
            m_mediator   = null;
            m_cache      = null;
            helpProvider = null;

            base.Dispose(disposing);
        }
        /// <summary>
        /// Init the dialog with an existing context.
        /// </summary>
        /// <param name="cache"></param>
        /// <param name="mediator"></param>
        /// <param name="rule"></param>
        /// <param name="ctxt"></param>
        public void SetDlgInfo(FdoCache cache, Mediator mediator, IPhRegularRule rule, IPhSimpleContextNC ctxt)
        {
            CheckDisposed();

            IFsFeatStruc fs = ((IPhNCFeatures)ctxt.FeatureStructureRA).FeaturesOA;

            SetDlgInfo(cache, mediator, ctxt.FeatureStructureRA.Hvo, PhNCFeaturesTags.kflidFeatures, fs, rule, ctxt);
        }
        public void Init(Mediator mediator, IFsFeatStruc fs)
        {
            CheckDisposed();

            m_fs       = fs;
            m_fdoCache = (FdoCache)mediator.PropertyTable.GetValue("cache");

            UpdateRootObject();
            m_fdoCache.DomainDataByFlid.AddNotification(this);
        }
Beispiel #22
0
        public void Init(LcmCache cache, IFsFeatStruc fs)
        {
            CheckDisposed();

            m_fs    = fs;
            m_cache = cache;

            UpdateRootObject();
            m_cache.DomainDataByFlid.AddNotification(this);
        }
        /// <summary>
        /// Init the dialog with an existing FS. Warning: the fs passed in
        /// might get deleted if it proves to be a duplicate. Retrieve the new FS after running it.
        /// This constructor is used in MsaInflectionFeatureListDlgLauncher.HandleChooser.
        /// </summary>
        /// <param name="cache"></param>
        /// <param name="mediator"></param>
        /// <param name="fs"></param>
        public void SetDlgInfo(FdoCache cache, Mediator mediator, IFsFeatStruc fs)
        {
            CheckDisposed();

            m_fs = fs;
            RestoreWindowPosition(mediator);
            m_cache = cache;
            LoadInflFeats(fs);
            EnableLink();
        }
Beispiel #24
0
        private void CreateFeatureStructureFromHvoString(XmlDocument doc, string sFSHvo, XmlNode parentNode)
        {
            int          fsHvo       = Convert.ToInt32(sFSHvo);
            IFsFeatStruc fsFeatStruc = (IFsFeatStruc)CmObject.CreateFromDBObject(m_cache, fsHvo);

            if (fsFeatStruc != null)
            {
                CreateFeatureStructureNodes(doc, parentNode, fsFeatStruc, fsHvo);
            }
        }
		public void Init(Mediator mediator, IFsFeatStruc fs)
		{
			CheckDisposed();

			m_fs = fs;
			m_fdoCache = (FdoCache)mediator.PropertyTable.GetValue("cache");

			UpdateRootObject();
			m_fdoCache.DomainDataByFlid.AddNotification(this);
		}
		public void Init(Mediator mediator, IFsFeatStruc fs)
		{
			CheckDisposed();

			m_fs = fs;
			m_fdoCache = (FdoCache)mediator.PropertyTable.GetValue("cache");

			UpdateRootObject();
			m_sda = m_fdoCache.MainCacheAccessor;
			m_sda.AddNotification(this);
		}
        /// <summary>
        /// If OK, then make FS have the selected feature value(s).
        /// JohnT: This is a really ugly kludge, which I have only partly repaired.
        /// We need the dialog to return with m_fs set to an FsFeatStruc (if OK was clicked),
        /// since that is what the bulk edit bar wants to copy to MoStemMsas for any items
        /// it is asked to modify. Also, the new FsFeatStruc needs to be in the ReferenceForms
        /// (which is what m_owningFlid apparently always is, currently) so that it will become
        /// one of the items in the combo list and can be selected. However, Andy says this is
        /// not the intended use of ReferenceForms at all.
        /// A further ugliness is that we always make a new FsFeatStruc (unless one was passed
        /// in to one of the SegDlgInfo methods, but AFAIK that override is never used), but
        /// we then delete it if it turns out to be a duplicate. There is no other straightforward
        /// way to detect that the current choices in the dialog correspond to an existing item.
        /// This may cause problems in the new world, where we can't do this "suppress sub tasks"
        /// trick without losing our Undo stack.
        /// It may be possible in the new world to create an object without initially giving it an
        /// owner, and only persist it if it is NOT a duplicate. But even that we don't really want
        /// to be undoable, nor should it clear the undo stack. Really the list of possible choices
        /// for the combo should not be separately persisted as model data, but it should be persisted
        /// somehow...
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MsaInflectionFeatureListDlg_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (DialogResult == DialogResult.OK)
            {
                using (new SuppressSubTasks(m_cache))                 // making and maybe then deleting the new item for the combo is not undoable
                {
                    if (m_fs == null)
                    {
                        // Didn't have one to begin with. See whether we want to create one.
                        if (CheckFeatureStructure(m_tvMsaFeatureList.Nodes))
                        {
                            // The last argument is meaningless since we expect this property to be owning
                            // or collection.
                            int hvoFs = m_cache.CreateObject(FsFeatStruc.kClassId, m_hvoOwner, m_owningFlid, 0);
                            m_fs = (IFsFeatStruc)FsFeatStruc.CreateFromDBObject(m_cache, hvoFs, false);
                        }
                        else
                        {
                            return;                             // leave it null.
                        }
                    }
                    // clean out any extant features in the feature structure
                    foreach (IFsFeatureSpecification spec in m_fs.FeatureSpecsOC)
                    {
                        m_fs.FeatureSpecsOC.Remove(spec);
                    }
                    UpdateFeatureStructure(m_tvMsaFeatureList.Nodes);
                    // The (usually) newly created one may be a duplicate. If we find a duplicate
                    // delete the one we just made (or were passed) and return the duplicate.
                    int chvo = m_cache.GetVectorSize(m_hvoOwner, m_owningFlid);
                    for (int ihvo = 0; ihvo < chvo; ihvo++)
                    {
                        int hvo = m_cache.GetVectorItem(m_hvoOwner, m_owningFlid, ihvo);
                        if (hvo == m_fs.Hvo)
                        {
                            continue;
                        }
                        IFsFeatStruc fs = CmObject.CreateFromDBObject(m_cache, hvo) as IFsFeatStruc;
                        if (FsFeatStruc.AreEquivalent(fs, m_fs))
                        {
                            m_fs.DeleteUnderlyingObject();
                            m_fs = fs;
                            break;
                        }
                    }
                }
            }

            if (m_mediator != null)
            {
                m_mediator.PropertyTable.SetProperty("msaInflFeatListDlgLocation", Location);
                m_mediator.PropertyTable.SetProperty("msaInflFeatListDlgSize", Size);
            }
        }
        public void Init(Mediator mediator, IFsFeatStruc fs)
        {
            CheckDisposed();

            m_fs       = fs;
            m_fdoCache = (FdoCache)mediator.PropertyTable.GetValue("cache");

            UpdateRootObject();
            m_sda = m_fdoCache.MainCacheAccessor;
            m_sda.AddNotification(this);
        }
Beispiel #29
0
        /// <summary>
        /// Init the dialog with an existing FS. Warning: the fs passed in
        /// might get deleted if it proves to be a duplicate. Retrieve the new FS after running it.
        /// This constructor is used in MsaInflectionFeatureListDlgLauncher.HandleChooser.
        /// </summary>
        /// <param name="cache"></param>
        /// <param name="mediator"></param>
        /// <param name="fs"></param>
        /// <param name="owningFlid"></param>
        public void SetDlgInfo(FdoCache cache, Mediator mediator, IFsFeatStruc fs, int owningFlid)
        {
            CheckDisposed();

            m_fs         = fs;
            Mediator     = mediator;
            m_cache      = cache;
            m_owningFlid = owningFlid;
            LoadInflFeats(fs);
            EnableLink();
        }
 private void MakeFeatureStructure(FeatureStructureTreeView tv, IFsFeatStruc featStruct)
 {
     using (MsaInflectionFeatureListDlg dlg = new MsaInflectionFeatureListDlg())
     {
         foreach (IFsFeatureSpecification spec in featStruct.FeatureSpecsOC)
         {
             featStruct.FeatureSpecsOC.Remove(spec);
         }
         dlg.SetDlgInfo(Cache, null, featStruct, MoStemMsaTags.kflidMsFeatures);
         dlg.UpdateFeatureStructure(tv.Nodes);
     }
 }
Beispiel #31
0
        /// <summary>
        /// Init the dialog with an existing FS. Warning: the fs passed in
        /// might get deleted if it proves to be a duplicate. Retrieve the new FS after running it.
        /// This constructor is used in MsaInflectionFeatureListDlgLauncher.HandleChooser.
        /// </summary>
        /// <param name="cache"></param>
        /// <param name="mediator"></param>
        /// <param name="propertyTable"></param>
        /// <param name="fs"></param>
        /// <param name="owningFlid"></param>
        public void SetDlgInfo(LcmCache cache, Mediator mediator, XCore.PropertyTable propertyTable, IFsFeatStruc fs, int owningFlid)
        {
            CheckDisposed();

            m_fs            = fs;
            m_propertyTable = propertyTable;
            Mediator        = mediator;
            m_cache         = cache;
            m_owningFlid    = owningFlid;
            LoadInflFeats(fs);
            EnableLink();
        }
Beispiel #32
0
        public void SetDlgInfo(FdoCache cache, XCore.Mediator mediator)
        {
            CheckDisposed();

            m_fs = null;
            RestoreWindowPosition(mediator);
            m_cache = cache;
            m_valuesCombo.WritingSystemFactory = m_cache.LanguageWritingSystemFactoryAccessor;
            m_valuesCombo.StyleSheet           = FontHeightAdjuster.StyleSheetFromMediator(mediator);
            LoadPhonFeats(null);
            BuildInitialBrowseView(mediator);
        }
Beispiel #33
0
 /// <summary>
 /// Answer true if the selected MSA has an MsFeatures that is the same as the argument.
 /// </summary>
 /// <returns></returns>
 private bool MsaMatchesTarget(IMoStemMsa msm, IFsFeatStruc fsTarget)
 {
     if (m_selectedHvo == 0 && msm.MsFeaturesOA == null)
     {
         return(true);
     }
     if (msm.MsFeaturesOA == null)
     {
         return(false);
     }
     return(msm.MsFeaturesOA.IsEquivalent(fsTarget));
 }
		public void Init(Mediator mediator, IFsFeatStruc fs)
		{
			CheckDisposed();

			m_fs = fs;
			m_fdoCache = (FdoCache)mediator.PropertyTable.GetValue("cache");

			if (m_rootb == null)
			{
				MakeRoot();
			}
			else
			{
				m_rootb.SetRootObject(m_fs == null ? 0 : m_fs.Hvo, m_vc, (int)VcFrags.kfragName, m_rootb.Stylesheet);
				m_rootb.Reconstruct();
			}
		}
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose(bool disposing)
		{
			// Must not be run more than once.
			if (IsDisposed)
				return;

			base.Dispose(disposing);

			if (disposing)
			{
				if (components != null)
				{
					components.Dispose();
				}
			}
			m_vc = null;
			m_fs = null;
		}
		private ILangProject CreateFeatureSystem(out IFsFeatStruc featStruct)
		{
			featStruct = null;
			ILangProject lp = Cache.LanguageProject;

			// Set up the xml fs description
			XmlDocument doc = new XmlDocument();
			string sFileDir = Path.Combine(SIL.FieldWorks.Common.FwUtils.FwDirectoryFinder.SourceDirectory,
				Path.Combine(@"FDO", Path.Combine(@"FDOTests", @"TestData")));
			string sFile = Path.Combine(sFileDir, "FeatureSystem2.xml");

			doc.Load(sFile);
			XmlNode itemNeut = doc.SelectSingleNode("//item[@id='vNeut']");

			// Add the feature for first time
			IFsFeatureSystem msfs = lp.MsFeatureSystemOA;
			msfs.AddFeatureFromXml(itemNeut);
			// Now add a feature that differs only in value
			XmlNode itemFem = doc.SelectSingleNode("//item[@id='vFem']");
			msfs.AddFeatureFromXml(itemFem);

			// now add to feature structure
			IPartOfSpeech pos = lp.PartsOfSpeechOA.PossibilitiesOS[0] as IPartOfSpeech;

			pos.DefaultFeaturesOA = Cache.ServiceLocator.GetInstance<IFsFeatStrucFactory>().Create();
			featStruct = pos.DefaultFeaturesOA;

			// Add the first feature
			featStruct.AddFeatureFromXml(itemNeut, msfs);
			// Now add a feature that differs only in value; it should override the old one
			featStruct.AddFeatureFromXml(itemFem, msfs);
			// Now add another feature
			XmlNode item1st = doc.SelectSingleNode("//item[@id='v1']");
			featStruct.AddFeatureFromXml(item1st, msfs);
			// Update inflectable features on pos
			XmlNode subjAgr = doc.SelectSingleNode("//item[@id='cSubjAgr']");
			pos.AddInflectableFeatsFromXml(subjAgr);
			pos.AddInflectableFeatsFromXml(itemNeut);

			return lp;
		}
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose(bool disposing)
		{
			//Debug.WriteLineIf(!disposing, "****************** " + GetType().Name + " 'disposing' is false. ******************");
			// Must not be run more than once.
			if (IsDisposed)
				return;

			base.Dispose(disposing);

			if (disposing)
			{
				if (components != null)
				{
					components.Dispose();
				}
				if (m_vc != null)
					m_vc.Dispose();
			}
			m_vc = null;
			m_fs = null;
		}
		private ILangProject CreateFeatureSystem(out IFsFeatStruc featStruct)
		{
			featStruct = null;
			ILangProject lp = Cache.LangProject;

			// Set up the xml fs description
			XmlDocument doc = new XmlDocument();
			string sFileDir = Path.Combine(SIL.FieldWorks.Common.Utils.DirectoryFinder.FwSourceDirectory, @"FDO\FDOTests\TestData");
			string sFile = Path.Combine(sFileDir, "FeatureSystem2.xml");

			doc.Load(sFile);
			XmlNode itemNeut = doc.SelectSingleNode("//item[@id='vNeut']");

			// Add the feature for first time
			FsFeatureSystem.AddFeatureAsXml(Cache, itemNeut);
			IFsFeatureSystem msfs = lp.MsFeatureSystemOA;
			// Now add a feature that differs only in value
			XmlNode itemFem = doc.SelectSingleNode("//item[@id='vFem']");
			FsFeatureSystem.AddFeatureAsXml(Cache, itemFem);

			// now add to feature structure
			IPartOfSpeech pos = (IPartOfSpeech)lp.PartsOfSpeechOA.PossibilitiesOS.FirstItem;

			pos.DefaultFeaturesOA = new FsFeatStruc();
			featStruct = pos.DefaultFeaturesOA;

			// Add the first feature
			featStruct.AddFeatureFromXml(Cache, itemNeut);
			// Now add a feature that differs only in value; it should override the old one
			featStruct.AddFeatureFromXml(Cache, itemFem);
			// Now add another feature
			XmlNode item1st = doc.SelectSingleNode("//item[@id='v1']");
			featStruct.AddFeatureFromXml(Cache, item1st);
			// Update inflectable features on pos
			XmlNode subjAgr = doc.SelectSingleNode("//item[@id='cSubjAgr']");
			pos.AddInflectableFeatsFromXml(Cache, subjAgr);
			pos.AddInflectableFeatsFromXml(Cache, itemNeut);

			return lp;
		}
		private static void WriteFeatureStructureNodes(XmlWriter writer, IFsFeatStruc fs, int id, string sFsName = "fs")
		{
			if (fs == null)
				return;
			writer.WriteStartElement(sFsName);
			writer.WriteAttributeString("id", id.ToString(CultureInfo.InvariantCulture));
			foreach (IFsFeatureSpecification spec in fs.FeatureSpecsOC)
			{
				writer.WriteStartElement("feature");
				writer.WriteElementString("name", spec.FeatureRA.Abbreviation.BestAnalysisAlternative.Text);
				writer.WriteStartElement("value");
				var cv = spec as IFsClosedValue;
				if (cv != null)
					writer.WriteString(cv.ValueRA.Abbreviation.BestAnalysisAlternative.Text);
				else
				{
					var complex = spec as IFsComplexValue;
					if (complex == null)
						continue; // skip this one since we're not dealing with it yet
					var nestedFs = complex.ValueOA as IFsFeatStruc;
					if (nestedFs != null)
						WriteFeatureStructureNodes(writer, nestedFs, 0);
				}
				writer.WriteEndElement(); //value
				writer.WriteEndElement(); //feature
			}
			writer.WriteEndElement(); //sFsName
		}
Beispiel #40
0
		private void CreateFeatStruc(IFsFeatureSystem featSys, IFsFeatStrucType type, IFsFeatStruc fs, FS featVals)
		{
			fs.TypeRA = type;
			foreach (KeyValuePair<string, object> featVal in featVals)
			{
				IFsFeatDefn fd = featSys.FeaturesOC.First(f => f.Abbreviation.AnalysisDefaultWritingSystem.Text == featVal.Key);

				var closedFeat = fd as IFsClosedFeature;
				if (closedFeat != null)
				{
					IFsSymFeatVal sym = closedFeat.ValuesOC.First(v => v.Abbreviation.AnalysisDefaultWritingSystem.Text == (string) featVal.Value);
					IFsClosedValue cv = Cache.ServiceLocator.GetInstance<IFsClosedValueFactory>().Create();
					fs.FeatureSpecsOC.Add(cv);
					cv.FeatureRA = fd;
					cv.ValueRA = sym;
				}
				else
				{
					var complexFeat = (IFsComplexFeature) fd;
					IFsComplexValue cv = Cache.ServiceLocator.GetInstance<IFsComplexValueFactory>().Create();
					fs.FeatureSpecsOC.Add(cv);

					IFsFeatStruc childFS = Cache.ServiceLocator.GetInstance<IFsFeatStrucFactory>().Create();
					cv.FeatureRA = fd;
					cv.ValueOA = childFS;
					CreateFeatStruc(featSys, complexFeat.TypeRA, childFS, (FS) featVal.Value);
				}
			}
		}
		/// <summary>
		/// Answer true if the selected MSA has an MsFeatures that is the same as the argument.
		/// </summary>
		/// <returns></returns>
		private bool MsaMatchesTarget(IMoStemMsa msm, IFsFeatStruc fsTarget)
		{
			if (m_selectedHvo == 0 && msm.MsFeaturesOAHvo == 0)
				return true;
			if (msm.MsFeaturesOAHvo == 0)
				return false;
			return msm.MsFeaturesOA.IsEquivalent(fsTarget);
		}
		/// <summary>
		/// Listen for change to basic IPA symbol
		/// If description and/or features are empty, try to supply the values associated with the symbol
		/// </summary>
		/// <param name="hvo"></param>
		/// <param name="tag"></param>
		/// <param name="ivMin"></param>
		/// <param name="cvIns"></param>
		/// <param name="cvDel"></param>
		public void PropChanged(int hvo, int tag, int ivMin, int cvIns, int cvDel)
		{
			if (hvo == 0)
				return;
			// We only want to do something when the basic IPA symbol changes
			if ((tag != PhPhonemeTags.kflidFeatures) && (tag != FsFeatStrucTags.kflidFeatureSpecs))
				return;
			if (tag == FsFeatStrucTags.kflidFeatureSpecs)
			{
				IFsFeatStruc featStruc = m_fdoCache.ServiceLocator.GetInstance<IFsFeatStrucRepository>().GetObject(hvo);
				// only want to do something when the feature structure is part of a IPhPhoneme))
				if (featStruc.OwningFlid != PhPhonemeTags.kflidFeatures)
					return;
			}
			if (tag == PhPhonemeTags.kflidFeatures && Phoneme != null && hvo == Phoneme.Hvo)
			{
				m_fs = Phoneme.FeaturesOA;
				if (m_fs != null && m_rootb != null)
					m_rootb.SetRootObject(m_fs.Hvo, m_vc, (int)VcFrags.kfragName, m_rootb.Stylesheet);
			}

			if (m_rootb != null)
				m_rootb.Reconstruct();
		}
		/// <summary>
		/// Init the dialog with an MSA and flid that does not yet contain a feature structure.
		/// </summary>
		/// <param name="cache"></param>
		/// <param name="mediator"></param>
		/// <param name="cobj"></param>
		/// <param name="owningFlid"></param>
		public void SetDlgInfo(FdoCache cache, Mediator mediator, ICmObject cobj, int owningFlid)
		{
			CheckDisposed();

			m_fs = null;
			m_owningFlid = owningFlid;
			m_hvoOwner = cobj.Hvo;
			Mediator = mediator;
			m_cache = cache;
			LoadInflFeats(cobj, owningFlid);
			EnableLink();
		}
		/// <summary>
		/// Load the tree items if the starting point is a feature structure.
		/// </summary>
		/// <param name="fs"></param>
		protected virtual void LoadInflFeats(IFsFeatStruc fs)
		{
			var cobj = fs.Owner;
			switch(cobj.ClassID)
			{
			case MoAffixAllomorphTags.kClassId:
				PopulateTreeFromPosInEntry(cobj);
				break;
			default:
				// load inflectable features of this POS and any inflectable features of its parent POS
				var pos = GetOwningPOSOfFS(fs, cobj);
				PopulateTreeFromPos(pos);
				break;
			}
			m_tvMsaFeatureList.PopulateTreeFromFeatureStructure(fs);
			FinishLoading();
		}
		/// <summary>
		/// If OK, then make FS have the selected feature value(s).
		/// JohnT: This is a really ugly kludge, which I have only partly repaired.
		/// We need the dialog to return with m_fs set to an FsFeatStruc (if OK was clicked),
		/// since that is what the bulk edit bar wants to copy to MoStemMsas for any items
		/// it is asked to modify. Also, the new FsFeatStruc needs to be in the ReferenceForms
		/// (which is what m_owningFlid apparently always is, currently) so that it will become
		/// one of the items in the combo list and can be selected. However, Andy says this is
		/// not the intended use of ReferenceForms at all.
		/// A further ugliness is that we always make a new FsFeatStruc (unless one was passed
		/// in to one of the SegDlgInfo methods, but AFAIK that override is never used), but
		/// we then delete it if it turns out to be a duplicate. There is no other straightforward
		/// way to detect that the current choices in the dialog correspond to an existing item.
		/// This may cause problems in the new world, where we can't do this "suppress sub tasks"
		/// trick without losing our Undo stack.
		/// It may be possible in the new world to create an object without initially giving it an
		/// owner, and only persist it if it is NOT a duplicate. But even that we don't really want
		/// to be undoable, nor should it clear the undo stack. Really the list of possible choices
		/// for the combo should not be separately persisted as model data, but it should be persisted
		/// somehow...
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void MsaInflectionFeatureListDlg_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			if (DialogResult == DialogResult.OK)
			{
				// making and maybe then deleting the new item for the combo is not undoable
				NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor,
					() =>
						{
							if (m_fs == null)
							{
								// Didn't have one to begin with. See whether we want to create one.
								if (CheckFeatureStructure(m_tvMsaFeatureList.Nodes))
								{
									var repo = m_cache.ServiceLocator.GetInstance<IFsFeatStrucRepository>();
									// FsFeatStruc may be owned atomically or in a colllection. See which fake insertion index we need.
									int where = m_cache.MetaDataCacheAccessor.GetFieldType(m_owningFlid) == (int) CellarPropertyType.OwningAtomic ? -2: -1;
									int hvoNew = m_cache.DomainDataByFlid.MakeNewObject(FsFeatStrucTags.kClassId, m_hvoOwner,
										m_owningFlid, where);
									m_fs = repo.GetObject(hvoNew);
								}
								else
								{
									return; // leave it null.
								}
							}
							// clean out any extant features in the feature structure
							foreach (var spec in m_fs.FeatureSpecsOC)
								m_fs.FeatureSpecsOC.Remove(spec);
							UpdateFeatureStructure(m_tvMsaFeatureList.Nodes);
							// The (usually) newly created one may be a duplicate. If we find a duplicate
							// delete the one we just made (or were passed) and return the duplicate.
							int cpt = m_cache.MetaDataCacheAccessor.GetFieldType(m_owningFlid);
							if (m_hvoOwner != 0 && cpt != (int) CellarPropertyType.OwningAtomic)
							{
								int chvo = m_cache.DomainDataByFlid.get_VecSize(m_hvoOwner, m_owningFlid);
								for (int ihvo = 0; ihvo < chvo; ihvo++)
								{
									int hvo = m_cache.DomainDataByFlid.get_VecItem(m_hvoOwner, m_owningFlid, ihvo);
									if (hvo == m_fs.Hvo)
										continue;
									IFsFeatStruc fs = m_cache.ServiceLocator.GetInstance<IFsFeatStrucRepository>().GetObject(hvo);
									if (DomainObjectServices.AreEquivalent(fs, m_fs))
									{
										m_cache.DomainDataByFlid.DeleteObj(m_fs.Hvo);
										m_fs = fs;
										break;
									}
								}
							}
							// If the user emptied all the FeatureSpecs (i.e. chose "None of the above" in each area),
							// then we need to delete the FsFeatStruc. (LT-13596)
							if (FS.FeatureSpecsOC.Count == 0)
							{
								if (m_fs.CanDelete)
									m_fs.Delete();
								m_fs = null;
							}
						});
			}

			if (m_mediator != null)
			{
				m_mediator.PropertyTable.SetProperty("msaInflFeatListDlgLocation", Location);
				m_mediator.PropertyTable.SetProperty("msaInflFeatListDlgSize", Size);
			}
		}
		/// <summary>
		/// Init the dialog with an existing FS. Warning: the fs passed in
		/// might get deleted if it proves to be a duplicate. Retrieve the new FS after running it.
		/// This constructor is used in MsaInflectionFeatureListDlgLauncher.HandleChooser.
		/// </summary>
		/// <param name="cache"></param>
		/// <param name="mediator"></param>
		/// <param name="fs"></param>
		/// <param name="owningFlid"></param>
		public void SetDlgInfo(FdoCache cache, Mediator mediator, IFsFeatStruc fs, int owningFlid)
		{
			CheckDisposed();

			m_fs = fs;
			Mediator = mediator;
			m_cache = cache;
			m_owningFlid = owningFlid;
			LoadInflFeats(fs);
			EnableLink();
		}
		/// <summary>
		/// Set your MsFeatures to a copy of the source object.
		/// </summary>
		public void CopyMsFeatures(IFsFeatStruc source)
		{
			CopyObject<IFsFeatStruc>.CloneFdoObject(source, newFeat => MsFeaturesOA = newFeat);
		}
		public void PopulateTreeFromFeatureStructure(IFsFeatStruc fs)
		{
			CheckDisposed();

			AddNode(fs, null);
		}
		private void AddNode(IFsFeatStruc fs, FeatureTreeNode parentNode)
		{
			foreach (var spec in fs.FeatureSpecsOC)
			{
				AddNode(spec, parentNode);
			}
		}
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose(bool disposing)
		{
			System.Diagnostics.Debug.WriteLineIf(!disposing, "****** Missing Dispose() call for " + GetType().Name + ". ****** ");
			// Must not be run more than once.
			if (IsDisposed)
				return;

			if (disposing)
			{
				if (components != null)
				{
					components.Dispose();
				}

				if (helpProvider != null)
					helpProvider.Dispose();
			}
			m_cache = null;
			m_fs = null;
			m_highestPOS = null;
			m_poses = null;
			m_mediator = null;
			m_cache = null;
			helpProvider = null;

			base.Dispose(disposing);
		}
		/// <summary>
		/// Load the tree items if the starting point is a feature structure.
		/// </summary>
		/// <param name="fs"></param>
		protected override void LoadInflFeats(IFsFeatStruc fs)
		{
			PopulateTreeFromFeatureSystem();
			m_tvMsaFeatureList.PopulateTreeFromFeatureStructure(fs);
			FinishLoading();
		}
		/// <summary>
		///
		/// </summary>
		/// <param name="parent"></param>
		public override void Install(DataTree parent)
		{
			CheckDisposed();

			base.Install(parent);

			MsaInflectionFeatureListDlgLauncher ctrl = (MsaInflectionFeatureListDlgLauncher)Control;

			m_flid = MsaInflectionFeatureListDlgLauncherSlice.GetFlid(m_configurationNode, m_obj);
			if (m_flid != 0)
				m_fs = MsaInflectionFeatureListDlgLauncherSlice.GetFeatureStructureFromMSA(m_obj, m_flid);
			else
			{
				m_fs = m_obj as FsFeatStruc;
				m_flid = (int)FsFeatStruc.FsFeatStrucTags.kflidFeatureSpecs;
			}

			ctrl.Initialize((FdoCache)Mediator.PropertyTable.GetValue("cache"),
				m_fs,
				m_flid,
				"Name",
				ContainingDataTree.PersistenceProvder,
				Mediator,
				"Name",
				XmlUtils.GetOptionalAttributeValue(m_configurationNode, "ws", "analysis")); // TODO: Get better default 'best ws'.
		}
		private IPartOfSpeech GetOwningPOSOfFS(IFsFeatStruc fs, ICmObject cobj)
		{
			return GetPosFromCmObjectAndFlid(cobj, fs.OwningFlid);
		}
		private FeatureStructureTreeView SetUpSampleData(out IFsFeatStruc featStruct)
		{
			ILangProject lp = CreateFeatureSystem(out featStruct);
			// load some feature system values into treeview
			IPartOfSpeech pos = (IPartOfSpeech)lp.PartsOfSpeechOA.PossibilitiesOS.FirstItem;
			FeatureStructureTreeView tv = new FeatureStructureTreeView();
			tv.PopulateTreeFromInflectableFeats(pos.InflectableFeatsRC);
			Assert.AreEqual(1, tv.Nodes.Count, "Count of top level nodes in tree view");
			TreeNodeCollection col = tv.Nodes[0].Nodes;
			Assert.AreEqual(1, col.Count, "Count of first level nodes in tree view");
			foreach (TreeNode node in col)
			{
				TreeNodeCollection col2 = node.Nodes;
				Assert.AreEqual(2, col2.Count, "Count of second level nodes in tree view");
				if (node.PrevNode == null)
					node.Checked = true;
			}
			return tv;
		}
		private void LoadFeatureValuesIntoTreeview(FeatureStructureTreeView tv, IFsFeatStruc featStruct)
		{
			TreeNodeCollection col;
			tv.PopulateTreeFromFeatureStructure(featStruct);
			Assert.AreEqual(1, tv.Nodes.Count, "Count of top level after feature structure");
			col = tv.Nodes[0].Nodes;
			Assert.AreEqual(2, col.Count, "Count of first level nodes in tree view");
			foreach (TreeNode node in col)
			{
				TreeNodeCollection col2 = node.Nodes;
				if (node.Text == "gender")
					Assert.AreEqual(2, col2.Count, "Count of second level nodes in tree view");
				if (node.Text == "person")
					Assert.AreEqual(1, col2.Count, "Count of second level nodes in tree view");
			}
		}
		private void MakeFeatureStructure(FeatureStructureTreeView tv, IFsFeatStruc featStruct)
		{
			using (MsaInflectionFeatureListDlg dlg = new MsaInflectionFeatureListDlg())
			{
				foreach (IFsFeatureSpecification spec in featStruct.FeatureSpecsOC)
					featStruct.FeatureSpecsOC.Remove(spec);
				dlg.SetDlgInfo(Cache, null, featStruct);
				dlg.UpdateFeatureStructure(tv.Nodes);
			}
		}
		public void UpdateFS(IFsFeatStruc fs)
		{
			m_fs = fs;
			UpdateRootObject();
		}
		/// <summary>
		/// Listen for change to basic IPA symbol
		/// If description and/or features are empty, try to supply the values associated with the symbol
		/// </summary>
		/// <param name="hvo"></param>
		/// <param name="tag"></param>
		/// <param name="ivMin"></param>
		/// <param name="cvIns"></param>
		/// <param name="cvDel"></param>
		public void PropChanged(int hvo, int tag, int ivMin, int cvIns, int cvDel)
		{
			if (hvo == 0)
				return;
			// We only want to do something when the basic IPA symbol changes
			if ((tag != (int)PhPhoneme.PhPhonemeTags.kflidFeatures) && (tag != (int)FsFeatStruc.FsFeatStrucTags.kflidFeatureSpecs))
				return;
			if (tag == (int)FsFeatStruc.FsFeatStrucTags.kflidFeatureSpecs)
			{
				// only want to do something when the feature structure is part of a PhPhoneme
				if (Cache.GetOwningFlidOfObject(hvo) != (int)PhPhoneme.PhPhonemeTags.kflidFeatures)
					return;
			}
			if (tag == (int)PhPhoneme.PhPhonemeTags.kflidFeatures && Phoneme != null && hvo == Phoneme.Hvo)
			{
				m_fs = Phoneme.FeaturesOA;
				m_rootb.SetRootObject(Phoneme.FeaturesOAHvo, m_vc, (int)VcFrags.kfragName, m_rootb.Stylesheet);
			}

			if (m_rootb != null)
				m_rootb.Reconstruct();
		}
		/// <summary>
		/// Recursively builds the feature structure based on contents of treeview node path.
		/// It recurses back up the treeview node path to the top and then builds the feature structure
		/// as it goes back down.
		/// </summary>
		/// <param name="node"></param>
		/// <param name="fs"></param>
		/// <param name="val"></param>
		/// <returns></returns>
		private void BuildFeatureStructure(FeatureTreeNode node, ref IFsFeatStruc fs, ref IFsFeatureSpecification val)
		{
			if (node.Parent != null)
				BuildFeatureStructure((FeatureTreeNode)node.Parent, ref fs, ref val);
			switch (node.Kind)
			{
				case FeatureTreeNodeInfo.NodeKind.Complex:
					var complexFeat = m_cache.ServiceLocator.GetInstance<IFsComplexFeatureRepository>().GetObject(node.Hvo);
					var complex = fs.GetOrCreateValue(complexFeat);
					val = complex;
					val.FeatureRA = complexFeat;
					if (fs.TypeRA == null)
						fs.TypeRA = m_cache.LanguageProject.MsFeatureSystemOA.TypesOC.SingleOrDefault(type => type.FeaturesRS.Contains(complexFeat));
					fs = (IFsFeatStruc)complex.ValueOA;
					if (fs.TypeRA == null)
					{
						// this is the type of what's being embedded in the fs
						var cf = val.FeatureRA as IFsComplexFeature;
						if (cf != null)
						{
							fs.TypeRA = cf.TypeRA;
						}
					}
					break;
				case FeatureTreeNodeInfo.NodeKind.Closed:
					var closedFeat = m_cache.ServiceLocator.GetInstance<IFsClosedFeatureRepository>().GetObject(node.Hvo);
					val = fs.GetOrCreateValue(closedFeat);
					val.FeatureRA = closedFeat;
					if (fs.TypeRA == null)
					{
						// SingleOrDefault() gave an exception if 2 complex features used the same feature (LT-12780)
						fs.TypeRA = m_cache.LanguageProject.MsFeatureSystemOA.TypesOC.FirstOrDefault(type => type.FeaturesRS.Contains(closedFeat));
					}
					break;
				case FeatureTreeNodeInfo.NodeKind.SymFeatValue:
					var closed = val as IFsClosedValue;
					if (closed != null)
						closed.ValueRA = m_cache.ServiceLocator.GetInstance<IFsSymFeatValRepository>().GetObject(node.Hvo);
					break;
			}
		}
		/// <summary>
		/// Removes all invalid feature specifications from the given feature
		/// structure.
		/// </summary>
		/// <param name="pos">the category to check for validity</param>
		/// <param name="fs">the field structure</param>
		protected void RemoveInvalidFeatureSpecs(IPartOfSpeech pos, IFsFeatStruc fs)
		{
			if (fs == null || pos == null)
				return;

			foreach (var spec in fs.FeatureSpecsOC)
			{
				if (!IsFeatureValid(pos, spec.FeatureRA))
				{
					fs.FeatureSpecsOC.Remove(spec);
				}
			}
		}