/// ------------------------------------------------------------------------------------ /// <summary> /// Print method /// </summary> /// ------------------------------------------------------------------------------------ public override void Print(PrintDocument pd) { CheckDisposed(); ISilDataAccess oldSda = null; bool fPrintSelection = (pd.PrinterSettings.PrintRange == PrintRange.Selection); if (fPrintSelection) { oldSda = RootBox.DataAccess; IVwSelection sel = RootBox.Selection; int clev = sel.CLevels(true); int hvoObj, tag, ihvoEnd, ihvoAnchor, cpropPrevious; IVwPropertyStore vps; sel.PropInfo(true, clev - 1, out hvoObj, out tag, out ihvoEnd, out cpropPrevious, out vps); clev = sel.CLevels(false); sel.PropInfo(false, clev - 1, out hvoObj, out tag, out ihvoAnchor, out cpropPrevious, out vps); int[] originalObjects = m_sdaSource.VecProp(m_hvoRoot, m_mainFlid); int ihvoMin = Math.Min(ihvoEnd, ihvoAnchor); int ihvoLim = Math.Max(ihvoEnd, ihvoAnchor) + 1; var selectedObjects = new int[ihvoLim - ihvoMin]; for (int i = 0; i < selectedObjects.Length; i++) { selectedObjects[i] = originalObjects[i + ihvoMin]; } RootBox.DataAccess = CachePrintDecorator(m_sdaSource, m_hvoRoot, m_mainFlid, selectedObjects); } base.Print(pd); if (fPrintSelection) { RootBox.DataAccess = oldSda; } }
/// <summary> /// Make one. /// </summary> public PromptSelectionRestorer(IVwRootBox rootbox) { m_rootbox = rootbox; if (rootbox == null) { return; } // Save information about the old selection. IVwSelection oldsel = rootbox.Selection; // Dummy variables int tagTextProp; int ichAnchor; int ichEnd; int ihvoEnd; bool fAssocPrev; if (oldsel != null && oldsel.CLevels(false) > 0) { cvsli = oldsel.CLevels(false); cvsli--; // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. rgvsli = SelLevInfo.AllTextSelInfo(oldsel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttp); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Do remaining initialization once we (might) have a selection. /// </summary> /// ------------------------------------------------------------------------------------ void Init() { if (m_sel == null) { return; } if (m_sel.SelType == VwSelType.kstPicture) { // TextSelInfo doesn't work; but we can get a good approximation of much of the // information like this. // Out variables for AllTextSelInfo. int ihvoRoot; int tagTextProp; int cpropPrevious; int ichAnchor; int ichEnd; int ws; bool fAssocPrev; int ihvoEnd; ITsTextProps ttpBogus; // Main array of information retrieved from sel that made combo. SelLevInfo[] rgvsli; // Analysis can now be zero (e.g., displaying alternate case form for non-existent WfiWordform) // and I don't believe it's a problem for the code below (JohnT). // if (sandbox.Analysis == 0) // { // // We aren't fully initialized yet, so don't do anything. // return null; // } try { int cvsli = m_sel.CLevels(false) - 1; rgvsli = SelLevInfo.AllTextSelInfo(m_sel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); } catch (Exception) { // If anything goes wrong just give up. return; } m_ichA = ichAnchor; m_ichE = ichEnd; if (rgvsli.Length > 0) { m_hvoObjA = m_hvoObjE = rgvsli[0].hvo; } m_tagA = m_tagE = tagTextProp; } else { m_sel.TextSelInfo(true, out m_tssE, out m_ichE, out m_fAssocPrev, out m_hvoObjE, out m_tagE, out m_wsE); m_sel.TextSelInfo(false, out m_tssA, out m_ichA, out m_fAssocPrev, out m_hvoObjA, out m_tagA, out m_wsA); } m_fIsRange = m_sel.IsRange; m_selType = m_sel.SelType; }
/// ----------------------------------------------------------------------------------- /// <summary> /// Notifies the site that something about the selection has changed. /// </summary> /// <param name="prootb"></param> /// <param name="vwselNew">Selection</param> /// <remarks>When overriding you should call the base class first.</remarks> /// ----------------------------------------------------------------------------------- public override void SelectionChanged(IVwRootBox prootb, IVwSelection vwselNew) { CheckDisposed(); base.SelectionChanged(prootb, vwselNew); if (vwselNew == null) { return; } int clev = vwselNew.CLevels(false); // anchor int hvoRoot, tag, ihvo, cpropPrevious; IVwPropertyStore vps; vwselNew.PropInfo(false, clev - 1, out hvoRoot, out tag, out ihvo, out cpropPrevious, out vps); Debug.Assert(hvoRoot == m_hvoRoot); int hvoObjNewSel = m_fdoCache.MainCacheAccessor.get_VecItem(hvoRoot, tag, ihvo); if (hvoObjNewSel != 0) { // Notify any delegates that the selection of the main object in the vector // may have changed. if (SelectionChangedEvent != null) { SelectionChangedEvent(this, new FwObjectSelectionEventArgs(hvoObjNewSel, ihvo)); } } }
public void OnFwRightMouseClick(SimpleRootSite sender, FwRightMouseClickEventArgs e) { CheckDisposed(); XmlBrowseView browseView = sender as XmlBrowseView; if (browseView != null) { IVwSelection sel = e.Selection; int clev = sel.CLevels(false); // anchor int hvoRoot, tag, ihvo, cpropPrevious; IVwPropertyStore vps; sel.PropInfo(false, clev - 1, out hvoRoot, out tag, out ihvo, out cpropPrevious, out vps); // First make the selection so it will be highlighted before the context menu popup. if (browseView.SelectedIndex != ihvo) // No sense in waking up the beast for no reason. { browseView.SelectedIndex = ihvo; } int hvo = browseView.HvoAt(ihvo); CmObjectUi ui = CmObjectUi.MakeUi(Cache, hvo); if (ui != null) { e.EventHandled = ui.HandleRightClick(m_mediator, sender, true, "mnuBrowseView"); } } }
void VerifySelection(SandboxBase sandbox, bool fPicture, int tagText, int tagObj, int morphIndex) { Assert.That(sandbox.RootBox.Selection, Is.Not.Null); Assert.That(sandbox.MorphIndex, Is.EqualTo(morphIndex)); int ihvoRoot; int tagTextProp; int cpropPrevious; int ichAnchor; int ichEnd; int ws; bool fAssocPrev; int ihvoEnd; ITsTextProps ttpBogus; // Main array of information retrived from sel that made combo. SelLevInfo[] rgvsli; bool fIsPictureSel; // icon selected. IVwSelection sel = sandbox.RootBox.Selection; fIsPictureSel = sel.SelType == VwSelType.kstPicture; int cvsli = sel.CLevels(false) - 1; rgvsli = SelLevInfo.AllTextSelInfo(sel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); Assert.That(fIsPictureSel, Is.EqualTo(fPicture)); Assert.That(tagTextProp, Is.EqualTo(tagText)); if (tagTextProp == SandboxBase.ktagSbNamedObjName) { int tagObjProp = rgvsli[0].tag; Assert.That(tagObjProp, Is.EqualTo(tagObj)); } //sandbox.InterlinLineChoices. }
public void OnFwRightMouseClick(SimpleRootSite sender, FwRightMouseClickEventArgs e) { CheckDisposed(); var browseView = sender as XmlBrowseView; if (browseView != null) { IVwSelection sel = e.Selection; int clev = sel.CLevels(false); // anchor int hvoRoot, tag, ihvo, cpropPrevious; IVwPropertyStore vps; sel.PropInfo(false, clev - 1, out hvoRoot, out tag, out ihvo, out cpropPrevious, out vps); // First make the selection so it will be highlighted before the context menu popup. if (browseView.SelectedIndex != ihvo) // No sense in waking up the beast for no reason. { browseView.SelectedIndex = ihvo; } int hvo = browseView.HvoAt(ihvo); if (Cache.ServiceLocator.IsValidObjectId(hvo)) // may be fake one from decorator. { CmObjectUi ui = CmObjectUi.MakeUi(Cache, hvo); // Disposes of itself when menu closes since true passed in lext line. if (ui != null) { ui.Mediator = m_mediator; ui.PropTable = m_propertyTable; e.EventHandled = ui.HandleRightClick(m_mediator, m_propertyTable, sender, true, "mnuBrowseView"); } } } }
/// <summary> /// Return annotation Hvo that contains the selection. /// </summary> /// <returns></returns> public int AnnotationContainingSelection() { Debug.Assert(m_rootb != null); if (m_rootb == null) { return(0); } IVwSelection sel = m_rootb.Selection; if (sel == null) { return(0); } // See if our selection contains a base annotation. int cvsli = sel.CLevels(false); cvsli--; // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. // Out variables for AllTextSelInfo. int ihvoRoot, tagTextProp, cpropPrevious, ichAnchor, ichEnd, ws, ihvoEnd; bool fAssocPrev; ITsTextProps ttpBogus; // Main array of information retrived from sel that made combo. SelLevInfo[] rgvsli = SelLevInfo.AllTextSelInfo(sel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); return(FindBaseAnnInSelLevInfo(rgvsli)); // returns 0 if unsuccessful }
protected bool CheckForValidDelete(IVwSelection sel, out int cvsli, out int hvoObj) { hvoObj = 0; if (sel == null) { cvsli = 0; // satisfy compiler. return(false); // nothing selected, give up. } cvsli = sel.CLevels(false); // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. cvsli--; if (cvsli == 0) { // No object in selection, so quit. return(false); } ITsString tss; int ichAnchor; bool fAssocPrev; int tag; int ws; int ichEnd; int hvoObjEnd; sel.TextSelInfo(false, out tss, out ichAnchor, out fAssocPrev, out hvoObj, out tag, out ws); sel.TextSelInfo(true, out tss, out ichEnd, out fAssocPrev, out hvoObjEnd, out tag, out ws); return(hvoObj == hvoObjEnd); }
/// ----------------------------------------------------------------------------------- /// <summary> /// Notifies the site that something about the selection has changed. /// </summary> /// <param name="prootb"></param> /// <param name="vwselNew">Selection</param> /// <remarks>When overriding you should call the base class first.</remarks> /// ----------------------------------------------------------------------------------- protected override void HandleSelectionChange(IVwRootBox prootb, IVwSelection vwselNew) { CheckDisposed(); base.HandleSelectionChange(prootb, vwselNew); if (vwselNew == null) { return; } int clev = vwselNew.CLevels(false); // anchor int clevEnd = vwselNew.CLevels(true); if (clev < 2 || clevEnd < 2) { return; // paranoia } int hvoRoot, tag, ihvo, ihvoEnd, cpropPrevious; IVwPropertyStore vps; vwselNew.PropInfo(true, clevEnd - 1, out hvoRoot, out tag, out ihvoEnd, out cpropPrevious, out vps); vwselNew.PropInfo(false, clev - 1, out hvoRoot, out tag, out ihvo, out cpropPrevious, out vps); // Give up if the selection doesn't indicate any top-level object; I think this can happen with pictures. // selection larger than a top-level object, maybe select all, side effects are confusing. if (ihvo != ihvoEnd || ihvo < 0) { return; } if (hvoRoot == 0) { return; } Debug.Assert(hvoRoot == m_hvoRoot); int hvoObjNewSel = m_sdaSource.get_VecItem(hvoRoot, tag, ihvo); if (hvoObjNewSel != 0) { // Notify any delegates that the selection of the main object in the vector // may have changed. if (SelectionChangedEvent != null) { SelectionChangedEvent(this, new FwObjectSelectionEventArgs(hvoObjNewSel, ihvo)); } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Print method /// </summary> /// ------------------------------------------------------------------------------------ public override void Print(PrintDocument pd) { CheckDisposed(); bool fPrintSelection = (pd.PrinterSettings.PrintRange == PrintRange.Selection); int[] originalObjects = null; if (fPrintSelection) { IVwSelection sel = RootBox.Selection; int clev = sel.CLevels(true); int hvoObj, tag, ihvoEnd, ihvoAnchor, cpropPrevious; IVwPropertyStore vps; sel.PropInfo(true, clev - 1, out hvoObj, out tag, out ihvoEnd, out cpropPrevious, out vps); clev = sel.CLevels(false); sel.PropInfo(false, clev - 1, out hvoObj, out tag, out ihvoAnchor, out cpropPrevious, out vps); ISilDataAccess sda = m_fdoCache.MainCacheAccessor; int chvoReal = sda.get_VecSize(m_hvoRoot, m_mainFlid); using (ArrayPtr arrayPtr = MarshalEx.ArrayToNative(chvoReal, typeof(int))) { sda.VecProp(m_hvoRoot, m_mainFlid, chvoReal, out chvoReal, arrayPtr); originalObjects = (int[])MarshalEx.NativeToArray(arrayPtr, chvoReal, typeof(int)); } int ihvoMin = Math.Min(ihvoEnd, ihvoAnchor); int ihvoLim = Math.Max(ihvoEnd, ihvoAnchor) + 1; int[] selectedObjects = new int[ihvoLim - ihvoMin]; for (int i = 0; i < selectedObjects.Length; i++) { selectedObjects[i] = originalObjects[i + ihvoMin]; } m_fdoCache.VwCacheDaAccessor.CacheVecProp(m_hvoRoot, m_mainFlid, selectedObjects, selectedObjects.Length); } try { base.Print(pd); } finally { if (fPrintSelection) { m_fdoCache.VwCacheDaAccessor.CacheVecProp(m_hvoRoot, m_mainFlid, originalObjects, originalObjects.Length); } } }
protected override void HandleSelectionChange(IVwRootBox rootb, IVwSelection vwselNew) { CheckDisposed(); if (m_handlingSelectionChanged) { return; } m_handlingSelectionChanged = true; try { m_selectedSenseHvo = 0; if (vwselNew == null) { return; } base.HandleSelectionChange(rootb, vwselNew); // Get the Id of the selected snes, and store it. int cvsli = vwselNew.CLevels(false); // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. cvsli--; if (cvsli == 0) { // No objects in selection: don't allow a selection. m_rootb.DestroySelection(); // Enhance: invoke launcher's selection dialog. return; } ITsString tss; int ichAnchor; int ichEnd; bool fAssocPrev; int hvoObj; int hvoObjEnd; int tag; int ws; vwselNew.TextSelInfo(false, out tss, out ichAnchor, out fAssocPrev, out hvoObj, out tag, out ws); vwselNew.TextSelInfo(true, out tss, out ichEnd, out fAssocPrev, out hvoObjEnd, out tag, out ws); if (hvoObj != hvoObjEnd) { return; } m_selectedSenseHvo = hvoObj; } finally { m_handlingSelectionChanged = false; } }
/// <summary> /// Determine whether the current selection is at a place suitable for type-ahead. If not, answer 0. /// (In this case the values of hvoParent and ihvo should not be relied on.) /// If so, indicate the object whose property may be set by type-ahead (hvoParent), the object /// in the relevant property that is selected (return result), and its index within the property /// (0 if atomic). /// </summary> /// <param name="rootb"></param> /// <param name="sel"></param> /// <param name="hvoParent"></param> /// <param name="ihvo"></param> /// <returns></returns> private int SelectedObject(IVwRootBox rootb, IVwSelection sel, out int hvoParent, out int ihvo) { hvoParent = 0; ihvo = 0; if (rootb == null) // If we don't have a root box, can't do anything interesting. { return(0); } if (sel == null) // nothing interesting to do without a selection, either. { return(0); } ITsString tssA, tssE; int ichA, ichE, hvoObjA, hvoObjE, tagA, tagE, ws; bool fAssocPrev; // Enhance JohnT: what we're really trying to do here is confirm that the selection is // all in one string property. We could readily have a method in the selection interface to tell us that. sel.TextSelInfo(false, out tssA, out ichA, out fAssocPrev, out hvoObjA, out tagA, out ws); if (tagA != m_taTagName && tagA != m_snTagName) { return(0); // selection not anchored in any sort of type-ahead name property. } sel.TextSelInfo(true, out tssE, out ichE, out fAssocPrev, out hvoObjE, out tagE, out ws); int cch = tssA.Length; // To do our type-ahead trick, both ends of the seleciton must be in the same string property. // Also, we want the selection to extend to the end of the name. // Enhance JohnT: if we do a popup window, it may not matter whether the selection extends // to the end; just show items that match. if (tagE != tagA || hvoObjE != hvoObjA || cch != tssE.Length || Math.Max(ichA, ichE) != cch) { return(0); // not going to attempt type-ahead behavior } int clev = sel.CLevels(false); if (clev < 2) { return(0); // can't be our property. } int tagParent, cpropPrevious; IVwPropertyStore vps; sel.PropInfo(false, 1, out hvoParent, out tagParent, out ihvo, out cpropPrevious, out vps); if (tagParent != m_virtualTagObj) { return(0); // not our virtual property! } return(hvoObjA); }
/// ------------------------------------------------------------------------------------ /// <summary> /// /// </summary> /// ------------------------------------------------------------------------------------ public override ITsString UpdateProp(IVwSelection vwsel, int hvo, int tag, int frag, ITsString tssVal) { CheckDisposed(); Debug.Assert(tag == kTagUserPrompt, "Got an unexpected tag"); // Get information about current selection int cvsli = vwsel.CLevels(false); cvsli--; // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. int ihvoRoot; int tagTextProp; int cpropPrevious; int ichAnchor; int ichEnd; int ihvoEnd; bool fAssocPrev; int ws; ITsTextProps ttp; SelLevInfo[] rgvsli = SelLevInfo.AllTextSelInfo(vwsel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttp); // get para info StTxtPara para = new StTxtPara(Cache, hvo); // ITsTextProps props = StyleUtils.CharStyleTextProps(null, Cache.DefaultVernWs); // // // set string info based on the para info // ITsStrBldr bldr = (ITsStrBldr)tssVal.GetBldr(); // bldr.SetProperties(0, bldr.Length, props); // tssVal = bldr.GetString(); // Add the text the user just typed to the paragraph - this destroys the selection // because we replace the user prompt. para.Contents.UnderlyingTsString = tssVal; // now restore the selection m_rootb.MakeTextSelection(ihvoRoot, cvsli, rgvsli, (int)StTxtPara.StTxtParaTags.kflidContents, cpropPrevious, ichAnchor, ichEnd, Cache.DefaultVernWs, fAssocPrev, ihvoEnd, null, true); return(tssVal); }
/// <summary> /// Get the array of SelLevInfo corresponding to one end point of a selection. /// </summary> /// <param name="vwselNew"></param> /// <param name="fEndPoint">True if we want the end of the selection. False if we want the anchor.</param> /// <returns></returns> protected static SelLevInfo[] GetOneEndPointOfSelection(IVwSelection vwselNew, bool fEndPoint) { // Get the info about the other end of the selection. int cvsli = vwselNew.CLevels(fEndPoint) - 1; SelLevInfo[] rgvsliEnd; using (ArrayPtr prgvsli = MarshalEx.ArrayToNative <SelLevInfo>(cvsli)) { int ihvoRoot, tagTextProp, cpropPrevious, ich, ws; bool fAssocPrev; ITsTextProps ttpSelProps; vwselNew.AllSelEndInfo(fEndPoint, out ihvoRoot, cvsli, prgvsli, out tagTextProp, out cpropPrevious, out ich, out ws, out fAssocPrev, out ttpSelProps); rgvsliEnd = MarshalEx.NativeToArray <SelLevInfo>(prgvsli, cvsli); } return(rgvsliEnd); }
protected override bool OnRightMouseDown(Point pt, Rectangle rcSrcRoot, Rectangle rcDstRoot) { IVwSelection vwsel = m_rootb.MakeSelAt(pt.X, pt.Y, rcSrcRoot, rcDstRoot, false); if (vwsel != null) { int clevels = vwsel.CLevels(false); // Figure which paragraph we clicked. The last level (clevels-1) is our top-level // list: hvoObj would be khvoBook. (clevels-2) is next: hvoObj is a section. // (clevels-3) gives us a paragraph object. int hvoObj, tag, ihvo, cpropPrevious; IVwPropertyStore vps; vwsel.PropInfo(false, clevels - 3, out hvoObj, out tag, out ihvo, out cpropPrevious, out vps); Parse(hvoObj); } return(true); }
// Regenerate the display of object m_ihvo of property m_virtualTagObj of object m_hvoParent, // assuming that the current selection is within it and that it will be displayed using // newTagName. private void SwitchTagAndFixSel(int newTagName, IVwRootBox rootb) { IVwSelection sel = rootb.Selection; int cvsli = 0; // Get selection information to determine where the user is typing. int ihvoRoot = 0; int tagTextProp = 0; int cpropPrevious = 0; int ichAnchor = 0; int ichEnd = 0; int ihvoEnd = 0; int ws = 0; ITsTextProps ttp = null; bool fAssocPrev = false; SelLevInfo[] rgvsli = null; if (sel != null) { // Next step will destroy selection. Save info to install new one. cvsli = sel.CLevels(false) - 1; // Get selection information to determine where the user is typing. rgvsli = SelLevInfo.AllTextSelInfo(sel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttp); } // This needs to be done even if we don't have a selection. m_sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, m_hvoParent, m_virtualTagObj, m_ihvoTa, 1, 1); if (sel != null) // nb old sel is now invalid, but should be OK to compare to null. { // Make a new selection. The critical difference is that, whereas tagTextProp was the other name property, // now that this is the active object the property displayed for its name is newTagName. try { rootb.MakeTextSelection(ihvoRoot, cvsli, rgvsli, newTagName, cpropPrevious, ichAnchor, ichEnd, ws, fAssocPrev, ihvoEnd, null, true); } catch { // Eat any exceptions. } } }
private ITsTextProps spyOnSelection(IVwSelection sel) { // See what got selected int ihvoRoot = 0; // first rootbox int cvsli = sel.CLevels(true); // selection levels-1 involved cvsli--; int tag; int cpropPrevious; int ichAnchor; int ichEnd; int ws; bool fAssocPrev; int ihvoEnd1; ITsTextProps ttp; ArrayPtr rgvsliTemp = MarshalEx.ArrayToNative(cvsli, typeof(SelLevInfo)); sel.AllTextSelInfo(out ihvoRoot, cvsli, rgvsliTemp, out tag, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd1, out ttp); SelLevInfo[] rgvsli = (SelLevInfo[])MarshalEx.NativeToArray(rgvsliTemp, cvsli, typeof(SelLevInfo)); // use the debugger to look at the vars. Can't get into ttp here. return(ttp); }
// Call this to create the appropriate subclass and set up the combo and return it. // May return null if no appropriate combo can be created at the current position. // Caller should hide all combos before calling, then // call Activate to add the combo to its controls (thus making it visible) // or display the ComboListBox if a non-null value // is returned. static internal IComboHandler MakeCombo(IHelpTopicProvider helpTopicProvider, IVwSelection vwselNew, SandboxBase sandbox, bool fMouseDown) { // Figure what property is selected and create a suitable class if appropriate. int cvsli = vwselNew.CLevels(false); // CLevels includes the string property itself, but AllTextSelInfo doesn't need // it. cvsli--; // Out variables for AllTextSelInfo. int ihvoRoot; int tagTextProp; int cpropPrevious; int ichAnchor; int ichEnd; int ws; bool fAssocPrev; int ihvoEnd; ITsTextProps ttpBogus; // Main array of information retrived from sel that made combo. SelLevInfo[] rgvsli; // Analysis can now be zero (e.g., displaying alterate case form for non-existent WfiWordform) // and I don't believe it's a problem for the code below (JohnT). // if (sandbox.Analysis == 0) // { // // We aren't fully initialized yet, so don't do anything. // return null; // } if (cvsli < 0) return null; try { rgvsli = SelLevInfo.AllTextSelInfo(vwselNew, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); } catch { // If anything goes wrong just give up. return null; } int hvoMorph = 0; int hvoSelObject = 0; if (tagTextProp >= ktagMinIcon && tagTextProp < ktagLimIcon) // its an icon { // If we're just hovering don't launch the pull-down. if (!fMouseDown) return null; if (rgvsli.Length >= 1) hvoMorph = hvoSelObject = rgvsli[0].hvo; return MakeCombo(helpTopicProvider, tagTextProp, sandbox, hvoMorph, rgvsli, hvoSelObject); } return null; }
/// <summary> /// Given a selection in the view, return the row index. Rarely may return -1 if unable to /// identify a row. /// </summary> /// <param name="sel"></param> /// <param name="fEndPoint">true to get index based on end of selection, false based on anchor. /// deafault is true, so in a long drag we get the mouse-up row.</param> /// <returns></returns> internal int GetRowIndexFromSelection(IVwSelection sel, bool fEndPoint) { if (sel == null) return -1; try { int clev = sel.CLevels(fEndPoint); int hvoRoot, tag, ihvo, cpropPrevious; IVwPropertyStore vps; sel.PropInfo(fEndPoint, clev - 1, out hvoRoot, out tag, out ihvo, out cpropPrevious, out vps); if (tag != m_fakeFlid) // not sure how this could happen, but the precaution was in an earlier version. return -1; return ihvo; } catch (System.Runtime.InteropServices.COMException) { // This shouldn't happen, but don't let it be catastrophic if it does. } return -1; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Selections the changed. /// </summary> /// <param name="prootb">The prootb.</param> /// <param name="sel">The sel.</param> /// ------------------------------------------------------------------------------------ public override void SelectionChanged(IVwRootBox prootb, IVwSelection sel) { CheckDisposed(); if (m_fInChangeSelectedObjects) { return; } m_fInChangeSelectedObjects = true; try { int cvsli = 0; // Out variables for AllTextSelInfo. int ihvoRoot = 0; int tagTextProp = 0; int cpropPrevious = 0; int ichAnchor = 0; int ichEnd = 0; int ws = 0; bool fAssocPrev = false; int ihvoEnd = 0; ITsTextProps ttpBogus = null; SelLevInfo[] rgvsli = new SelLevInfo[0]; List <int> newSelectedObjects = new List <int>(4); newSelectedObjects.Add(XmlVc.FocusHvo); if (sel != null) { cvsli = sel.CLevels(false) - 1; // Main array of information retrived from sel that made combo. rgvsli = SelLevInfo.AllTextSelInfo(sel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); for (int i = 0; i < cvsli; i++) { newSelectedObjects.Add(rgvsli[i].hvo); } } ISilDataAccess sda = Cache.MainCacheAccessor; IVwCacheDa cda = Cache.VwCacheDaAccessor; foreach (int hvo in m_selectedObjects) { if (!newSelectedObjects.Contains(hvo)) { cda.CacheIntProp(hvo, m_xmlVc.IsObjectSelectedTag, 0); sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, hvo, m_xmlVc.IsObjectSelectedTag, 0, 1, 1); } } foreach (int hvo in newSelectedObjects) { if (!m_selectedObjects.Contains(hvo)) { cda.CacheIntProp(hvo, m_xmlVc.IsObjectSelectedTag, 1); sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, hvo, m_xmlVc.IsObjectSelectedTag, 0, 1, 1); } } m_selectedObjects = newSelectedObjects; if (sel != null && !sel.IsValid) { // we wiped it out by regenerating parts of the display in our PropChanged calls! Restore it if we can. sel = m_rootb.MakeTextSelection(ihvoRoot, cvsli, rgvsli, tagTextProp, cpropPrevious, ichAnchor, ichEnd, ws, fAssocPrev, ihvoEnd, ttpBogus, true); } } finally { m_fInChangeSelectedObjects = false; } base.SelectionChanged(prootb, sel); }
/// <summary> /// Handles a view selection produced by a click. Return true to suppress normal /// mouse down handling, indicating that an interlinear bundle has been clicked and the Sandbox /// moved. /// </summary> /// <param name="vwselNew"></param> /// <param name="fBundleOnly"></param> /// <param name="fSaveGuess">if true, saves guesses; if false, skips guesses but still saves edits.</param> /// <returns></returns> protected virtual bool HandleClickSelection(IVwSelection vwselNew, bool fBundleOnly, bool fSaveGuess) { if (vwselNew == null) return false; // couldn't select a bundle! // The basic idea is to find the level at which we are displaying the TagAnalysis property. int cvsli = vwselNew.CLevels(false); cvsli--; // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. // Out variables for AllTextSelInfo. int ihvoRoot; int tagTextProp; int cpropPrevious; int ichAnchor; int ichEnd; int ws; bool fAssocPrev; int ihvoEnd; ITsTextProps ttpBogus; // Main array of information retrived from sel that made combo. SelLevInfo[] rgvsli = SelLevInfo.AllTextSelInfo(vwselNew, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); if (tagTextProp == (int)CmAnnotation.CmAnnotationTags.kflidComment) { bool fWasFocusBoxInstalled = IsFocusBoxInstalled; Rect oldSelLoc = GetPrimarySelRect(vwselNew); if (!fBundleOnly) DestroyFocusBoxAndSetFocus(fSaveGuess); // If the selection resulting from the click is still valid, and we just closed the focus box, go ahead and install it; // continuing to process the click may not produce the intended result, because // removing the focus box can re-arrange things substantially (LT-9220). // (However, if we didn't change anything it is necesary to process it normally, otherwise, dragging // and shift-clicking in the free translation don't work.) if (!vwselNew.IsValid || !fWasFocusBoxInstalled) return false; // We have destroyed a focus box...but we may not have moved the free translation we clicked enough // to cause problems. If not, we'd rather do a normal click, because installing a selection that // the root box doesn't think is from mouse down does not allow dragging. Rect selLoc = GetPrimarySelRect(vwselNew); if (selLoc.top == oldSelLoc.top) return false; vwselNew.Install(); return true; } // Identify the twfic, and the position in m_rgvsli of the property holding it. // It is also possible that the twfic is the root object. // This is important because although we are currently displaying just an StTxtPara, // eventually it might be part of a higher level structure. We want to be able to // reproduce everything that gets us down to the twfic. int itagAnalysis = -1; for (int i = rgvsli.Length; --i >= 0; ) { if (rgvsli[i].tag == TagAnalysis) { itagAnalysis = i; break; } } if (itagAnalysis < 0) { // Go ahead and hide the focus box, since it could try to still the selection back (cf. LT-7968) if (!fBundleOnly) DestroyFocusBoxAndSetFocus(fSaveGuess); return false; // Selection is somewhere we can't handle. } int hvoAnalysis = rgvsli[itagAnalysis].hvo; // The current analyis object. Debug.Assert(itagAnalysis < rgvsli.Length - 1); // Need different approach if the twfic is the root. int hvoAnnotation = rgvsli[itagAnalysis + 1].hvo; // Launch a combo on the base line. // if (tagTextProp == (int)WfiWordform.WfiWordformTags.kflidForm) // { // // First line: display the in-place combo. // analysisHandler = new ChooseAnalysisHandler(m_fdoCache, hvoSrc, hvoAnalysis); // analysisHandler.AnalysisChosen += analysisChosenDelegate; // analysisHandler.SetupCombo(); // analysisHandler.Show(m_site, m_vwselNew); // return; // } // Enhance JohnT: if click was on word gloss line, put cursor there instead of default. TriggerAnnotationSelected(hvoAnnotation, hvoAnalysis, fSaveGuess); // new HandleSelectionChangeMethod(vwselNew, this) // .Run(ref m_analysisHandler, m_vc.ListManager, // new EventHandler(m_analysisHandler_AnalysisChosen), new AdvanceWordEventHandler(scope_AdvanceWord)); return true; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Selections the changed. /// </summary> /// <param name="prootb">The prootb.</param> /// <param name="sel">The sel.</param> /// ------------------------------------------------------------------------------------ protected override void HandleSelectionChange(IVwRootBox prootb, IVwSelection sel) { CheckDisposed(); if (m_fInChangeSelectedObjects) { return; } m_fInChangeSelectedObjects = true; try { int cvsli = 0; // Out variables for AllTextSelInfo. int ihvoRoot = 0; int tagTextProp = 0; int cpropPrevious = 0; int ichAnchor = 0; int ichEnd = 0; int ws = 0; bool fAssocPrev = false; int ihvoEnd = 0; ITsTextProps ttpBogus = null; SelLevInfo[] rgvsli = new SelLevInfo[0]; List <int> newSelectedObjects = new List <int>(4); newSelectedObjects.Add(XmlVc.FocusHvo); if (sel != null) { cvsli = sel.CLevels(false) - 1; // Main array of information retrived from sel that made combo. rgvsli = SelLevInfo.AllTextSelInfo(sel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); for (int i = 0; i < cvsli; i++) { newSelectedObjects.Add(rgvsli[i].hvo); } } var changed = new HashSet <int>(m_xmlVc.SelectedObjects); changed.SymmetricExceptWith(newSelectedObjects); if (changed.Count != 0) { m_xmlVc.SelectedObjects = newSelectedObjects; // Generate propChanged calls that force the relevant parts of the view to redraw // to indicate which command icons should be visible. foreach (int hvo in changed) { m_rootb.PropChanged(hvo, XmlVc.IsObjectSelectedTag, 0, 1, 1); } if (sel != null && !sel.IsValid) { // we wiped it out by regenerating parts of the display in our PropChanged calls! Restore it if we can. sel = m_rootb.MakeTextSelection(ihvoRoot, cvsli, rgvsli, tagTextProp, cpropPrevious, ichAnchor, ichEnd, ws, fAssocPrev, ihvoEnd, ttpBogus, true); } } } finally { m_fInChangeSelectedObjects = false; } base.HandleSelectionChange(prootb, sel); }
public override void SelectionChanged(IVwRootBox rootb, IVwSelection vwselNew) { CheckDisposed(); if (m_handlingSelectionChanged) return; m_handlingSelectionChanged = true; try { m_selectedSenseHvo = 0; if (vwselNew == null) return; base.SelectionChanged(rootb, vwselNew); // Get the Id of the selected snes, and store it. int cvsli = vwselNew.CLevels(false); // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. cvsli--; if (cvsli == 0) { // No objects in selection: don't allow a selection. m_rootb.DestroySelection(); // Enhance: invoke launcher's selection dialog. return; } ITsString tss; int ichAnchor; int ichEnd; bool fAssocPrev; int hvoObj; int hvoObjEnd; int tag; int ws; vwselNew.TextSelInfo(false, out tss, out ichAnchor, out fAssocPrev, out hvoObj, out tag, out ws); vwselNew.TextSelInfo(true, out tss, out ichEnd, out fAssocPrev, out hvoObjEnd, out tag, out ws); if (hvoObj != hvoObjEnd) return; m_selectedSenseHvo = hvoObj; } finally { m_handlingSelectionChanged = false; } }
private ITsTextProps spyOnSelection(IVwSelection sel) { // See what got selected int ihvoRoot = 0; // first rootbox int cvsli = sel.CLevels(true); // selection levels-1 involved cvsli--; int tag; int cpropPrevious; int ichAnchor; int ichEnd; int ws; bool fAssocPrev; int ihvoEnd1; ITsTextProps ttp; ArrayPtr rgvsliTemp = MarshalEx.ArrayToNative(cvsli, typeof(SelLevInfo)); sel.AllTextSelInfo(out ihvoRoot, cvsli, rgvsliTemp, out tag, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd1, out ttp); SelLevInfo[] rgvsli = (SelLevInfo[])MarshalEx.NativeToArray(rgvsliTemp, cvsli, typeof(SelLevInfo)); // use the debugger to look at the vars. Can't get into ttp here. return ttp; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Selections the changed. /// </summary> /// <param name="prootb">The prootb.</param> /// <param name="sel">The sel.</param> /// ------------------------------------------------------------------------------------ protected override void HandleSelectionChange(IVwRootBox prootb, IVwSelection sel) { CheckDisposed(); if (m_fInChangeSelectedObjects) return; m_fInChangeSelectedObjects = true; try { int cvsli = 0; // Out variables for AllTextSelInfo. int ihvoRoot = 0; int tagTextProp = 0; int cpropPrevious = 0; int ichAnchor = 0; int ichEnd = 0; int ws = 0; bool fAssocPrev = false; int ihvoEnd = 0; ITsTextProps ttpBogus = null; SelLevInfo[] rgvsli = new SelLevInfo[0]; List<int> newSelectedObjects = new List<int>(4); newSelectedObjects.Add(XmlVc.FocusHvo); if (sel != null) { cvsli = sel.CLevels(false) - 1; // Main array of information retrived from sel that made combo. rgvsli = SelLevInfo.AllTextSelInfo(sel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); for (int i = 0; i < cvsli; i++) { newSelectedObjects.Add(rgvsli[i].hvo); } } var changed = new HashSet<int>(m_xmlVc.SelectedObjects); changed.SymmetricExceptWith(newSelectedObjects); if (changed.Count != 0) { m_xmlVc.SelectedObjects = newSelectedObjects; // Generate propChanged calls that force the relevant parts of the view to redraw // to indicate which command icons should be visible. foreach (int hvo in changed) m_rootb.PropChanged(hvo, XmlVc.IsObjectSelectedTag, 0, 1, 1); if (sel != null && !sel.IsValid) { // we wiped it out by regenerating parts of the display in our PropChanged calls! Restore it if we can. sel = m_rootb.MakeTextSelection(ihvoRoot, cvsli, rgvsli, tagTextProp, cpropPrevious, ichAnchor, ichEnd, ws, fAssocPrev, ihvoEnd, ttpBogus, true); } } } finally { m_fInChangeSelectedObjects = false; } base.HandleSelectionChange(prootb, sel); }
/// ----------------------------------------------------------------------------------- /// <summary> /// Replace the user prompt with the text the user typed. This method is called from /// the views code when the user prompt is edited. /// </summary> /// <param name="vwsel">Current selection in rootbox where this prop was updated</param> /// <param name="hvo">Hvo of the paragraph/string/segment whose contents are being /// changed</param> /// <param name="tag">Tag (must be SimpleRootSite.kTagUserPrompt)</param> /// <param name="frag">Owning flid of the text/object that owns the paragraph/string/ /// segment whose user prompt is being replaced with typed text</param> /// <param name="tssVal">Text the user just typed</param> /// <returns>possibly modified ITsString.</returns> /// <remarks>The return value is currently ignored in production code, but we use it /// in our tests.</remarks> /// ----------------------------------------------------------------------------------- public override ITsString UpdateProp(IVwSelection vwsel, int hvo, int tag, int frag, ITsString tssVal) { Debug.Assert(tag == SimpleRootSite.kTagUserPrompt, "Got an unexpected tag"); Debug.Assert(vwsel != null, "Got a null selection!"); Debug.Assert(vwsel.IsValid, "Got an invalid selection!"); IVwRootBox rootbox = vwsel.RootBox; // If a (typically Chinese) character composition is in progress, replacing the prompt will // destroy the selection and end the composition, causing weird typing problems (TE-8267). // Ending the composition does another Commit, which ensures that this will eventually be // called when there is NOT a composition in progress. if (rootbox.IsCompositionInProgress) return tssVal; // Remove the UserPrompt pseudo-property from the text the user typed. // when appropriate also ensure the correct writing system. // The correct WS is m_wsDefault in the view constructor ITsStrBldr bldr = tssVal.GetBldr(); if (frag != SegmentTags.kflidFreeTranslation) { bldr.SetIntPropValues(0, bldr.Length, (int)FwTextPropType.ktptWs, (int)FwTextPropVar.ktpvDefault, m_wsDefault); } // Delete the user prompt property from the string (TE-3994) bldr.SetIntPropValues(0, bldr.Length, SimpleRootSite.ktptUserPrompt, -1, -1); tssVal = bldr.GetString(); // Get information about current selection int cvsli = vwsel.CLevels(false); cvsli--; // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. int ihvoRoot; int tagTextProp_Ignore; int cpropPrevious; int ichAnchor; int ichEnd; int ihvoEnd; // Prior to the Commit in selection changed which causes this UpdateProp to be called, // earlier selection changed code has expanded the selection (because it is in a user prompt) // to the whole prompt. It is therefore a range selection, and the value of fAssocPrev we got // is useless. bool fAssocPrev_Ignore; int ws; ITsTextProps ttp; SelLevInfo[] rgvsli = SelLevInfo.AllTextSelInfo(vwsel, cvsli, out ihvoRoot, out tagTextProp_Ignore, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev_Ignore, out ihvoEnd, out ttp); int tagTextProp; ITsTextProps props = null; if (frag == SegmentTags.kflidFreeTranslation) { // If the length is zero...we need to suppress replacing the comment with a prompt. if (tssVal.Length == 0) m_hvoOfSegmentWhoseBtPromptIsToBeSupressed = hvo; ISegment seg = Cache.ServiceLocator.GetInstance<ISegmentRepository>().GetObject(hvo); if (seg.FreeTranslation.get_String(BackTranslationWS).Length == 0) { // Undo needs to unset suppressing the comment prompt. Cache.ActionHandlerAccessor.AddAction(new UndoSuppressBtPrompt(this, seg)); } ws = BackTranslationWS; tagTextProp = frag; seg.FreeTranslation.set_String(ws, tssVal); rootbox.PropChanged(seg.Paragraph.Owner.Hvo, StTextTags.kflidParagraphs, seg.Paragraph.IndexInOwner, 1, 1); } else { ReplacePromptUndoAction undoAction = new ReplacePromptUndoAction(hvo, rootbox, m_updatedPrompts); if (m_cache.ActionHandlerAccessor != null) { m_cache.ActionHandlerAccessor.AddAction( new UndoSelectionAction(rootbox.Site, true, vwsel)); m_cache.ActionHandlerAccessor.AddAction(undoAction); } // Mark the user prompt as having been updated - will not show prompt again. // Note: ReplacePromptUndoAction:Undo removes items from the Set. m_updatedPrompts.Add(hvo); // Replace the ITsString in the paragraph or translation props = StyleUtils.CharStyleTextProps(null, m_wsDefault); if (frag == CmTranslationTags.kflidTranslation) { ICmTranslation trans = Cache.ServiceLocator.GetInstance<ICmTranslationRepository>().GetObject(hvo); trans.Translation.set_String(m_wsDefault, tssVal); undoAction.ParaHvo = trans.Owner.Hvo; ws = BackTranslationWS; tagTextProp = frag; } else { IStTxtPara para = Cache.ServiceLocator.GetInstance<IStTxtParaRepository>().GetObject(hvo); para.Contents = tssVal; undoAction.ParaHvo = hvo; ws = 0; tagTextProp = StTxtParaTags.kflidContents; } // Do a fake propchange to update the prompt rootbox.PropChanged(undoAction.ParaHvo, StParaTags.kflidStyleRules, 0, 1, 1); } // Now request a selection at the end of the text that was just put in. rootbox.Site.RequestSelectionAtEndOfUow(rootbox, ihvoRoot, cvsli, rgvsli, tagTextProp, cpropPrevious, ichEnd, ws, true, props); return tssVal; }
/// <summary> /// Given a selection (typically from a click), determine the object that should be the target for jumping to, /// and return the property that was clicked (which in the case of a right-click may generate a spelling menu instead). /// </summary> /// <param name="sel"></param> /// <param name="hvoReal"></param> /// <returns></returns> private int GetInfoForJumpToTool(IVwSelection sel, out int hvoReal) { int ws; int tagRightClickTextProp; bool fAssocPrev; ITsString tss; int ichAnchorDum; int hvoRightClickObject = 0; sel.TextSelInfo(false, out tss, out ichAnchorDum, out fAssocPrev, out hvoRightClickObject, out tagRightClickTextProp, out ws); switch (tagRightClickTextProp) { case ktagSbMorphPrefix: case ktagSbMorphPostfix: m_hvoRightClickMorph = hvoRightClickObject; // Pretend we clicked on the morph form. (See LT-7590.) hvoRightClickObject = Caches.DataAccess.get_ObjectProp(hvoRightClickObject, ktagSbMorphForm); break; case ktagSbNamedObjName: if (sel.CLevels(false) < 2) break; int hvoOuterObj, tagOuter, ihvoOuter, cpropPreviousOuter; IVwPropertyStore vpsDummy; sel.PropInfo(false, 1, out hvoOuterObj, out tagOuter, out ihvoOuter, out cpropPreviousOuter, out vpsDummy); if (tagOuter == ktagSbMorphGloss || tagOuter == ktagSbMorphPos || tagOuter == ktagSbMorphForm || tagOuter == ktagSbMorphEntry) { m_hvoRightClickMorph = hvoOuterObj; } break; default: m_hvoRightClickMorph = 0; break; } hvoReal = m_caches.RealHvo(hvoRightClickObject); return tagRightClickTextProp; }
protected bool CheckForValidDelete(IVwSelection sel, out int cvsli, out int hvoObj) { hvoObj = 0; if (sel == null) { cvsli = 0; // satisfy compiler. return false; // nothing selected, give up. } cvsli = sel.CLevels(false); // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. cvsli--; if (cvsli == 0) { // No object in selection, so quit. return false; } ITsString tss; int ichAnchor; bool fAssocPrev; int tag; int ws; int ichEnd; int hvoObjEnd; sel.TextSelInfo(false, out tss, out ichAnchor, out fAssocPrev, out hvoObj, out tag, out ws); sel.TextSelInfo(true, out tss, out ichEnd, out fAssocPrev, out hvoObjEnd, out tag, out ws); return (hvoObj == hvoObjEnd); }
protected override void HandleSelectionChange(IVwRootBox rootb, IVwSelection vwselNew) { CheckDisposed(); if (vwselNew == null) return; int cvsli = vwselNew.CLevels(false); // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. cvsli--; if (cvsli == 0) { // No objects in selection: don't allow a selection. m_rootb.DestroySelection(); // Enhance: invoke launcher's selection dialog. return; } ITsString tss; int ichAnchor; int ichEnd; bool fAssocPrev; int hvoObj; int hvoObjEnd; int tag; int ws; vwselNew.TextSelInfo(false, out tss, out ichAnchor, out fAssocPrev, out hvoObj, out tag, out ws); vwselNew.TextSelInfo(true, out tss, out ichEnd, out fAssocPrev, out hvoObjEnd, out tag, out ws); if (hvoObj != hvoObjEnd) return; int ihvoRoot; int tagTextProp; int cpropPrevious; int ihvoEnd; ITsTextProps ttp; SelLevInfo[] rgvsli = SelLevInfo.AllTextSelInfo(vwselNew, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttp); Debug.Assert(m_rootb != null); // Create a selection that covers the entire target object. If it differs from // the new selection, we'll install it (which will recurse back to this method). IVwSelection vwselWhole = m_rootb.MakeTextSelInObj(ihvoRoot, cvsli, rgvsli, 0, null, false, false, false, true, false); if (vwselWhole != null) { ITsString tssWhole; int ichAnchorWhole; int ichEndWhole; int hvoObjWhole; int hvoObjEndWhole; bool fAssocPrevWhole; int tagWhole; int wsWhole; vwselWhole.TextSelInfo(false, out tssWhole, out ichAnchorWhole, out fAssocPrevWhole, out hvoObjWhole, out tagWhole, out wsWhole); vwselWhole.TextSelInfo(true, out tssWhole, out ichEndWhole, out fAssocPrevWhole, out hvoObjEndWhole, out tagWhole, out wsWhole); if (hvoObj == hvoObjWhole && hvoObjEnd == hvoObjEndWhole && (ichAnchor != ichAnchorWhole || ichEnd != ichEndWhole)) { // Install it this time! m_rootb.MakeTextSelInObj(ihvoRoot, cvsli, rgvsli, 0, null, false, false, false, true, true); } } }
protected AnalysisOccurrence GetAnalysisFromSelection(IVwSelection sel) { AnalysisOccurrence result = null; var cvsli = sel.CLevels(false); cvsli--; // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. // Out variables for AllTextSelInfo. int ihvoRoot; int tagTextProp; int cpropPrevious; int ichAnchor; int ichEnd; int ws; bool fAssocPrev; int ihvoEnd; ITsTextProps ttpBogus; // Main array of information retrieved from sel. var rgvsli = SelLevInfo.AllTextSelInfo(sel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); if (rgvsli.Length > 1) { // Need to loop backwards until we get down to index 1 or index produces a valid Segment. var i = rgvsli.Length - 1; ISegment seg = null; for (; i > 0; i--) { // get the container for whatever is selected at this level. ICmObject container; if (!m_objRepo.TryGetObject(rgvsli[i].hvo, out container)) return null; // may fail, e.g., trying to get bookmark for text just deleted. seg = container as ISegment; if (seg != null) break; } if (seg != null && i > 0) // This checks the case where there is no Segment in the selection at all { // Make a new AnalysisOccurrence var selObject = m_objRepo.GetObject(rgvsli[i-1].hvo); if (selObject is IAnalysis) { var indexInContainer = rgvsli[i-1].ihvo; result = new AnalysisOccurrence(seg, indexInContainer); } if (result == null || !result.IsValid) result = new AnalysisOccurrence(seg, 0); } else { // TODO: other possibilities?! Debug.Assert(false, "Reached 'other' situation in OccurrenceContainingSelection()."); } } return result; }
/// ----------------------------------------------------------------------------------- /// <summary> /// Replace the user prompt with the text the user typed. This method is called from /// the views code when the user prompt is edited. /// </summary> /// <param name="vwsel">Current selection in rootbox where this prop was updated</param> /// <param name="hvo">Hvo of the paragraph/string/segment whose contents are being /// changed</param> /// <param name="tag">Tag (must be SimpleRootSite.kTagUserPrompt)</param> /// <param name="frag">Owning flid of the text/object that owns the paragraph/string/ /// segment whose user prompt is being replaced with typed text</param> /// <param name="tssVal">Text the user just typed</param> /// <returns>possibly modified ITsString.</returns> /// <remarks>The return value is currently ignored in production code, but we use it /// in our tests.</remarks> /// ----------------------------------------------------------------------------------- public override ITsString UpdateProp(IVwSelection vwsel, int hvo, int tag, int frag, ITsString tssVal) { Debug.Assert(tag == SimpleRootSite.kTagUserPrompt, "Got an unexpected tag"); Debug.Assert(vwsel != null, "Got a null selection!"); Debug.Assert(vwsel.IsValid, "Got an invalid selection!"); IVwRootBox rootbox = vwsel.RootBox; // If a (typically Chinese) character composition is in progress, replacing the prompt will // destroy the selection and end the composition, causing weird typing problems (TE-8267). // Ending the composition does another Commit, which ensures that this will eventually be // called when there is NOT a composition in progress. if (rootbox.IsCompositionInProgress) { return(tssVal); } // Remove the UserPrompt pseudo-property from the text the user typed. // when appropriate also ensure the correct writing system. // The correct WS is m_wsDefault in the view constructor ITsStrBldr bldr = tssVal.GetBldr(); if (frag != SegmentTags.kflidFreeTranslation) { bldr.SetIntPropValues(0, bldr.Length, (int)FwTextPropType.ktptWs, (int)FwTextPropVar.ktpvDefault, m_wsDefault); } // Delete the user prompt property from the string (TE-3994) bldr.SetIntPropValues(0, bldr.Length, SimpleRootSite.ktptUserPrompt, -1, -1); tssVal = bldr.GetString(); // Get information about current selection int cvsli = vwsel.CLevels(false); cvsli--; // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. int ihvoRoot; int tagTextProp_Ignore; int cpropPrevious; int ichAnchor; int ichEnd; int ihvoEnd; // Prior to the Commit in selection changed which causes this UpdateProp to be called, // earlier selection changed code has expanded the selection (because it is in a user prompt) // to the whole prompt. It is therefore a range selection, and the value of fAssocPrev we got // is useless. bool fAssocPrev_Ignore; int ws; ITsTextProps ttp; SelLevInfo[] rgvsli = SelLevInfo.AllTextSelInfo(vwsel, cvsli, out ihvoRoot, out tagTextProp_Ignore, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev_Ignore, out ihvoEnd, out ttp); int tagTextProp; ITsTextProps props = null; if (frag == SegmentTags.kflidFreeTranslation) { // If the length is zero...we need to suppress replacing the comment with a prompt. if (tssVal.Length == 0) { m_hvoOfSegmentWhoseBtPromptIsToBeSupressed = hvo; } ISegment seg = Cache.ServiceLocator.GetInstance <ISegmentRepository>().GetObject(hvo); if (seg.FreeTranslation.get_String(BackTranslationWS).Length == 0) { // Undo needs to unset suppressing the comment prompt. Cache.ActionHandlerAccessor.AddAction(new UndoSuppressBtPrompt(this, seg)); } ws = BackTranslationWS; tagTextProp = frag; seg.FreeTranslation.set_String(ws, tssVal); rootbox.PropChanged(seg.Paragraph.Owner.Hvo, StTextTags.kflidParagraphs, seg.Paragraph.IndexInOwner, 1, 1); } else { ReplacePromptUndoAction undoAction = new ReplacePromptUndoAction(hvo, rootbox, m_updatedPrompts); if (m_cache.ActionHandlerAccessor != null) { m_cache.ActionHandlerAccessor.AddAction(new UndoSelectionAction(rootbox.Site, true, vwsel)); m_cache.ActionHandlerAccessor.AddAction(undoAction); } // Mark the user prompt as having been updated - will not show prompt again. // Note: ReplacePromptUndoAction:Undo removes items from the Set. m_updatedPrompts.Add(hvo); // Replace the ITsString in the paragraph or translation props = StyleUtils.CharStyleTextProps(null, m_wsDefault); if (frag == CmTranslationTags.kflidTranslation) { ICmTranslation trans = Cache.ServiceLocator.GetInstance <ICmTranslationRepository>().GetObject(hvo); trans.Translation.set_String(m_wsDefault, tssVal); undoAction.ParaHvo = trans.Owner.Hvo; ws = BackTranslationWS; tagTextProp = frag; } else { IStTxtPara para = Cache.ServiceLocator.GetInstance <IStTxtParaRepository>().GetObject(hvo); para.Contents = tssVal; undoAction.ParaHvo = hvo; ws = 0; tagTextProp = StTxtParaTags.kflidContents; } // Do a fake propchange to update the prompt rootbox.PropChanged(undoAction.ParaHvo, StParaTags.kflidStyleRules, 0, 1, 1); } // Now request a selection at the end of the text that was just put in. rootbox.Site.RequestSelectionAtEndOfUow(rootbox, ihvoRoot, cvsli, rgvsli, tagTextProp, cpropPrevious, ichEnd, ws, true, props); return(tssVal); }
/// ------------------------------------------------------------------------------------ /// <summary> /// /// </summary> /// ------------------------------------------------------------------------------------ public override ITsString UpdateProp(IVwSelection vwsel, int hvo, int tag, int frag, ITsString tssVal) { Debug.Assert(tag == kTagUserPrompt, "Got an unexpected tag"); // Get information about current selection int cvsli = vwsel.CLevels(false); cvsli--; // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. int ihvoRoot; int tagTextProp; int cpropPrevious; int ichAnchor; int ichEnd; int ihvoEnd; bool fAssocPrev; int ws; ITsTextProps ttp; SelLevInfo[] rgvsli = SelLevInfo.AllTextSelInfo(vwsel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttp); // get para info IStTxtPara para = Cache.ServiceLocator.GetInstance<IStTxtParaRepository>().GetObject(hvo); // ITsTextProps props = StyleUtils.CharStyleTextProps(null, Cache.DefaultVernWs); // // // set string info based on the para info // ITsStrBldr bldr = (ITsStrBldr)tssVal.GetBldr(); // bldr.SetProperties(0, bldr.Length, props); // tssVal = bldr.GetString(); // Add the text the user just typed to the paragraph - this destroys the selection // because we replace the user prompt. para.Contents = tssVal; // now restore the selection m_rootb.MakeTextSelection(ihvoRoot, cvsli, rgvsli, StTxtParaTags.kflidContents, cpropPrevious, ichAnchor, ichEnd, Cache.DefaultVernWs, fAssocPrev, ihvoEnd, null, true); return tssVal; }
/// ----------------------------------------------------------------------------------- /// <summary> /// Notifies the site that something about the selection has changed. /// </summary> /// <param name="prootb"></param> /// <param name="vwselNew">Selection</param> /// <remarks>When overriding you should call the base class first.</remarks> /// ----------------------------------------------------------------------------------- protected override void HandleSelectionChange(IVwRootBox prootb, IVwSelection vwselNew) { CheckDisposed(); base.HandleSelectionChange(prootb, vwselNew); if (vwselNew == null) return; int clev = vwselNew.CLevels(false); // anchor int clevEnd = vwselNew.CLevels(true); if (clev < 2 || clevEnd < 2) return; // paranoia int hvoRoot, tag, ihvo, ihvoEnd, cpropPrevious; IVwPropertyStore vps; vwselNew.PropInfo(true, clevEnd - 1, out hvoRoot, out tag, out ihvoEnd, out cpropPrevious, out vps); vwselNew.PropInfo(false, clev - 1, out hvoRoot, out tag, out ihvo, out cpropPrevious, out vps); // Give up if the selection doesn't indicate any top-level object; I think this can happen with pictures. // selection larger than a top-level object, maybe select all, side effects are confusing. if (ihvo != ihvoEnd || ihvo < 0) return; if (hvoRoot == 0) return; Debug.Assert(hvoRoot == m_hvoRoot); int hvoObjNewSel = m_sdaSource.get_VecItem(hvoRoot, tag, ihvo); if (hvoObjNewSel != 0) { // Notify any delegates that the selection of the main object in the vector // may have changed. if (SelectionChangedEvent != null) SelectionChangedEvent(this, new FwObjectSelectionEventArgs(hvoObjNewSel, ihvo)); } }
internal void Run(bool fMakeSelectionInNewFreeformAnnotation) { IVwSelection sel = null; if (m_site is InterlinDocChild) { sel = (m_site as InterlinDocChild).MakeSandboxSel(); } // If there's no sandbox selection, there may be one in the site itself, perhaps in another // free translation. if (sel == null) { sel = m_site.RootBox.Selection; } if (sel == null) { return; // Enhance JohnT: give an error, or disable the command. } int cvsli = sel.CLevels(false); cvsli--; // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. // Out variables for AllTextSelInfo. int ihvoRoot; int tagTextProp; int cpropPrevious; int ichAnchor; int ichEnd; int ws; bool fAssocPrev; int ihvoEnd; ITsTextProps ttpBogus; // Main array of information retrived from sel that made combo. SelLevInfo[] rgvsli = SelLevInfo.AllTextSelInfo(sel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); // Identify the segment. // This is important because although we are currently displaying just an StTxtPara, // eventually it might be part of a higher level structure. We want this to work // no matter how much higher level structure there is. int itagSegments = -1; for (int i = rgvsli.Length; --i >= 0;) { if (rgvsli[i].tag == m_vc.ktagParaSegments) { itagSegments = i; break; } } if (itagSegments == -1) { return; // Enhance JohnT: throw? disable command? Give an error? } int hvoSeg = rgvsli[itagSegments].hvo; if (m_fdoCache.IsDummyObject(hvoSeg)) { // we need to convert this into a real segment before proceeding. ICmBaseAnnotation cbaReal = CmBaseAnnotation.ConvertBaseAnnotationToReal(m_fdoCache, hvoSeg); hvoSeg = cbaReal != null ? cbaReal.Hvo : 0; rgvsli[itagSegments].hvo = hvoSeg; } ICmIndirectAnnotation ann = AddFreeformAnnotation(hvoSeg, m_hvoType); // If necessary (e.g., we just added a previously invisible FF annotation), // Reconstruct the root box. Otherwise, a simple PropChanged will do. if (m_fNeedReconstruct) { m_site.RootBox.Reconstruct(); // m_site.Invalidate(); // m_site.Update(); // necessary to get a lazy } if (!fMakeSelectionInNewFreeformAnnotation) { return; } // Now try to make a new selection in the FF we just made. // The elements of rgvsli from itagSegments onwards form a path to the segment. // In the segment we want the freeform propery, specifically the new one we just made. // We want to select at the start of it. SelLevInfo[] rgvsliNew = new SelLevInfo[rgvsli.Length - itagSegments + 1]; for (int i = 1; i < rgvsliNew.Length; i++) { rgvsliNew[i] = rgvsli[i + itagSegments - 1]; } // Work out how many freeforms are DISPLAYED before the (first occurrence of the) one we want to select. int ihvo = 0; Dictionary <int, List <int> > dict = m_vc.OrganizeFfAnnotations(hvoSeg); for (int i = m_choices.FirstFreeformIndex; i < m_choices.Count;) { int hvoAnnType = m_vc.SegDefnFromFfFlid(m_choices[i].Flid); List <int> annotations = null; if (dict.ContainsKey(hvoAnnType)) { annotations = dict[hvoAnnType]; } if (hvoAnnType == m_hvoType) { ihvo += annotations.IndexOf(ann.Hvo); break; // And that's where we want our selection!! } // Adjacent WSS of the same annotation count as only ONE object in the display. // So we advance i over as many items in m_choices as there are adjacent Wss // of the same flid. i += m_choices.AdjacentWssAtIndex(i).Length; // But each time we display this flid, we display ALL the objects, // so advance ihvo by the number of annotations of the type. int chvoAnn = annotations == null ? 0 : annotations.Count; ihvo += chvoAnn; } rgvsliNew[0].ihvo = ihvo; rgvsliNew[0].tag = m_vc.ktagSegFF; rgvsliNew[0].cpropPrevious = 0; m_site.RootBox.MakeTextSelInObj(0, rgvsliNew.Length, rgvsliNew, 0, null, true, true, false, false, true); }
/// <summary> /// Check whether Free Translation and/or Literal Translation annotations already exist /// for the segment containing the given selection. /// </summary> /// <param name="vwsel"></param> private void CheckForFreeOrLitAnnotations(IVwSelection sel) { m_fCanAddFreeTrans = false; m_fCanAddLitTrans = false; m_fCanAddNote = false; if (sel == null || !m_fForEditing) return; int cvsli = sel.CLevels(false); // CLevels includes the string property itself, but AllTextSelInfo doesn't need // it. cvsli--; // Out variables for AllTextSelInfo. int ihvoRoot; int tagTextProp; int cpropPrevious; int ichAnchor; int ichEnd; int ws; bool fAssocPrev; int ihvoEnd; ITsTextProps ttpBogus; // Main array of information retrived from sel that made combo. SelLevInfo[] rgvsli = SelLevInfo.AllTextSelInfo(sel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); // Identify the segment. // This is important because although we are currently displaying just an // StTxtPara, eventually it might be part of a higher level structure. We want // this to work no matter how much higher level structure there is. int itagSegments = -1; for (int i = rgvsli.Length; --i >= 0; ) { if (rgvsli[i].tag == m_vc.ktagParaSegments) { itagSegments = i; break; } } if (itagSegments == -1) return; // All the above, just to get hvoSeg! int hvoSeg = rgvsli[itagSegments].hvo; ISilDataAccess sda = Cache.MainCacheAccessor; int cFreeForm = sda.get_VecSize(hvoSeg, m_vc.ktagSegFF); m_fCanAddFreeTrans = true; m_fCanAddLitTrans = true; m_fCanAddNote = true; for (int i = 0; i < cFreeForm; i++) { int hvoAnn = sda.get_VecItem(hvoSeg, m_vc.ktagSegFF, i); int hvo = sda.get_ObjectProp(hvoAnn, (int)CmAnnotation.CmAnnotationTags.kflidAnnotationType); // Only one Free Translation annotation and one Literal Translation annotation // is allowed for each segment! if (hvo == m_vc.FtSegmentDefn) m_fCanAddFreeTrans = false; if (hvo == m_vc.LtSegmentDefn) m_fCanAddLitTrans = false; } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Selections the changed. /// </summary> /// <param name="prootb">The prootb.</param> /// <param name="sel">The sel.</param> /// ------------------------------------------------------------------------------------ public override void SelectionChanged(IVwRootBox prootb, IVwSelection sel) { CheckDisposed(); if (m_fInChangeSelectedObjects) return; m_fInChangeSelectedObjects = true; try { int cvsli = 0; // Out variables for AllTextSelInfo. int ihvoRoot = 0; int tagTextProp = 0; int cpropPrevious = 0; int ichAnchor = 0; int ichEnd = 0; int ws = 0; bool fAssocPrev = false; int ihvoEnd = 0; ITsTextProps ttpBogus = null; SelLevInfo[] rgvsli = new SelLevInfo[0]; List<int> newSelectedObjects = new List<int>(4); newSelectedObjects.Add(XmlVc.FocusHvo); if (sel != null) { cvsli = sel.CLevels(false) - 1; // Main array of information retrived from sel that made combo. rgvsli = SelLevInfo.AllTextSelInfo(sel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); for (int i = 0; i < cvsli; i++) { newSelectedObjects.Add(rgvsli[i].hvo); } } ISilDataAccess sda = Cache.MainCacheAccessor; IVwCacheDa cda = Cache.VwCacheDaAccessor; foreach (int hvo in m_selectedObjects) { if (!newSelectedObjects.Contains(hvo)) { cda.CacheIntProp(hvo, m_xmlVc.IsObjectSelectedTag, 0); sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, hvo, m_xmlVc.IsObjectSelectedTag, 0, 1, 1); } } foreach (int hvo in newSelectedObjects) { if (!m_selectedObjects.Contains(hvo)) { cda.CacheIntProp(hvo, m_xmlVc.IsObjectSelectedTag, 1); sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, hvo, m_xmlVc.IsObjectSelectedTag, 0, 1, 1); } } m_selectedObjects = newSelectedObjects; if (sel != null && !sel.IsValid) { // we wiped it out by regenerating parts of the display in our PropChanged calls! Restore it if we can. sel = m_rootb.MakeTextSelection(ihvoRoot, cvsli, rgvsli, tagTextProp, cpropPrevious, ichAnchor, ichEnd, ws, fAssocPrev, ihvoEnd, ttpBogus, true); } } finally { m_fInChangeSelectedObjects = false; } base.SelectionChanged(prootb, sel); }
/// <summary> /// This is the real guts of type-ahead. It is called by the client whenever a key is pressed. /// It returns true if it handled the key press, which it does if the current selection /// is in a type-ahead name property. /// </summary> /// <param name="ehelp"></param> /// <param name="e"></param> /// <param name="modifiers"></param> /// <param name="vwGraphics"></param> /// <returns></returns> public virtual bool OnKeyPress(EditingHelper ehelp, KeyPressEventArgs e, Keys modifiers, IVwGraphics vwGraphics) { IVwRootBox rootb = ehelp.Callbacks.EditedRootBox; if (rootb == null) // If we don't have a root box, can't do anything interesting. { return(false); } IVwSelection sel = rootb.Selection; if (sel == null) // nothing interesting to do without a selection, either. { return(false); } ITsString tssA, tssE; int ichA, ichE, hvoObjA, hvoObjE, tagA, tagE, ws; bool fAssocPrev; // Enhance JohnT: what we're really trying to do here is confirm that the selection is // all in one string property. We could readily have a method in the selection interface to tell us that. sel.TextSelInfo(false, out tssA, out ichA, out fAssocPrev, out hvoObjA, out tagA, out ws); if (tagA != m_taTagName) { return(false); // selection not anchored in a type-ahead name property. } sel.TextSelInfo(true, out tssE, out ichE, out fAssocPrev, out hvoObjE, out tagE, out ws); int cch = tssA.Length; // To do our type-ahead trick, both ends of the seleciton must be in the same string property. // Also, we want the selection to extend to the end of the name. // Enhance JohnT: poupu list may not depend on selection extending to end. if (tagE != m_taTagName || hvoObjE != hvoObjA || cch != tssE.Length || Math.Max(ichA, ichE) != cch) { return(false); // not going to attempt type-ahead behavior } // if the key pressed is a backspace or del, prevent smart completion, // otherwise we are likely to put back what the user deleted. // Review JohnT: do arrow keys come through here? What do we do if so? int charT = Convert.ToInt32(e.KeyChar); if (charT == (int)Keys.Back || charT == (int)Keys.Delete) { return(false); // normal key handling will just delete selection. // Review: should backspace delete one more? } // OK, we're in a type-ahead situation. First step is to let normal editing take place. ehelp.OnKeyPress(e, modifiers); e.Handled = true; // Now see what we have. Note that our old selection is no longer valid. sel = rootb.Selection; if (sel == null) { return(true); // can't be smart, but we already did the keypress. } int cvsli = sel.CLevels(false); // CLevels includes the string prop itself, but AllTextSelInfo does not need it. cvsli--; // Get selection information to determine where the user is typing. int ihvoObj; int tagTextProp; int cpropPrevious, ichAnchor, ichEnd, ihvoEnd; ITsTextProps ttp; SelLevInfo[] rgvsli = SelLevInfo.AllTextSelInfo(sel, cvsli, out ihvoObj, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttp); if (tagTextProp != m_taTagName || ichAnchor != ichEnd || ihvoEnd != -1 || cvsli < 1) { return(true); // something bizarre happened, but keypress is done. } int hvoLeaf = rgvsli[0].hvo; // Get the parent object we will modify. // (This would usually work, but not if the parent object is the root of the whole display, // as in a simple atomic ref type ahead slice. //int hvoParent = rgvsli[1].hvo; // object whose reference property we are setting.) int tagParent, cpropPreviousDummy, ihvo; IVwPropertyStore vps; int hvoParent; sel.PropInfo(false, 1, out hvoParent, out tagParent, out ihvo, out cpropPreviousDummy, out vps); if (hvoParent != m_hvoParent) { return(true); // another bizarre unexpected event. } // This is what the name looks like after the keypress. ITsString tssTyped = m_sda.get_StringProp(hvoLeaf, m_taTagName); // Get the substitute. This is where the actual type-ahead behavior happens. Sets hvoNewRef to 0 if no match. ICmObject objNewRef; ITsString tssLookup = Lookup(tssTyped, out objNewRef); int hvoNewRef = (objNewRef != null) ? objNewRef.Hvo : 0; IVwCacheDa cda = m_sda as IVwCacheDa; if (hvoNewRef == 0 && tssTyped.Length > 0) { // No match...underline string in red squiggle. ITsStrBldr bldr = tssLookup.GetBldr(); bldr.SetIntPropValues(0, tssLookup.Length, (int)FwTextPropType.ktptUnderline, (int)FwTextPropVar.ktpvEnum, (int)FwUnderlineType.kuntSquiggle); bldr.SetIntPropValues(0, tssLookup.Length, (int)FwTextPropType.ktptUnderColor, (int)FwTextPropVar.ktpvDefault, (int)ColorUtil.ConvertColorToBGR(Color.Red)); tssLookup = bldr.GetString(); } // Don't rely on sel from here on. if (hvoNewRef != hvoLeaf) { m_hvoTa = hvoNewRef; // Before we replace in the prop, so it gets displayed using special ta prop. switch (m_type) { case CellarPropertyType.ReferenceAtomic: if (m_hvoParent != 0) // I think it always is, except when loss of focus during debugging causes problems. { // If nothing matched, set the real property to null and the fake one to kbaseFakeObj. // Otherwise set both to the indicated object. m_sda.SetObjProp(m_hvoParent, m_tag, hvoNewRef); // Review: do we want to set the real thing yet? m_sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, m_hvoParent, m_tag, 0, 1, 1); if (hvoNewRef == 0) { hvoNewRef = m_hvoTa = kBaseFakeObj; // use in fake so we can display something. } cda.CacheObjProp(m_hvoParent, m_virtualTagObj, hvoNewRef); // Change the fake property m_sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, m_hvoParent, m_virtualTagObj, 0, 1, 1); } break; case CellarPropertyType.ReferenceSequence: case CellarPropertyType.ReferenceCollection: // Several cases, depending on whether we got a match and whether hvoLeaf is the dummy object // 1. match on dummy: insert appropriate real object, change dummy name to empty. // 2. match on non-dummy: replace old object with new // 3: non-match: do nothing. (Even if not looking at the fake object, we'll go on using the // actual object as a base for the fake name, since it's displayed only for the active position.) if (hvoNewRef == 0) { break; // case 3 } if (hvoLeaf == kBaseFakeObj) { // case 1 // The fake object goes back to being an empty name at the end of the list. ITsStrBldr bldr = tssLookup.GetBldr(); bldr.ReplaceTsString(0, bldr.Length, null); // makes an empty string in correct ws. cda.CacheStringProp(kBaseFakeObj, m_taTagName, bldr.GetString()); // Insert the new object before the fake one in fake prop and at end of real seq. // Include the fake object in the replace to get it redisplayed also. cda.CacheReplace(m_hvoParent, m_virtualTagObj, m_ihvoTa, m_ihvoTa + 1, new int[] { hvoNewRef, kBaseFakeObj }, 2); m_sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, m_hvoParent, m_virtualTagObj, m_ihvoTa, 2, 1); m_sda.Replace(m_hvoParent, m_tag, m_ihvoTa, m_ihvoTa, new int[] { hvoNewRef }, 1); m_sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, m_hvoParent, m_tag, m_ihvoTa, 1, 0); } else { // case 2 // Replace the object being edited with the indicated one in both props. cda.CacheReplace(m_hvoParent, m_virtualTagObj, m_ihvoTa, m_ihvoTa + 1, new int[] { hvoNewRef }, 1); m_sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, m_hvoParent, m_virtualTagObj, m_ihvoTa, 1, 1); m_sda.Replace(m_hvoParent, m_tag, m_ihvoTa, m_ihvoTa + 1, new int[] { hvoNewRef }, 1); m_sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, m_hvoParent, m_tag, m_ihvoTa, 1, 1); } break; default: throw new Exception("unsupported property type for type-ahead chooser"); } } cda.CacheStringProp(hvoNewRef, m_taTagName, tssLookup); m_sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, hvoNewRef, m_taTagName, 0, tssLookup.Length, tssTyped.Length); // Make a new selection, typically the range that is the bit added to the typed string. // no change is needed to rgvsli because it's the same object index in the same property of the same parent. sel = rootb.MakeTextSelection(ihvoObj, cvsli, rgvsli, m_taTagName, cpropPrevious, ichAnchor, tssLookup.Length, ws, true, -1, null, true); return(true); }
/// ----------------------------------------------------------------------------------- /// <summary> /// Notifies the site that something about the selection has changed. /// </summary> /// <param name="prootb"></param> /// <param name="vwselNew">Selection</param> /// <remarks>When overriding you should call the base class first.</remarks> /// ----------------------------------------------------------------------------------- public override void SelectionChanged(IVwRootBox prootb, IVwSelection vwselNew) { CheckDisposed(); base.SelectionChanged(prootb, vwselNew); if (vwselNew == null) return; int clev = vwselNew.CLevels(false); // anchor int hvoRoot, tag, ihvo, cpropPrevious; IVwPropertyStore vps; vwselNew.PropInfo(false, clev - 1, out hvoRoot, out tag, out ihvo, out cpropPrevious, out vps); Debug.Assert(hvoRoot == m_hvoRoot); int hvoObjNewSel = m_fdoCache.MainCacheAccessor.get_VecItem(hvoRoot, tag, ihvo); if (hvoObjNewSel != 0) { // Notify any delegates that the selection of the main object in the vector // may have changed. if (SelectionChangedEvent != null) SelectionChangedEvent(this, new FwObjectSelectionEventArgs(hvoObjNewSel, ihvo)); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// We override this method to make a selection in all of the views that are in a /// synced group. This fixes problems where the user changes the selection in one of /// the slaves, but the master is not updated. Thus the view is not scrolled as the /// groups scroll position only scrolls the master's selection into view. (TE-3380) /// </summary> /// <param name="rootb">The rootbox whose selection changed</param> /// <param name="vwselNew">The new selection</param> /// ------------------------------------------------------------------------------------ protected override void HandleSelectionChange(IVwRootBox rootb, IVwSelection vwselNew) { CheckDisposed(); // Guard against recursive calls, typically caused by the MakeTextSelection call below. if (m_fInSelectionChanged) return; try { m_fInSelectionChanged = true; // Make sure we're not handling MouseDown since it // handles SelectionChanged and DoSelectionSideEffects. // No need to do it again. if (!ReadOnlySelect && !m_fHandlingMouseUp) { if (vwselNew == null) return; // The selection can apparently be invalid on rare occasions, and will lead // to a crash below trying to call CLevels. See LT-10301. Treat it the // same as a null selection. if (!vwselNew.IsValid) return; base.HandleSelectionChange(rootb, vwselNew); m_wantScrollIntoView = false; // It should already be visible here. // Collect all the information we can about the selection. int ihvoRoot = 0; int tagTextProp = 0; int cpropPrevious = 0; int ichAnchor = 0; int ichEnd = 0; int ws = 0; bool fAssocPrev = false; int ihvoEnd = 0; ITsTextProps ttpBogus = null; SelLevInfo[] rgvsli = new SelLevInfo[0]; int cvsli = vwselNew.CLevels(false) - 1; if (cvsli < 0) return;// Nothing useful we can do. // Main array of information retrived from sel that made combo. rgvsli = SelLevInfo.AllTextSelInfo(vwselNew, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); //for (int i = 0; i < cvsli; ++i) //{ // Debug.Write(String.Format("XmlBrowseView.SelectionChanged(): rgvsli[{0}].hvo={1}, ivho={2}, tag={3}, cpropPrevious={4}, ich={5}, ws={6}", // i, rgvsli[i].hvo, rgvsli[i].ihvo, rgvsli[i].tag, rgvsli[i].cpropPrevious, rgvsli[i].ich, rgvsli[i].ws)); // Debug.WriteLine(String.Format("; ihvoRoot={0}, ihvoEnd={1}, ichEnd={2}", // ihvoRoot, ihvoEnd, ichEnd)); //} // The call to the base implementation can invalidate the selection. It's rare, but quite // possible. (See the comment in EditingHelper.SelectionChanged() following // Commit().) This test fixes LT-4731. if (vwselNew.IsValid) { DoSelectionSideEffects(vwselNew); } else { // But if the selection is invalid, and we do nothing about it, then we can // type only one character at a time in a browse cell because we no longer // have a valid selection. See LT-6443. rootb.MakeTextSelection(ihvoRoot, cvsli, rgvsli, tagTextProp, cpropPrevious, ichAnchor, ichEnd, ws, fAssocPrev, ihvoEnd, ttpBogus, true); DoSelectionSideEffects(rootb.Selection); } m_wantScrollIntoView = true; } } finally { m_fInSelectionChanged = false; } }
/// <summary> /// Determine whether the current selection is at a place suitable for type-ahead. If not, answer 0. /// (In this case the values of hvoParent and ihvo should not be relied on.) /// If so, indicate the object whose property may be set by type-ahead (hvoParent), the object /// in the relevant property that is selected (return result), and its index within the property /// (0 if atomic). /// </summary> /// <param name="rootb"></param> /// <param name="sel"></param> /// <param name="hvoParent"></param> /// <param name="ihvo"></param> /// <returns></returns> private int SelectedObject(IVwRootBox rootb, IVwSelection sel, out int hvoParent, out int ihvo) { hvoParent = 0; ihvo = 0; if (rootb == null) // If we don't have a root box, can't do anything interesting. return 0; if (sel == null) // nothing interesting to do without a selection, either. return 0; ITsString tssA, tssE; int ichA, ichE, hvoObjA, hvoObjE, tagA, tagE, ws; bool fAssocPrev; // Enhance JohnT: what we're really trying to do here is confirm that the selection is // all in one string property. We could readily have a method in the selection interface to tell us that. sel.TextSelInfo(false, out tssA, out ichA, out fAssocPrev, out hvoObjA, out tagA, out ws); if (tagA != m_taTagName && tagA != m_snTagName) return 0; // selection not anchored in any sort of type-ahead name property. sel.TextSelInfo(true, out tssE, out ichE, out fAssocPrev, out hvoObjE, out tagE, out ws); int cch = tssA.Length; // To do our type-ahead trick, both ends of the seleciton must be in the same string property. // Also, we want the selection to extend to the end of the name. // Enhance JohnT: if we do a popup window, it may not matter whether the selection extends // to the end; just show items that match. if (tagE != tagA || hvoObjE != hvoObjA || cch != tssE.Length || Math.Max(ichA, ichE) != cch) return 0; // not going to attempt type-ahead behavior int clev = sel.CLevels(false); if (clev < 2) return 0; // can't be our property. int tagParent, cpropPrevious; IVwPropertyStore vps; sel.PropInfo(false, 1, out hvoParent, out tagParent, out ihvo, out cpropPrevious, out vps); if (tagParent != m_virtualTagObj) return 0; // not our virtual property! return hvoObjA; }
/// <summary> /// Get the array of SelLevInfo corresponding to one end point of a selection. /// </summary> /// <param name="vwselNew"></param> /// <param name="fEndPoint">True if we want the end of the selection. False if we want the anchor.</param> /// <returns></returns> protected static SelLevInfo[] GetOneEndPointOfSelection(IVwSelection vwselNew, bool fEndPoint) { // Get the info about the other end of the selection. int ihvoRoot, tagTextProp, cpropPrevious, ich, ws; bool fAssocPrev; ITsTextProps ttpSelProps; int cvsli = vwselNew.CLevels(fEndPoint) - 1; SelLevInfo[] rgvsliEnd; using (ArrayPtr prgvsli = MarshalEx.ArrayToNative(cvsli, typeof(SelLevInfo))) { vwselNew.AllSelEndInfo(fEndPoint, out ihvoRoot, cvsli, prgvsli, out tagTextProp, out cpropPrevious, out ich, out ws, out fAssocPrev, out ttpSelProps); rgvsliEnd = (SelLevInfo[])MarshalEx.NativeToArray(prgvsli, cvsli, typeof(SelLevInfo)); } return rgvsliEnd; }
/// ------------------------------------------------------------------------------------ /// <summary> /// We override this method to make a selection in all of the views that are in a /// synced group. This fixes problems where the user changes the selection in one of /// the slaves, but the master is not updated. Thus the view is not scrolled as the /// groups scroll position only scrolls the master's selection into view. (TE-3380) /// </summary> /// <param name="rootb">The rootbox whose selection changed</param> /// <param name="vwselNew">The new selection</param> /// ------------------------------------------------------------------------------------ protected override void HandleSelectionChange(IVwRootBox rootb, IVwSelection vwselNew) { CheckDisposed(); // Guard against recursive calls, typically caused by the MakeTextSelection call below. if (m_fInSelectionChanged) { return; } try { m_fInSelectionChanged = true; // Make sure we're not handling MouseDown since it // handles SelectionChanged and DoSelectionSideEffects. // No need to do it again. if (!ReadOnlySelect && !m_fHandlingMouseUp) { if (vwselNew == null) { return; } // The selection can apparently be invalid on rare occasions, and will lead // to a crash below trying to call CLevels. See LT-10301. Treat it the // same as a null selection. if (!vwselNew.IsValid) { return; } base.HandleSelectionChange(rootb, vwselNew); m_wantScrollIntoView = false; // It should already be visible here. // Collect all the information we can about the selection. int ihvoRoot = 0; int tagTextProp = 0; int cpropPrevious = 0; int ichAnchor = 0; int ichEnd = 0; int ws = 0; bool fAssocPrev = false; int ihvoEnd = 0; ITsTextProps ttpBogus = null; SelLevInfo[] rgvsli = new SelLevInfo[0]; int cvsli = vwselNew.CLevels(false) - 1; if (cvsli < 0) { return; // Nothing useful we can do. } // Main array of information retrived from sel that made combo. rgvsli = SelLevInfo.AllTextSelInfo(vwselNew, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); //for (int i = 0; i < cvsli; ++i) //{ // Debug.Write(String.Format("XmlBrowseView.SelectionChanged(): rgvsli[{0}].hvo={1}, ivho={2}, tag={3}, cpropPrevious={4}, ich={5}, ws={6}", // i, rgvsli[i].hvo, rgvsli[i].ihvo, rgvsli[i].tag, rgvsli[i].cpropPrevious, rgvsli[i].ich, rgvsli[i].ws)); // Debug.WriteLine(String.Format("; ihvoRoot={0}, ihvoEnd={1}, ichEnd={2}", // ihvoRoot, ihvoEnd, ichEnd)); //} // The call to the base implementation can invalidate the selection. It's rare, but quite // possible. (See the comment in EditingHelper.SelectionChanged() following // Commit().) This test fixes LT-4731. if (vwselNew.IsValid) { DoSelectionSideEffects(vwselNew); } else { // But if the selection is invalid, and we do nothing about it, then we can // type only one character at a time in a browse cell because we no longer // have a valid selection. See LT-6443. rootb.MakeTextSelection(ihvoRoot, cvsli, rgvsli, tagTextProp, cpropPrevious, ichAnchor, ichEnd, ws, fAssocPrev, ihvoEnd, ttpBogus, true); DoSelectionSideEffects(rootb.Selection); } m_wantScrollIntoView = true; } } finally { m_fInSelectionChanged = false; } }
/// ----------------------------------------------------------------------------------- /// <summary> /// Replace the user prompt with the text the user typed. This method is called from /// the views code when the user prompt is edited. /// </summary> /// <param name="vwsel">Current selection in rootbox where this prop was updated</param> /// <param name="hvo">Hvo of the paragraph</param> /// <param name="tag">Tag</param> /// <param name="frag">Fragment</param> /// <param name="tssVal">Text the user just typed</param> /// <returns>possibly modified ITsString.</returns> /// <remarks>The return value is currently ignored in production code, but we use it /// in our tests.</remarks> /// ----------------------------------------------------------------------------------- public override ITsString UpdateProp(IVwSelection vwsel, int hvo, int tag, int frag, ITsString tssVal) { CheckDisposed(); Debug.Assert(tag == SimpleRootSite.kTagUserPrompt, "Got an unexpected tag"); Debug.Assert(vwsel != null, "Got a null selection!"); Debug.Assert(vwsel.IsValid, "Got an invalid selection!"); IVwRootBox rootbox = vwsel.RootBox; // If a (typically Chinese) character composition is in progress, replacing the prompt will // destroy the selection and end the composition, causing weird typing problems (TE-8267). // Ending the composition does another Commit, which ensures that this will eventually be // called when there is NOT a composition in progress. if (rootbox.IsCompositionInProgress) return tssVal; // Remove the UserPrompt pseudo-property from the text the user typed. // when appropriate also ensure the correct writing system. // The correct WS is m_wsDefault in the view constructor ITsStrBldr bldr = (ITsStrBldr)tssVal.GetBldr(); if (frag != (int)CmAnnotation.CmAnnotationTags.kflidComment) { bldr.SetIntPropValues(0, bldr.Length, (int)FwTextPropType.ktptWs, (int)FwTextPropVar.ktpvDefault, m_wsDefault); } // Delete the user prompt property from the string (TE-3994) bldr.SetIntPropValues(0, bldr.Length, SimpleRootSite.ktptUserPrompt, -1, -1); tssVal = bldr.GetString(); // Get information about current selection int cvsli = vwsel.CLevels(false); cvsli--; // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. int ihvoRoot; int tagTextProp; int cpropPrevious; int ichAnchor; int ichEnd; int ihvoEnd; bool fAssocPrev; int ws; ITsTextProps ttp; SelLevInfo[] rgvsli = SelLevInfo.AllTextSelInfo(vwsel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttp); // Prior to the Commit in selection changed which causes this UpdateProp to be called, // earlier selection changed code has expanded the selection (because it is in a user prompt) // to the whole prompt. It is therefore a range selection, and the value of fAssocPrev we got // is useless. We want to make a selection associated with the previous character at the END of // the range. if (frag == (int)CmAnnotation.CmAnnotationTags.kflidComment) { // If the length is zero...we need to suppress replacing the comment with a prompt. if (tssVal.Length == 0) m_hvoSuppressCommentPrompt = hvo; CmIndirectAnnotation ann = new CmIndirectAnnotation(Cache, hvo); if (ann.Comment.GetAlternative(BackTranslationWS).Length == 0) { // Undo needs to unset suppressing the comment prompt. Cache.ActionHandlerAccessor.AddAction(new UndoSuppressCommentPrompt(this, ann)); } // Turn the prompt property off for future typing, too. ITsPropsBldr pb = ttp.GetBldr(); pb.SetIntPropValues(SimpleRootSite.ktptUserPrompt, -1, -1); ann.Comment.SetAlternative(tssVal, BackTranslationWS); rootbox.MakeTextSelection(ihvoRoot, cvsli, rgvsli, (int)CmAnnotation.CmAnnotationTags.kflidComment, cpropPrevious, ichEnd, ichEnd, BackTranslationWS, fAssocPrev, ihvoEnd, pb.GetTextProps(), true); return tssVal; } ReplacePromptUndoAction undoAction = new ReplacePromptUndoAction(hvo, m_cache, m_updatedPrompts); if (m_cache.ActionHandlerAccessor != null) m_cache.ActionHandlerAccessor.AddAction(undoAction); // Mark the user prompt as having been updated - will not show prompt again. // Note: ReplacePromptUndoAction:Undo removes items from the Set. m_updatedPrompts.Add(hvo); // Replace the ITsString in the paragraph or translation // - this destroys the selection because we replace the user prompt. StTxtPara para; CmTranslation trans; ITsTextProps props = StyleUtils.CharStyleTextProps(null, m_wsDefault); if (frag == (int)CmTranslation.CmTranslationTags.kflidTranslation) { trans = new CmTranslation(Cache, hvo); trans.Translation.GetAlternative(m_wsDefault).UnderlyingTsString = tssVal; undoAction.ParaHvo = trans.OwnerHVO; // now set the selection to the end of the text that was just put in. ichAnchor = ichEnd; rootbox.MakeTextSelection(ihvoRoot, cvsli, rgvsli, (int)CmTranslation.CmTranslationTags.kflidTranslation, cpropPrevious, ichAnchor, ichEnd, m_wsDefault, true, ihvoEnd, props, true); } else { para = new StTxtPara(Cache, hvo); para.Contents.UnderlyingTsString = tssVal; undoAction.ParaHvo = hvo; // now set the selection to the end of the text that was just put in. ichAnchor = ichEnd; rootbox.MakeTextSelection(ihvoRoot, cvsli, rgvsli, (int)StTxtPara.StTxtParaTags.kflidContents, cpropPrevious, ichAnchor, ichEnd, m_wsDefault, true, ihvoEnd, props, true); } return tssVal; }
protected override void HandleSelectionChange(IVwRootBox rootb, IVwSelection vwselNew) { CheckDisposed(); if (vwselNew == null) { return; } int cvsli = vwselNew.CLevels(false); // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. cvsli--; if (cvsli == 0) { // No objects in selection: don't allow a selection. m_rootb.DestroySelection(); // Enhance: invoke launcher's selection dialog. return; } ITsString tss; int ichAnchor; int ichEnd; bool fAssocPrev; int hvoObj; int hvoObjEnd; int tag; int ws; vwselNew.TextSelInfo(false, out tss, out ichAnchor, out fAssocPrev, out hvoObj, out tag, out ws); vwselNew.TextSelInfo(true, out tss, out ichEnd, out fAssocPrev, out hvoObjEnd, out tag, out ws); if (hvoObj != hvoObjEnd) { return; } int ihvoRoot; int tagTextProp; int cpropPrevious; int ihvoEnd; ITsTextProps ttp; SelLevInfo[] rgvsli = SelLevInfo.AllTextSelInfo(vwselNew, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttp); Debug.Assert(m_rootb != null); // Create a selection that covers the entire target object. If it differs from // the new selection, we'll install it (which will recurse back to this method). IVwSelection vwselWhole = m_rootb.MakeTextSelInObj(ihvoRoot, cvsli, rgvsli, 0, null, false, false, false, true, false); if (vwselWhole != null) { ITsString tssWhole; int ichAnchorWhole; int ichEndWhole; int hvoObjWhole; int hvoObjEndWhole; bool fAssocPrevWhole; int tagWhole; int wsWhole; vwselWhole.TextSelInfo(false, out tssWhole, out ichAnchorWhole, out fAssocPrevWhole, out hvoObjWhole, out tagWhole, out wsWhole); vwselWhole.TextSelInfo(true, out tssWhole, out ichEndWhole, out fAssocPrevWhole, out hvoObjEndWhole, out tagWhole, out wsWhole); if (hvoObj == hvoObjWhole && hvoObjEnd == hvoObjEndWhole && (ichAnchor != ichAnchorWhole || ichEnd != ichEndWhole)) { // Install it this time! m_rootb.MakeTextSelInObj(ihvoRoot, cvsli, rgvsli, 0, null, false, false, false, true, true); } } }
private void SelectAndScrollToCurrentRecord() { bool fOldForce = BaseVirtualHandler.ForceBulkLoadIfPossible; // Scroll the display to the given record. (See LT-927 for explanation.) try { BaseVirtualHandler.ForceBulkLoadIfPossible = true; // disable "compute-every-time" // Todo JohnT: move IP to specified record. (The following code does this, // but makes a range selection of the entire object instead of an IP.) // Also override HandleSelChange to update current record. RecordClerk clerk = Clerk; IVwRootBox rootb = (m_mainView as IVwRootSite).RootBox; if (rootb != null) { int idx = clerk.CurrentIndex; if (idx < 0) { return; } // Review JohnT: is there a better way to obtain the needed rgvsli[]? IVwSelection sel = rootb.Selection; if (sel == null) { sel = rootb.MakeSimpleSel(true, false, false, true); } int cvsli = sel.CLevels(false) - 1; // Out variables for AllTextSelInfo. int ihvoRoot; int tagTextProp; int cpropPrevious; int ichAnchor; int ichEnd; int ws; bool fAssocPrev; int ihvoEnd; ITsTextProps ttpBogus; SelLevInfo[] rgvsli = SelLevInfo.AllTextSelInfo(sel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); rgvsli[cvsli - 1].ihvo = idx; sel = rootb.MakeTextSelInObj(ihvoRoot, cvsli, rgvsli, 0, null, false, false, false, true, true); if (sel == null) { // If the current selection is in a property that the new selection // lacks, making the selection can fail. If that happens, try again at // a higher level. See LT-6011. int cvsliNew = cvsli - 1; while (sel == null && cvsliNew > 0) { // Shift the SelLevInfo values down one place in the array, getting // rid of the first one. for (int i = 1; i <= cvsliNew; ++i) { rgvsli[i - 1] = rgvsli[i]; } sel = rootb.MakeTextSelInObj(ihvoRoot, cvsliNew, rgvsli, 0, null, false, false, false, true, true); --cvsliNew; } } // TODO: implement and use kssoCenter. (m_mainView as IVwRootSite).ScrollSelectionIntoView(sel, VwScrollSelOpts.kssoDefault); // It's a pity this next step is needed! rootb.Activate(VwSelectionState.vssEnabled); } } catch { // not much we can do to handle errors, but don't let the program die just // because the display hasn't yet been laid out, so selections can't fully be // created and displayed. } finally { BaseVirtualHandler.ForceBulkLoadIfPossible = fOldForce; // reenable "compute-every-time" } }
/// <summary> /// Handles a view selection produced by a click. Return true to suppress normal /// mouse down handling, indicating that an interlinear bundle has been clicked and the Sandbox /// moved. /// </summary> /// <param name="vwselNew"></param> /// <param name="fBundleOnly"></param> /// <param name="fSaveGuess">if true, saves guesses; if false, skips guesses but still saves edits.</param> /// <returns></returns> protected virtual bool HandleClickSelection(IVwSelection vwselNew, bool fBundleOnly, bool fSaveGuess) { if (vwselNew == null) return false; // couldn't select a bundle! // The basic idea is to find the level at which we are displaying the TagAnalysis property. int cvsli = vwselNew.CLevels(false); cvsli--; // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. // Out variables for AllTextSelInfo. int ihvoRoot; int tagTextProp; int cpropPrevious; int ichAnchor; int ichEnd; int ws; bool fAssocPrev; int ihvoEnd; ITsTextProps ttpBogus; // Main array of information retrived from sel that made combo. SelLevInfo[] rgvsli = SelLevInfo.AllTextSelInfo(vwselNew, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); if (tagTextProp == SegmentTags.kflidFreeTranslation || tagTextProp == SegmentTags.kflidLiteralTranslation || tagTextProp == NoteTags.kflidContent) { bool fWasFocusBoxInstalled = IsFocusBoxInstalled; Rect oldSelLoc = GetPrimarySelRect(vwselNew); if (!fBundleOnly) { if (IsFocusBoxInstalled) FocusBox.UpdateRealFromSandbox(null, fSaveGuess, null); TryHideFocusBoxAndUninstall(); } // If the selection resulting from the click is still valid, and we just closed the focus box, go ahead and install it; // continuing to process the click may not produce the intended result, because // removing the focus box can re-arrange things substantially (LT-9220). // (However, if we didn't change anything it is necesary to process it normally, otherwise, dragging // and shift-clicking in the free translation don't work.) if (!vwselNew.IsValid || !fWasFocusBoxInstalled) return false; // We have destroyed a focus box...but we may not have moved the free translation we clicked enough // to cause problems. If not, we'd rather do a normal click, because installing a selection that // the root box doesn't think is from mouse down does not allow dragging. Rect selLoc = GetPrimarySelRect(vwselNew); if (selLoc.top == oldSelLoc.top) return false; //The following line could quite possibly invalidate the selection as in the case where it creates //a translation prompt. vwselNew.Install(); //scroll the current selection into view (don't use vwselNew, it might be invalid now) ScrollSelectionIntoView(this.RootBox.Selection, VwScrollSelOpts.kssoDefault); return true; } // Identify the analysis, and the position in m_rgvsli of the property holding it. // It is also possible that the analysis is the root object. // This is important because although we are currently displaying just an StTxtPara, // eventually it might be part of a higher level structure. We want to be able to // reproduce everything that gets us down to the analysis. int itagAnalysis = -1; for (int i = rgvsli.Length; --i >= 0; ) { if (rgvsli[i].tag == SegmentTags.kflidAnalyses) { itagAnalysis = i; break; } } if (itagAnalysis < 0) { if (!fBundleOnly) { if (IsFocusBoxInstalled) FocusBox.UpdateRealFromSandbox(null, fSaveGuess, null); TryHideFocusBoxAndUninstall(); } return false; // Selection is somewhere we can't handle. } int ianalysis = rgvsli[itagAnalysis].ihvo; Debug.Assert(itagAnalysis < rgvsli.Length - 1); // Need different approach if the analysis is the root. int hvoSeg = rgvsli[itagAnalysis + 1].hvo; var seg = Cache.ServiceLocator.GetObject(hvoSeg) as ISegment; Debug.Assert(seg != null); // If the mouse click lands on a punctuation form, move to the preceding // wordform (if any). See FWR-815. while (seg.AnalysesRS[ianalysis] is IPunctuationForm && ianalysis > 0) --ianalysis; if (ianalysis == 0 && seg.AnalysesRS[0] is IPunctuationForm) { if (!fBundleOnly) TryHideFocusBoxAndUninstall(); return false; } TriggerAnnotationSelected(new AnalysisOccurrence(seg, ianalysis), fSaveGuess); return true; }
protected AnalysisOccurrence GetAnalysisFromSelection(IVwSelection sel) { AnalysisOccurrence result = null; var cvsli = sel.CLevels(false); cvsli--; // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. // Out variables for AllTextSelInfo. int ihvoRoot; int tagTextProp; int cpropPrevious; int ichAnchor; int ichEnd; int ws; bool fAssocPrev; int ihvoEnd; ITsTextProps ttpBogus; // Main array of information retrieved from sel. var rgvsli = SelLevInfo.AllTextSelInfo(sel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttpBogus); if (rgvsli.Length > 1) { // Need to loop backwards until we get down to index 1 or index produces a valid Segment. var i = rgvsli.Length - 1; ISegment seg = null; for (; i > 0; i--) { // get the container for whatever is selected at this level. ICmObject container; if (!m_objRepo.TryGetObject(rgvsli[i].hvo, out container)) { return(null); // may fail, e.g., trying to get bookmark for text just deleted. } seg = container as ISegment; if (seg != null) { break; } } if (seg != null && i > 0) // This checks the case where there is no Segment in the selection at all { // Make a new AnalysisOccurrence var selObject = m_objRepo.GetObject(rgvsli[i - 1].hvo); if (selObject is IAnalysis) { var indexInContainer = rgvsli[i - 1].ihvo; result = new AnalysisOccurrence(seg, indexInContainer); } if (result == null || !result.IsValid) { result = new AnalysisOccurrence(seg, 0); } } else { // TODO: other possibilities?! Debug.Assert(false, "Reached 'other' situation in OccurrenceContainingSelection()."); } } return(result); }