/// <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; }
/// <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); } }
/// <summary> /// Execute the change requested by the current selection in the combo. /// Basically we want a copy of the FsFeatStruc indicated by m_selectedHvo, (even if 0?? not yet possible), /// to become the MsFeatures of each record that is appropriate to change. /// We do nothing to records where the check box is turned off, /// and nothing to ones that currently have an MSA other than an MoStemMsa, /// and nothing to ones that currently have an MSA with the wrong POS. /// (a) If the owning entry has an MoStemMsa with a matching MsFeatures (and presumably POS), /// set the sense to use it. /// (b) If all senses using the current MoStemMsa are to be changed, just update /// the MsFeatures of that MoStemMsa. /// We could add this...but very probably unused MSAs would have been taken over /// when setting the POS. /// --(c) If the entry has an MoStemMsa which is not being used at all, change it to /// --the required POS and inflection class and use it. /// (d) Make a new MoStemMsa in the LexEntry with the required POS and features /// and point the sense at it. /// </summary> public void DoIt(Set <int> itemsToChange, ProgressState state) { CheckDisposed(); int hvoPos = GetPOS(); // Make a Set of eligible parts of speech to use in filtering. Set <int> possiblePOS = GetPossiblePartsOfSpeech(); // Make a Dictionary from HVO of entry to list of modified senses. Dictionary <int, Set <ILexSense> > sensesByEntry = new Dictionary <int, Set <ILexSense> >(); int tagOwningEntry = m_cache.VwCacheDaAccessor.GetVirtualHandlerName("LexSense", "OwningEntry").Tag; int i = 0; // Report progress 50 times or every 100 items, whichever is more (but no more than once per item!) int interval = Math.Min(100, Math.Max(itemsToChange.Count / 50, 1)); foreach (int hvoSense in itemsToChange) { i++; if (i % interval == 0) { state.PercentDone = i * 20 / itemsToChange.Count; state.Breath(); } if (!IsItemEligible(m_cache.MainCacheAccessor, hvoSense, possiblePOS)) { continue; } ILexSense ls = (ILexSense)CmObject.CreateFromDBObject(m_cache, hvoSense, false); IMoMorphSynAnalysis msa = ls.MorphoSyntaxAnalysisRA; int hvoEntry = m_cache.MainCacheAccessor.get_ObjectProp(ls.Hvo, tagOwningEntry); if (!sensesByEntry.ContainsKey(hvoEntry)) { sensesByEntry[hvoEntry] = new Set <ILexSense>(); } sensesByEntry[hvoEntry].Add(ls); } //REVIEW: Should these really be the same Undo/Redo strings as for InflectionClassEditor.cs? m_cache.BeginUndoTask(FdoUiStrings.ksUndoBEInflClass, FdoUiStrings.ksRedoBEInflClass); BulkEditBar.ForceRefreshOnUndoRedo(Cache.MainCacheAccessor); i = 0; interval = Math.Min(100, Math.Max(sensesByEntry.Count / 50, 1)); IFsFeatStruc fsTarget = null; if (m_selectedHvo != 0) { fsTarget = FsFeatStruc.CreateFromDBObject(Cache, m_selectedHvo); } foreach (KeyValuePair <int, Set <ILexSense> > kvp in sensesByEntry) { i++; if (i % interval == 0) { state.PercentDone = i * 80 / sensesByEntry.Count + 20; state.Breath(); } ILexEntry entry = (ILexEntry)CmObject.CreateFromDBObject(m_cache, kvp.Key, false); Set <ILexSense> sensesToChange = kvp.Value; IMoStemMsa msmTarget = null; foreach (IMoMorphSynAnalysis msa in entry.MorphoSyntaxAnalysesOC) { IMoStemMsa msm = msa as IMoStemMsa; if (msm != null && MsaMatchesTarget(msm, fsTarget)) { // Can reuse this one! msmTarget = msm; break; } } if (msmTarget == null) { // See if we can reuse an existing MoStemMsa by changing it. // This is possible if it is used only by senses in the list, or not used at all. Set <ILexSense> otherSenses = new Set <ILexSense>(); Set <ILexSense> senses = new Set <ILexSense>(entry.AllSenses.ToArray()); if (senses.Count != sensesToChange.Count) { foreach (ILexSense ls in senses) { if (!sensesToChange.Contains(ls)) { otherSenses.Add(ls); } } } foreach (IMoMorphSynAnalysis msa in entry.MorphoSyntaxAnalysesOC) { IMoStemMsa msm = msa as IMoStemMsa; if (msm == null) { continue; } bool fOk = true; foreach (ILexSense ls in otherSenses) { if (ls.MorphoSyntaxAnalysisRA == msm) { fOk = false; break; } } if (fOk) { // Can reuse this one! Nothing we don't want to change uses it. // Adjust its POS as well as its inflection feature, just to be sure. // Ensure that we don't change the POS! See LT-6835. msmTarget = msm; InitMsa(msmTarget, msm.PartOfSpeechRAHvo); break; } } } if (msmTarget == null) { // Nothing we can reuse...make a new one. msmTarget = new MoStemMsa(); entry.MorphoSyntaxAnalysesOC.Add(msmTarget); InitMsa(msmTarget, hvoPos); } // Finally! Make the senses we want to change use it. foreach (ILexSense ls in sensesToChange) { ls.MorphoSyntaxAnalysisRA = msmTarget; } } m_cache.EndUndoTask(); }