void m_hookup_PropChangedCompleted() { try { if (m_rootb.Site != null) { m_rootb.MakeTextSelection(m_ihvoRoot, m_rgvsli.Length, m_rgvsli, m_tagTextProp, m_cpropPrevious, m_ich, m_ich, m_wsAlt, m_fAssocPrev, -1, m_selProps, true); } } catch (COMException) { try { // Try again making the selection in a prompt m_rootb.MakeTextSelection(m_ihvoRoot, m_rgvsli.Length, m_rgvsli, SimpleRootSite.kTagUserPrompt, m_cpropPrevious, m_ich, m_ich, m_wsAlt, m_fAssocPrev, -1, m_selProps, true); } catch (COMException) { Debug.WriteLine("Failed to make a selection at end of UOW."); // Ignore any errors that happen when trying to set the selection. We really don't // want a program to crash if it fails. } } }
/// <summary> /// Insert "()" into the rootbox at the current selection, then back up the selection /// to be between the parentheses. /// </summary> /// <param name="rootb"></param> public static void InsertOptionalItem(IVwRootBox rootb) { rootb.OnChar('('); rootb.OnChar(')'); // Adjust the selection to be between the parentheses. var vwsel = rootb.Selection; var cvsli = vwsel.CLevels(false); // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. cvsli--; int ihvoRoot; int tagTextProp; int cpropPrevious; int ichAnchor; int ichEnd; int ws; bool fAssocPrev; int ihvoEnd; ITsTextProps ttp; var rgvsli = SelLevInfo.AllTextSelInfo(vwsel, cvsli, out ihvoRoot, out tagTextProp, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd, out ttp); Debug.Assert(ichAnchor == ichEnd); Debug.Assert(ichAnchor > 0); --ichEnd; --ichAnchor; rootb.MakeTextSelection(ihvoRoot, cvsli, rgvsli, tagTextProp, cpropPrevious, ichAnchor, ichEnd, ws, fAssocPrev, ihvoEnd, ttp, true); }
internal static IVwSelection GetSelAtStartOfWs(IVwRootBox rootBox, int flid, int wsIndex, IWritingSystem ws) { try { return rootBox.MakeTextSelection(0, 0, null, flid, wsIndex, 0, 0, (ws == null) ? 0 : ws.Handle, false, -1, null, false); } catch (COMException) { return null; // can fail if we are hiding an empty WS. } }
internal static IVwSelection GetSelAtStartOfWs(IVwRootBox rootBox, int flid, int wsIndex, IWritingSystem ws) { try { return(rootBox.MakeTextSelection(0, 0, null, flid, wsIndex, 0, 0, (ws == null) ? 0 : ws.Handle, false, -1, null, false)); } catch (COMException) { return(null); // can fail if we are hiding an empty WS. } }
/// <summary> /// We consciously don't do the usual destructor stuff. There's nothing useful to do unless properly /// disposed. /// </summary> public void Dispose() { if (m_rootbox != null && m_rootbox.Selection == null && rgvsli != null) { // The likely reason for this is that the backspace deleted the last character in a prompt and we // re-inserted the prompt. Try to re-select the whole prompt. Don't worry if this fails. try { m_rootbox.MakeTextSelection(ihvoRoot, cvsli, rgvsli, SimpleRootSite.kTagUserPrompt, cpropPrevious, 0, 0, ws, false, -1, ttp, true); } catch (Exception) { } } }
/// ------------------------------------------------------------------------------------ /// <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); }
// 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. } } }
/// ------------------------------------------------------------------------------------ /// <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> /// Insert "()" into the rootbox at the current selection, then back up the selection /// to be between the parentheses. /// </summary> /// <param name="rootb"></param> public static void InsertOptionalItem(IVwRootBox rootb) { rootb.OnChar((int)'('); rootb.OnChar((int)')'); // Adjust the selection to be between the parentheses. IVwSelection vwsel = rootb.Selection; int cvsli = vwsel.CLevels(false); // CLevels includes the string property itself, but AllTextSelInfo doesn't need it. cvsli--; int ihvoRoot; int tagTextProp; int cpropPrevious; int ichAnchor; int ichEnd; int ws; bool fAssocPrev; int ihvoEnd; 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); Debug.Assert(ichAnchor == ichEnd); Debug.Assert(ichAnchor > 0); --ichEnd; --ichAnchor; rootb.MakeTextSelection(ihvoRoot, cvsli, rgvsli, tagTextProp, cpropPrevious, ichAnchor, ichEnd, ws, fAssocPrev, ihvoEnd, ttp, true); }
/// ----------------------------------------------------------------------------------- /// <summary> /// Make a range selection based upon our saved selection info. /// NOTE: Installing the selection may trigger side effects that will invalidate the selection. /// Callers should check to make sure the selection is still valid before using it. /// </summary> /// <param name="rootBox"></param> /// <param name="fInstall"></param> /// <exception cref="Exception">throws if unable to make an end selection</exception> /// <returns>a range selection (could become invalid as a side-effect of installing.)</returns> /// ----------------------------------------------------------------------------------- public IVwSelection MakeRangeSelection(IVwRootBox rootBox, bool fInstall) { int iAnchor = 0; int iEnd = 1; if (!m_fEndSet) { // No end information set, so use iAnchor as end iEnd = iAnchor; } if (m_selInfo[iEnd] == null) { m_selInfo[iEnd] = new SelInfo(m_selInfo[iAnchor]); } // This change was proposed in change set 37331 but it's not clear what crash sometimes happens if it's not done. // Apparently it doesn't always crash because some TeDllTests fail if we do this. // Don't make a selection if the property indicates not to: see comment about -2 in InterlinDocForAnalysis.HandleSelectionChange //if (m_selInfo[iAnchor].tagTextProp == -2) // return null; // crashes if allowed to continue // we want to pass fInstall=false to MakeTextSelection so that it doesn't notify // the RootSite of the selection change. IVwSelection vwSelAnchor; try { vwSelAnchor = rootBox.MakeTextSelection( m_selInfo[iAnchor].ihvoRoot, m_selInfo[iAnchor].rgvsli.Length, m_selInfo[iAnchor].rgvsli, m_selInfo[iAnchor].tagTextProp, m_selInfo[iAnchor].cpropPrevious, m_selInfo[iAnchor].ich, m_selInfo[iAnchor].ich, m_selInfo[iAnchor].ws, m_selInfo[iAnchor].fAssocPrev, m_selInfo[iAnchor].ihvoEnd, null, false); } catch (Exception e) { Debug.Assert(m_selInfo[iEnd].rgvsli.Length > 0 || m_selInfo[iAnchor].rgvsli.Length == 0, "Making the anchor selection failed, this is probably an empty editable field."); throw; } IVwSelection vwSelEnd; try { vwSelEnd = rootBox.MakeTextSelection( m_selInfo[iEnd].ihvoRoot, m_selInfo[iEnd].rgvsli.Length, m_selInfo[iEnd].rgvsli, m_selInfo[iEnd].tagTextProp, m_selInfo[iEnd].cpropPrevious, m_selInfo[iEnd].ich, m_selInfo[iEnd].ich, m_selInfo[iEnd].ws, m_selInfo[iEnd].fAssocPrev, m_selInfo[iEnd].ihvoEnd, null, false); } catch (Exception) { Debug.Assert(m_selInfo[iEnd].rgvsli.Length > 0 || m_selInfo[iAnchor].rgvsli.Length == 0, "The anchor has rgvsli but the end does not; since making the end selection failed, this is probably a mistake."); throw; } return rootBox.MakeRangeSelection(vwSelAnchor, vwSelEnd, fInstall); }
/// ------------------------------------------------------------------------------------ /// <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> /// 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> /// Makes a text selection out of the given locationInfo. /// </summary> /// <param name="rootb">The rootb.</param> /// <param name="li">The selection path info</param> /// <param name="fInstall">if true, install the selection</param> /// <returns></returns> public static IVwSelection MakeTextSelection(IVwRootBox rootb, CollectorEnv.LocationInfo li, bool fInstall) { if (rootb == null || li == null) return null; return rootb.MakeTextSelection(0, li.m_location.Length, li.m_location, li.m_tag, li.m_cpropPrev, li.m_ichMin, li.m_ichMin, li.m_ws, false, -1, null, fInstall); }
/// ----------------------------------------------------------------------------------- /// <summary> /// Make a range selection based upon our saved selection info. /// NOTE: Installing the selection may trigger side effects that will invalidate the selection. /// Callers should check to make sure the selection is still valid before using it. /// </summary> /// <param name="rootBox"></param> /// <param name="fInstall"></param> /// <returns>a range selection (could become invalid as a side-effect of installing.)</returns> /// ----------------------------------------------------------------------------------- public IVwSelection MakeRangeSelection(IVwRootBox rootBox, bool fInstall) { int iAnchor = 0; int iEnd = 1; if (!m_fEndSet) { // No end information set, so use iAnchor as end iEnd = iAnchor; } if (m_selInfo[iEnd] == null) { m_selInfo[iEnd] = new SelInfo(m_selInfo[iAnchor]); } // we want to pass fInstall=false to MakeTextSelection so that it doesn't notify // the RootSite of the selection change. IVwSelection vwSelAnchor = rootBox.MakeTextSelection( m_selInfo[iAnchor].ihvoRoot, m_selInfo[iAnchor].rgvsli.Length, m_selInfo[iAnchor].rgvsli, m_selInfo[iAnchor].tagTextProp, m_selInfo[iAnchor].cpropPrevious, m_selInfo[iAnchor].ich, m_selInfo[iAnchor].ich, m_selInfo[iAnchor].ws, m_selInfo[iAnchor].fAssocPrev, m_selInfo[iAnchor].ihvoEnd, null, false); IVwSelection vwSelEnd = rootBox.MakeTextSelection( m_selInfo[iEnd].ihvoRoot, m_selInfo[iEnd].rgvsli.Length, m_selInfo[iEnd].rgvsli, m_selInfo[iEnd].tagTextProp, m_selInfo[iEnd].cpropPrevious, m_selInfo[iEnd].ich, m_selInfo[iEnd].ich, m_selInfo[iEnd].ws, m_selInfo[iEnd].fAssocPrev, m_selInfo[iEnd].ihvoEnd, null, false); return rootBox.MakeRangeSelection(vwSelAnchor, vwSelEnd, fInstall); }
/// <summary> /// Given the GUI control or view ah, find and highlight the text indicated /// via the location (level) path. /// </summary> /// <param name="lpath">Level path array.</param> /// <param name="ah">Accessibility helper from the GUI control or view</param> /// <returns>true if the selected string was retrieved.</returns> private bool selectText(GuiPath lpath, AccessibilityHelper ah) { IVwRootBox rbox = ah.RootBox(); isNotNull(rbox, "view rootbox not found"); IVwSelection sel = null; // returned selection // create a SelLevInfo[] array to the content using the model view levels. int clevels = 0; SelLevInfo[] rgvsli; if (DrillToContent(lpath, out rgvsli, out clevels)) { int ihvoRoot = 0; // first rootbox int tagTextProp = 16002; // kflidStTxtPara_Contents int cpropPrevious = 0; int ichAnchor = m_at; // starting character number int ichEnd = m_at + m_run; // ending character number in rgvsli[0].ihvo or ihvoEnd if it is not -1 int ws = 0; bool fAssocPrev = false; int ihvoEnd = -1; // paragraph # to end at, if it doesn't exist, get unspecified interop error ITsTextProps ttpIns = null; bool fInstall = true; // make it the view's default selection //int iHeight = rbox.get_Height(); int iHeight = rbox.Height; sel = rbox.MakeTextSelection (ihvoRoot, clevels, rgvsli, tagTextProp, cpropPrevious, ichAnchor, ichEnd, ws, fAssocPrev, ihvoEnd, ttpIns, fInstall); isNotNull(sel, "failed to select text"); //areEqual(true, sel.get_IsValid(), "selection is not valid"); areEqual(true, sel.IsValid, "selection is not valid"); ITsTextProps ttp = spyOnSelection(sel); if (ttp != null) { spyOnTextProps(ttp); } } string strSeparator = "|"; ITsString tssFromApp; sel.GetSelectionString(out tssFromApp, strSeparator); ITsStreamWrapper tsw = TsStreamWrapperClass.Create(); //UCOMIStream strm = tsw.get_Stream(); System.Runtime.InteropServices.ComTypes.IStream strm = tsw.Stream; // Copy the string to our address space. ITsStrBldr bldr = TsStrBldrClass.Create(); bldr.ReplaceTsString(0, 0, tssFromApp); ITsString tss = bldr.GetString(); int icchIndent = 2; int iws = 0; bool fWriteObjData = true; //tsw.WriteTssAsXml(tss2, icchIndent, iws, fWriteObjData); //ISilDataAccess da = rbox.get_DataAccess(); ISilDataAccess da = rbox.DataAccess; //ILgWritingSystemFactory wsf = da.get_WritingSystemFactory(); ILgWritingSystemFactory wsf = da.WritingSystemFactory; tss.WriteAsXml(strm, wsf, icchIndent, iws, fWriteObjData); //m_text = tsw.get_Contents(); // XML formatted string m_text = tsw.Contents; // XML formatted string return(m_text != null); }