/// ------------------------------------------------------------------------------------ /// <summary> /// Creates a simulated range selection /// </summary> /// <param name="hvoPara1"></param> /// <param name="hvoPara2"></param> /// <param name="ichAnchor"></param> /// <param name="ichEnd"></param> /// ------------------------------------------------------------------------------------ public void SetupSelectionForParas(int hvoPara1, int hvoPara2, int ichAnchor, int ichEnd) { CheckDisposed(); DynamicMock fakeSelHelper = new DynamicMock(typeof(SelectionHelper)); fakeSelHelper.SetupResult("NumberOfLevels", 1); SelLevInfo[] topInfo = new SelLevInfo[1]; topInfo[0].tag = StTextTags.kflidParagraphs; topInfo[0].hvo = hvoPara1; SelLevInfo[] bottomInfo = new SelLevInfo[1]; bottomInfo[0].tag = StTextTags.kflidParagraphs; bottomInfo[0].hvo = hvoPara2; fakeSelHelper.SetupResult("LevelInfo", topInfo); fakeSelHelper.SetupResult("IchAnchor", ichAnchor); fakeSelHelper.SetupResult("IchEnd", ichEnd); fakeSelHelper.SetupResultForParams("GetLevelInfo", topInfo, SelectionHelper.SelLimitType.Top); fakeSelHelper.SetupResultForParams("GetLevelInfo", topInfo, SelectionHelper.SelLimitType.Anchor); fakeSelHelper.SetupResultForParams("GetLevelInfo", bottomInfo, SelectionHelper.SelLimitType.Bottom); fakeSelHelper.SetupResultForParams("GetLevelInfo", bottomInfo, SelectionHelper.SelLimitType.End); fakeSelHelper.SetupResultForParams("GetIch", ichAnchor, SelectionHelper.SelLimitType.Top); fakeSelHelper.SetupResultForParams("GetIch", ichEnd, SelectionHelper.SelLimitType.Bottom); m_currentSelection = (SelectionHelper)fakeSelHelper.MockInstance; }
/// ----------------------------------------------------------------------------------- /// <summary> /// Make one and hook it up to be called at the appropriate time. /// </summary> /// ----------------------------------------------------------------------------------- public RequestSelectionHelper(IActionHandlerExtensions hookup, IVwRootBox rootb, int ihvoRoot, SelLevInfo[] rgvsli, int tagTextProp, int cpropPrevious, int ich, int wsAlt, bool fAssocPrev, ITsTextProps selProps) { m_hookup = hookup; m_rootb = rootb; m_ihvoRoot = ihvoRoot; m_rgvsli = rgvsli; m_tagTextProp = tagTextProp; m_cpropPrevious = cpropPrevious; m_ich = ich; m_wsAlt = wsAlt; m_fAssocPrev = fAssocPrev; m_selProps = selProps; m_hookup.DoAtEndOfPropChanged(m_hookup_PropChangedCompleted); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Setup the selection in footnote. /// </summary> /// <param name="footnote">The footnote.</param> /// <param name="book">The book.</param> /// <param name="iBook">The 0-based index of the book.</param> /// <param name="ichStart">The 0-based starting character index.</param> /// <param name="ichEnd">The 0-based ending character index.</param> /// ------------------------------------------------------------------------------------ public void SetupSelectionInFootnote(IStFootnote footnote, IScrBook book, int iBook, int ichStart, int ichEnd) { CheckDisposed(); DynamicMock fakeSelHelper = new DynamicMock(typeof(SelectionHelper)); fakeSelHelper.SetupResult("GetTextPropId", StTxtParaTags.kflidContents, typeof(SelectionHelper.SelLimitType)); fakeSelHelper.SetupResult("NumberOfLevels", 3); // Setup the anchor SelLevInfo[] topInfo = new SelLevInfo[3]; IStTxtPara para = footnote[0]; topInfo[0].tag = StTextTags.kflidParagraphs; topInfo[0].ihvo = 0; // only one para per footnote allowed topInfo[0].hvo = para.Hvo; topInfo[1].tag = ScrBookTags.kflidFootnotes; topInfo[1].ihvo = footnote.IndexInOwner; topInfo[1].hvo = footnote.Hvo; topInfo[2].tag = BookFilter.Tag; topInfo[2].ihvo = iBook; topInfo[2].hvo = book.Hvo; // Setup the end SelLevInfo[] bottomInfo = new SelLevInfo[3]; for(int i = 0; i < 3; i++) bottomInfo[i] = topInfo[i]; fakeSelHelper.SetupResult("LevelInfo", topInfo); fakeSelHelper.SetupResult("IchAnchor", ichStart); fakeSelHelper.SetupResult("IchEnd", ichEnd); fakeSelHelper.SetupResultForParams("GetLevelInfo", topInfo, SelectionHelper.SelLimitType.Top); fakeSelHelper.SetupResultForParams("GetLevelInfo", topInfo, SelectionHelper.SelLimitType.Anchor); fakeSelHelper.SetupResultForParams("GetLevelInfo", bottomInfo, SelectionHelper.SelLimitType.Bottom); fakeSelHelper.SetupResultForParams("GetLevelInfo", bottomInfo, SelectionHelper.SelLimitType.End); fakeSelHelper.SetupResultForParams("GetIch", ichStart, SelectionHelper.SelLimitType.Top); fakeSelHelper.SetupResultForParams("GetIch", ichEnd, SelectionHelper.SelLimitType.Bottom); m_currentSelection = (SelectionHelper)fakeSelHelper.MockInstance; }
/// <summary> /// Sets up the tags for the 0 level of a selection of a free translation or note. /// This will be the level "inside" the ones that select the paragraph and segment. /// For a note, we need to select the first note. /// For a free translation, we need to insert the level for the 'self' property /// which the VC inserts to isolate the free translations and make it easier to update them. /// </summary> /// <param name="tagTextProp">The segment or note tag of an annotation to be selected.</param> private SelLevInfo MakeInnerLevelForFreeformSelection(int tagTextProp) { var noteLevel = new SelLevInfo(); noteLevel.ihvo = 0; if (tagTextProp == NoteTags.kflidContent) { noteLevel.tag = SegmentTags.kflidNotes; } else { noteLevel.tag = Cache.MetaDataCacheAccessor.GetFieldId2(CmObjectTags.kClassId, "Self", false); } return noteLevel; }
/// <summary> /// Select the first non-null translation or note in the current segment /// of the current analysis occurance. /// </summary> /// <returns>true if successful, false if there is no real translation or note</returns> internal bool SelectFirstTranslationOrNote() { int ws; int annotationFlid = GetFirstVisibleTranslationOrNoteFlid(SelectedOccurrence.Segment, out ws); if (annotationFlid == 0) return false; var sel = MakeSandboxSel(); int clev = sel.CLevels(true); clev--; // result it returns is one more than what the AllTextSelInfo routine wants. SelLevInfo[] rgvsli; using (ArrayPtr rgvsliTemp = MarshalEx.ArrayToNative<SelLevInfo>(clev)) { int ihvoRoot; int cpropPrevious; int ichAnchor; int ichEnd; int ihvoEnd1; int tag, ws1; bool fAssocPrev; ITsTextProps ttp; sel.AllTextSelInfo(out ihvoRoot, clev, rgvsliTemp, out tag, out cpropPrevious, out ichAnchor, out ichEnd, out ws1, out fAssocPrev, out ihvoEnd1, out ttp); rgvsli = MarshalEx.NativeToArray<SelLevInfo>(rgvsliTemp, clev); } // What non-word "choice" ie., translation text or note is on this line? int tagTextProp = ConvertTranslationOrNoteFlidToSegmentFlid(annotationFlid, SelectedOccurrence.Segment, ws); int levels; SelLevInfo noteLevel = MakeInnerLevelForFreeformSelection(tagTextProp); var vsli = new SelLevInfo[3]; vsli[0] = noteLevel; // note or translation line vsli[1] = rgvsli[0]; // segment vsli[2] = rgvsli[1]; // para int cPropPrevious = 0; // todo: other if not the first WS for tagTextProp TryHideFocusBoxAndUninstall(); RootBox.MakeTextSelection(0, vsli.Length, vsli, tagTextProp, cPropPrevious, 0, 0, 0, false, -1, null, true); Focus(); return true; }
/// <summary> /// Gets the current selection and returns enough data to move the IP. /// </summary> /// <param name="clev">The number of levels of selection range results.</param> /// <param name="rgvsli">The selection range with clev levels of structure.</param> /// <param name="tag">The property of the bottom-level [0] object that is of interest.</param> /// <param name="ichAnchor">The start index of the text selection.</param> /// <param name="ichEnd">The end index of the text selection.</param> /// <param name="ws">Index of the writing system of the selection.</param> /// <returns>true if a selection was made, false if something prevented it.</returns> private bool GetCurrentSelection(out int clev, out SelLevInfo[] rgvsli, out int tag, out int ichAnchor, out int ichEnd, out int ws) { clev = -1; rgvsli = null; tag = -1; ichAnchor = -1; ichEnd = -1; ws = -1; var sel = EditingHelper.RootBoxSelection; if (sel == null) return false; // which "line choice" is active in this segment? if (sel.SelType != VwSelType.kstText || !sel.IsValid || !sel.IsEditable) return false; clev = sel.CLevels(true); ITsTextProps ttp; using (ArrayPtr rgvsliTemp = MarshalEx.ArrayToNative<SelLevInfo>(clev)) { int ihvoRoot; int ihvoEnd1; int cpropPrevious; bool fAssocPrev; sel.AllTextSelInfo(out ihvoRoot, clev, rgvsliTemp, out tag, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd1, out ttp); rgvsli = MarshalEx.NativeToArray<SelLevInfo>(rgvsliTemp, clev); } return true; }
public override void SelectionChanged(IVwRootBox rootb, IVwSelection vwselNew) { CheckDisposed(); if (vwselNew == null) return; bool hasFoc = Focused; base.SelectionChanged(rootb, vwselNew); ITsString tss; int ichAnchor; bool fAssocPrev; int hvoObj; int tag; int ws; // NB: This will be 0 after each call, since the string does // not have alternatives. Ws would be the WS of an alternative, // if there were any. vwselNew.TextSelInfo(false, out tss, out ichAnchor, out fAssocPrev, out hvoObj, out tag, out ws); int ichEnd; int hvoObjEnd; vwselNew.TextSelInfo(true, out tss, out ichEnd, out fAssocPrev, out hvoObjEnd, out tag, out ws); if (hvoObjEnd != hvoObj) { CheckHeight(); return; } if (m_hvoOldSelection > 0 && hvoObj != m_hvoOldSelection) { // Try to validate previously selected string rep. if (m_silCache.get_StringProp(m_hvoOldSelection, kEnvStringRep).Length==0) { // Remove it from the dummy cache, since its length is 0. int limit = m_silCache.get_VecSize(m_rootObj.Hvo, kMainObjEnvironments); for (int i = 0; i < limit; ++i) { if (m_hvoOldSelection == m_silCache.get_VecItem(m_rootObj.Hvo, kMainObjEnvironments, i)) { RemoveFromDummyCache(i); break; } } } else // Validate previously selected string rep. { ValidateStringRep(m_hvoOldSelection); } } if (hvoObj != kDummyPhoneEnvID) { m_hvoOldSelection = hvoObj; CheckHeight(); return; } if (tss.Length == 0) { CheckHeight(); return; } // Create a new object, and recreate a new empty object. Make this part of the Undo // Task with the character we typed. m_silCache.GetActionHandler().ContinueUndoTask(); int count = m_silCache.get_VecSize(m_rootObj.Hvo, kMainObjEnvironments); int hvoNew = InsertNewEnv(count - 1); m_silCache.SetString(hvoNew, kEnvStringRep, tss); m_silCache.SetString(kDummyPhoneEnvID, kEnvStringRep, DummyString); m_silCache.EndUndoTask(); // Refresh m_silCache.PropChanged(null, (int)PropChangeType.kpctNotifyAll, m_rootObj.Hvo, kMainObjEnvironments, count - 1, 2, 1); // Reset selection. SelLevInfo[] rgvsli = new SelLevInfo[1]; rgvsli[0].cpropPrevious = 0; rgvsli[0].tag = kMainObjEnvironments; rgvsli[0].ihvo = count - 1; m_rootb.MakeTextSelection(0, rgvsli.Length, rgvsli, tag, 0, ichAnchor, ichEnd, ws, fAssocPrev, -1, null, true); m_hvoOldSelection = hvoNew; CheckHeight(); }
public IVwSelection MakeSelInObj(int ihvoRoot, int cvsli, SelLevInfo[] _rgvsli, int tag, bool fInstall) { throw new NotImplementedException(); }
public IVwSelection MakeTextSelection(int ihvoRoot, int cvlsi, SelLevInfo[] _rgvsli, int tagTextProp, int cpropPrevious, int ichAnchor, int ichEnd, int ws, bool fAssocPrev, int ihvoEnd, ITsTextProps _ttpIns, bool fInstall) { return new DummyVwSelection(this, ichAnchor, ichEnd); }
protected override SelLevInfo[] GetLevelInfo(int cellId, int cellIndex) { SelLevInfo[] levels = null; switch (cellId) { case AffixRuleFormulaVc.ktagLeftEmpty: case AffixRuleFormulaVc.ktagRightEmpty: break; case MoAffixProcessTags.kflidOutput: if (cellIndex >= 0) { levels = new SelLevInfo[1]; levels[0].tag = cellId; levels[0].ihvo = cellIndex; } break; default: var ctxtOrVar = m_cache.ServiceLocator.GetInstance<IPhContextOrVarRepository>().GetObject(cellId); if (cellIndex < 0 || ctxtOrVar.ClassID != PhSequenceContextTags.kClassId) { levels = new SelLevInfo[1]; levels[0].tag = MoAffixProcessTags.kflidInput; levels[0].ihvo = ctxtOrVar.IndexInOwner; } else { levels = new SelLevInfo[2]; levels[0].tag = PhSequenceContextTags.kflidMembers; levels[0].ihvo = cellIndex; levels[1].tag = MoAffixProcessTags.kflidInput; levels[1].ihvo = ctxtOrVar.IndexInOwner; } break; } return levels; }
/// <summary> /// Reestablish a selection, if possible. /// </summary> public void MakeSel() { if (m_tagSel == -1) return; int clev = 2; // typically two level if (m_tagSel != ktagSbNamedObjName) clev--; // prefix and postfix are one level less embedded SelLevInfo[] rgsli = new SelLevInfo[clev]; // The selection is in the morphemes of the root object rgsli[clev - 1].ihvo = m_ihvoSelMorph; rgsli[clev - 1].tag = ktagSbWordMorphs; if (clev > 1) rgsli[0].tag = ktagSbMorphForm; // leave other slots zero try { m_sandbox.RootBox.MakeTextSelection( m_sandbox.IndexOfCurrentItem, // which root, clev, rgsli, m_tagSel, 0, // no previous occurrence m_ichSelOutput, m_ichSelOutput, m_wsVern, false, // needs to be false here to associate with trailing character // esp. for when the cursor is at the beginning of the morpheme (LT-7773) -1, // end not in different object null, // no special props to use for typing true); // install it. } catch (Exception) { // Ignore anything that goes wrong making a selection. At worst we just don't have one. } }
public void GetParagraphProps() { CheckDisposed(); // we want more paragraphs with different Hvos MakeEnglishParagraphs(); ShowForm(Lng.English, DummyBasicViewVc.DisplayType.kNormal); IVwRootBox rootBox = m_basicView.RootBox; IVwSelection vwsel; int hvoText, tagText, ihvoFirst, ihvoLast; IVwPropertyStore[] vqvps; ITsTextProps[] vqttp; // Test 1: selection in one paragraph rootBox.MakeSimpleSel(false, true, false, true); IVwSelection sel = rootBox.Selection; ITsString tss; int ich, hvoObj, tag, ws; bool fAssocPrev; sel.TextSelInfo(true, out tss, out ich, out fAssocPrev, out hvoObj, out tag, out ws); int clev = sel.CLevels(true); clev--; // result it returns is one more than what the AllTextSelInfo routine wants. int ihvoRoot; int cpropPrevious; int ichAnchor; int ichEnd; int ihvoEnd1; ITsTextProps ttp; using (ArrayPtr rgvsliTemp = MarshalEx.ArrayToNative(clev, typeof(SelLevInfo))) { sel.AllTextSelInfo(out ihvoRoot, clev, rgvsliTemp, out tag, out cpropPrevious, out ichAnchor, out ichEnd, out ws, out fAssocPrev, out ihvoEnd1, out ttp); SelLevInfo[] rgvsli = (SelLevInfo[])MarshalEx.NativeToArray(rgvsliTemp, clev, typeof(SelLevInfo)); int ichInsert = 0; rootBox.MakeTextSelection(ihvoRoot, clev, rgvsli, tag, cpropPrevious, ichInsert, ichInsert + 5, ws, fAssocPrev, ihvoEnd1, ttp, true); bool fRet = m_basicView.GetParagraphProps(out vwsel, out hvoText, out tagText, out vqvps, out ihvoFirst, out ihvoLast, out vqttp); Assert.IsTrue(fRet, "Test 1 "); Assert.AreEqual(ihvoFirst, ihvoLast, "Test 1 "); Assert.AreEqual(1, vqttp.Length, "Test 1 "); // Test 2: selection across two sections SelLevInfo[] rgvsliEnd = new SelLevInfo[clev]; rgvsli.CopyTo(rgvsliEnd, 0); rgvsli[0].ihvo = 0; // first paragraph rgvsli[clev-1].ihvo = 2; // third section rootBox.MakeTextSelInObj(ihvoRoot, clev, rgvsli, clev, rgvsliEnd, false, true, true, true, true); fRet = m_basicView.GetParagraphProps(out vwsel, out hvoText, out tagText, out vqvps, out ihvoFirst, out ihvoLast, out vqttp); Assert.IsFalse(fRet, "Test 2 "); } }
public void LoseFocusToView_RangeSel_FlagSet() { CheckDisposed(); ShowForm(Lng.English, DummyBasicViewVc.DisplayType.kNormal); IVwRootBox rootBox = m_basicView.RootBox; rootBox.Activate(VwSelectionState.vssEnabled); m_basicView.ShowRangeSelAfterLostFocus = true; // Select the first four characters in the first paragraph SelLevInfo[] levelInfo = new SelLevInfo[2]; levelInfo[1].tag = m_flidContainingTexts; levelInfo[1].cpropPrevious = 0; levelInfo[1].ihvo = 0; levelInfo[0].tag = (int)StText.StTextTags.kflidParagraphs; levelInfo[0].cpropPrevious = 0; levelInfo[0].ihvo = 0; rootBox.MakeTextSelection(0, 2, levelInfo, (int)StTxtPara.StTxtParaTags.kflidContents, 0, 0, 3, 0, true, 0, null, true); // Lets pretend we a different view gets the focus (although it's the same) m_basicView.KillFocus(m_basicView); Assert.IsTrue(rootBox.Selection.IsEnabled, "Selection should still be enabled if the ShowRangeSelAfterLostFocus flag is set"); }
public void LoseFocusToNonView_RangeSel() { CheckDisposed(); ShowForm(Lng.English, DummyBasicViewVc.DisplayType.kNormal); IVwRootBox rootBox = m_basicView.RootBox; rootBox.Activate(VwSelectionState.vssEnabled); // Select the first four characters in the first paragraph SelLevInfo[] levelInfo = new SelLevInfo[2]; levelInfo[1].tag = m_flidContainingTexts; levelInfo[1].cpropPrevious = 0; levelInfo[1].ihvo = 0; levelInfo[0].tag = (int)StText.StTextTags.kflidParagraphs; levelInfo[0].cpropPrevious = 0; levelInfo[0].ihvo = 0; rootBox.MakeTextSelection(0, 2, levelInfo, (int)StTxtPara.StTxtParaTags.kflidContents, 0, 0, 3, 0, true, 0, null, true); // We have to set up a form that contains the view and the control that we pretend // gets focus. using (Form parentForm = new Form()) using (Control control = new Control()) { m_basicView.Parent = parentForm; control.Parent = parentForm; // Lets pretend we a non-view gets the focus (although it's the same) m_basicView.KillFocus(control); Assert.IsTrue(rootBox.Selection.IsEnabled, "Selection should still be enabled if non-view window got focus"); } }
public void MergeBTsWhenParasMerge_FromMiddleOfPara1ToMiddleOfPara2_aKey() { CheckDisposed(); ShowForm(Lng.English, DummyBasicViewVc.DisplayType.kNormal); IVwRootBox rootBox = m_basicView.RootBox; // Add a second paragraph to the first text and create some Back Translations on // both paragraphs ScrBook book = new ScrBook(Cache, m_hvoRoot); StText text1 = (StText)book.FootnotesOS[0]; StTxtPara para1 = (StTxtPara)text1.ParagraphsOS[0]; StTxtPara para2 = m_scrInMemoryCache.AddParaToMockedText(text1.Hvo, string.Empty); m_scrInMemoryCache.AddRunToMockedPara(para2, DummyBasicView.kSecondParaEng, m_wsEng); // We'll just re-use our "vernacular" WS for the back translation, for testing purposes. ICmTranslation trans1 = m_inMemoryCache.AddBtToMockedParagraph(para1, m_wsEng); m_inMemoryCache.AddRunToMockedTrans(trans1, m_wsEng, "BT1", null); ICmTranslation trans2 = m_inMemoryCache.AddBtToMockedParagraph(para2, m_wsEng); m_inMemoryCache.AddRunToMockedTrans(trans2, m_wsEng, "BT2", null); Cache.PropChanged(null, PropChangeType.kpctNotifyAll, text1.Hvo, (int)StText.StTextTags.kflidParagraphs, 1, 1, 0); // Make a selection from the end of first paragraph to the beginning of the second. SelLevInfo[] levelInfo = new SelLevInfo[2]; levelInfo[1].tag = m_flidContainingTexts; levelInfo[1].cpropPrevious = 0; levelInfo[1].ihvo = 0; levelInfo[0].tag = (int)StText.StTextTags.kflidParagraphs; levelInfo[0].cpropPrevious = 0; levelInfo[0].ihvo = 0; int ichAnchor = DummyBasicView.kFirstParaEng.Length - 2; int ichEnd = 2; rootBox.MakeTextSelection(0, 2, levelInfo, (int)StTxtPara.StTxtParaTags.kflidContents, 0, ichAnchor, ichEnd, 0, true, 1, null, true); TypeChar('a'); Assert.AreEqual(DummyBasicView.kFirstParaEng.Substring(0, ichAnchor) + "a" + DummyBasicView.kSecondParaEng.Substring(ichEnd), para1.Contents.Text); Assert.AreEqual("BT1 BT2", trans1.Translation.GetAlternative(m_wsEng).Text); }
/// <summary> /// COPIED from INTERLINPRINTVIEW temporarily to (temporarily) preserve Print View functionality. /// </summary> /// <param name="rgvsli"></param> /// <returns></returns> private int FindBaseAnnInSelLevInfo(SelLevInfo[] rgvsli) { for (int i = 0; i < rgvsli.Length; i++) { int hvoAnn = rgvsli[i].hvo; if (hvoAnn > 0 && HvoIsRealBaseAnnotation(hvoAnn)) return hvoAnn; } return 0; }
/// ------------------------------------------------------------------------------------- /// <summary> /// The layout manager is informed by this method that the (primary) layout stream 'lay' /// has determined that references to the objects objectGuids occur on the page. The input /// value of dysAvailHeight indicates how much of the height allocated to 'lay' for this /// page will remain available if the text containing these references is added to the /// page (assuming that adding them does not reduce the space available for 'lay'). /// This is an alternative implementation of AddDependentObjects for the case where /// RootOnEachPage is true. /// </summary> /// <param name="lay">The primary layout stream filling the page</param> /// <param name="vg">The graphics object being used to layout the page</param> /// <param name="hPage">The handle to the page being laid out</param> /// <param name="cguid">Number of elements in objectGuids array</param> /// <param name="objectGuids">Array of GUIDS representing objects to be laid out in a /// separate layout stream</param> /// <param name="fAllowFail">Indicates whether this method can fail (return /// <c>fFailed == true</c>). If this is false, this method should force the requested /// objects to be laid out within the available space, even if it requires omitting or /// truncating some or all of them</param> /// <param name="fFailed">If the available height would become negative (typically /// because the objects must share space with 'lay' and they don't fit in the available /// height), this will be set to true (unless fAllowFail is false).</param> /// <param name="dysAvailHeight">Input value indicates how much of the height allocated /// to 'lay' for this page will remain available if the text containing these references /// is added to the page, assuming that adding them does not reduce the space available /// for 'lay'. The output value indicates how much is left after laying out these /// dependent objects.</param> /// ------------------------------------------------------------------------------------- public virtual void AddDependentObjectsToPageRoot(IVwLayoutStream lay, IVwGraphics vg, int hPage, int cguid, Guid[] objectGuids, bool fAllowFail, out bool fFailed, ref int dysAvailHeight) { int dysAvailableHeight = dysAvailHeight; fFailed = false; int[] rgHvo = new int[cguid]; int i = 0; foreach (Guid guid in objectGuids) { int hvo = m_configurer.GetIdFromGuid(guid); if (hvo != 0) rgHvo[i++] = hvo; // only add the ones we can match. else cguid--; // found unmatched guid } Page page = Publication.FindPage(hPage); if (page.DoingTrialLayout) { page.NoteDependentRoots(rgHvo); // note that we do not need to adjust dysAvailHeight, because in trial mode the // INITIAL height is set to the space available minus the old dependent root // objects view's height. return; } // Collect some information we need IVwLayoutStream dependentStream = page.DependentObjectsRootStream; IVwRootBox dependentRootbox = (IVwRootBox)dependentStream; int hvoRoot = m_configurer.DependentRootHvo; int dependentObjTag = m_configurer.DependentRootTag; int dependentObjFrag = m_configurer.DependentRootFrag; IDependentObjectsVc depObjVc; ISilDataAccess sda = m_configurer.DataAccess; int oldHeight = 0; int startIndex = -1; int endIndex = -1; int prevStartIndex; int prevEndIndex; if (dependentRootbox == null) { // no pre-existing rootbox for this page so create a new one depObjVc = m_configurer.DependentRootVc; dependentStream = VwLayoutStreamClass.Create(); dependentStream.SetManager(this); page.DependentObjectsRootStream = dependentStream; dependentRootbox = (IVwRootBox)dependentStream; dependentRootbox.SetSite(Publication); dependentRootbox.DataAccess = sda; dependentRootbox.SetRootObject(hvoRoot, depObjVc, dependentObjFrag, m_configurer.StyleSheet); // Set up the view constructor to show the correct objects if (cguid > 0) { startIndex = sda.GetObjIndex(hvoRoot, dependentObjTag, rgHvo[0]); endIndex = sda.GetObjIndex(hvoRoot, dependentObjTag, rgHvo[cguid - 1]); Debug.Assert(startIndex >= 0 && endIndex >= 0); } depObjVc.StartingObjIndex = startIndex; depObjVc.EndingObjIndex = endIndex; prevStartIndex = prevEndIndex = -1; } else { // A rootbox was already created for this page, just update what is shown oldHeight = dependentRootbox.Height; IVwViewConstructor vc; IVwStylesheet ss; dependentRootbox.GetRootObject(out hvoRoot, out vc, out dependentObjFrag, out ss); depObjVc = (IDependentObjectsVc)vc; prevStartIndex = depObjVc.StartingObjIndex; prevEndIndex = depObjVc.EndingObjIndex; // Update the view constructor with the new objects if (cguid > 0) { startIndex = sda.GetObjIndex(hvoRoot, dependentObjTag, rgHvo[0]); endIndex = sda.GetObjIndex(hvoRoot, dependentObjTag, rgHvo[cguid - 1]); Debug.Assert(startIndex >= 0 && endIndex >= 0); Debug.Assert(startIndex > depObjVc.EndingObjIndex && endIndex > depObjVc.EndingObjIndex); if (depObjVc.StartingObjIndex == -1) { // Most likely all the shown objects were removed from the view constructor. // We need to make sure we have a valid starting index. depObjVc.StartingObjIndex = startIndex; } depObjVc.EndingObjIndex = endIndex; } } if (startIndex < 0 || endIndex < 0) { fFailed = fAllowFail; return; } // update the rootbox with the new items. try { // propChanged generates a PageBroken notification we need to ignore. m_hPageBeingBuilt = hPage; int count = endIndex - startIndex + 1; dependentRootbox.PropChanged(hvoRoot, dependentObjTag, startIndex, count, count); } finally { m_hPageBeingBuilt = 0; } PublicationControl.SetAccessibleStreamName(dependentStream, "Dependent stream for page " + page.PageNumber); // The actual laying out is probably redundant, but this lets the dependent stream // know what page it's on, which is useful for notifications. With an interface // change we could do this more efficiently, I think. for (int ihvo = startIndex; ihvo <= endIndex; ihvo++) { SelLevInfo[] rgSelLevInfo = new SelLevInfo[1]; rgSelLevInfo[0].tag = dependentObjTag; rgSelLevInfo[0].ihvo = ihvo - depObjVc.StartingObjIndex; dependentStream.LayoutObj(vg, AvailablePageWidthInPrinterPixels, 0, rgSelLevInfo.Length, rgSelLevInfo, hPage); } int newHeight = dependentRootbox.Height; int dysHeightUsed = newHeight - oldHeight; // If this stream is just now being added to the page, need to allow for gap between elements. if (oldHeight == 0) dysHeightUsed += VerticalGapBetweenElements * vg.YUnitsPerInch / MiscUtils.kdzmpInch; if ((dysHeightUsed * m_numberMainStreamColumns) > dysAvailHeight) { // We can't add everything needed for the current chunk (in the main stream), // so we need to fail (if that's permitted), and roll everything back if (fAllowFail) { fFailed = true; // roll back: remove the extra objects. try { int newStartObjIndex = depObjVc.StartingObjIndex; int newEndObjIndex = depObjVc.EndingObjIndex; depObjVc.StartingObjIndex = prevStartIndex; depObjVc.EndingObjIndex = prevEndIndex; int count = endIndex - newStartObjIndex + 1; dependentRootbox.PropChanged(hvoRoot, dependentObjTag, newStartObjIndex, count, count); } finally { m_hPageBeingBuilt = 0; } return; } else dysAvailableHeight = 0; } else { // When we layout with multiple columns, we pretend to have one large // page. But the substreams are still only one column which means // they affect all columns, so we have to multiply the height used // with the number of columns. dysAvailableHeight -= (dysHeightUsed * m_numberMainStreamColumns); } // Now we know all the objects fit (or else we weren't allowed to fail), so // adjust the rectangle occupied by the element. // First time thru, the previous "element" is the bottom page margin. // So far we only have one, but the code here shows vestiges of the loop in the // main AddDependentObjects. int ysTopOfPrevElement = Publication.PageHeightInPrinterPixels - BottomMarginInPrinterPixels; if (newHeight > 0) AddOrAdjustPageElement(page, ysTopOfPrevElement, newHeight, dependentStream, 0); dysAvailHeight = dysAvailableHeight; }
/// ------------------------------------------------------------------------------------ /// <summary> /// If we need to make a selection, but we can't because edits haven't been updated in the /// view, this method requests creation of a selection after the unit of work is complete. /// Specifically, when all PropChanged calls have been made for the UOW. /// The arguments are as for MakeTextSelection, except that we only include the ones /// necessary to specify an insertion point, and of course don't return the selection, /// which typically won't be made until later. The selection made is always installed. /// </summary> /// ------------------------------------------------------------------------------------ public void RequestSelectionAtEndOfUow(IVwRootBox rootb, int ihvoRoot, int cvlsi, SelLevInfo[] rgvsli, int tagTextProp, int cpropPrevious, int ich, int wsAlt, bool fAssocPrev, ITsTextProps selProps) { // Creating one hooks it up; it will free itself when invoked. new RequestSelectionHelper((IActionHandlerExtensions)m_cache.ActionHandlerAccessor, rootb, ihvoRoot, rgvsli, tagTextProp, cpropPrevious, ich, wsAlt, fAssocPrev, selProps); // We don't want to continue using the old, out-of-date selection. rootb.DestroySelection(); }
public IVwSelection MakeTextSelInObj(int ihvoRoot, int cvsli, SelLevInfo[] _rgvsli, int cvsliEnd, SelLevInfo[] _rgvsliEnd, bool fInitial, bool fEdit, bool fRange, bool fWholeObj, bool fInstall) { throw new NotImplementedException(); }
public void UpdateGoToSubItems_EnabledWhenRequiredSelectionIsPresent() { CheckDisposed(); m_mainWnd.m_mockedBookFilter.SetupResult("BookCount", 1); DynamicMock sel = new DynamicMock(typeof(IVwSelection)); DynamicMock selHelper = new DynamicMock(typeof(SelectionHelper)); SelLevInfo[] levInfo = new SelLevInfo[1]; selHelper.SetupResult("LevelInfo", levInfo); selHelper.SetupResult("Selection", sel.MockInstance); m_mainWnd.m_mockedEditingHelper.SetupResult("CurrentSelection", selHelper.MockInstance); Assert.IsTrue(m_mainWnd.UpdateGoToSubItems(m_dummyItemProps, true)); Assert.IsTrue(m_dummyItemProps.Enabled, "Go to Prev/Next subitem should be enabled when there is a selection."); }
/// <summary> /// print root sites are never used for editing, so this routine should never be called. /// </summary> public void RequestSelectionAtEndOfUow(IVwRootBox _rootb, int ihvoRoot, int cvlsi, SelLevInfo[] rgvsli, int tagTextProp, int cpropPrevious, int ich, int wsAlt, bool fAssocPrev, ITsTextProps selProps) { throw new NotImplementedException(); }
public override void SelectionChanged(IVwRootBox rootb, IVwSelection vwselNew) { CheckDisposed(); if (vwselNew == null) return; base.SelectionChanged(rootb, vwselNew); ITsString tss; int ichAnchor; bool fAssocPrev; int hvoObj; int tag; int ws; vwselNew.TextSelInfo(false, out tss, out ichAnchor, out fAssocPrev, out hvoObj, out tag, out ws); int ichEnd; int hvoObjEnd; vwselNew.TextSelInfo(true, out tss, out ichEnd, out fAssocPrev, out hvoObjEnd, out tag, out ws); if (hvoObjEnd != hvoObj) { // Can't do much with a multi-object selection. CheckHeight(); return; } // The next level out in the view should be the entry in the index. int hvoIndex, ihvoEntry, cpropPrevious, tagEntry; IVwPropertyStore vps; vwselNew.PropInfo(false, 1, out hvoIndex, out tagEntry, out ihvoEntry, out cpropPrevious, out vps); // And the next one is the relevant index. int hvoSense, tagIndex, ihvoIndex; vwselNew.PropInfo(false, 2, out hvoSense, out tagIndex, out ihvoIndex, out cpropPrevious, out vps); int count = m_silCache.get_VecSize(hvoIndex, kFlidEntries); int lastEntryHvo = m_silCache.get_VecItem(hvoIndex, kFlidEntries, count - 1); //string oldForm = m_silCache.get_UnicodeProp(m_hvoOldSelection, (int)ReversalIndexEntry.ReversalIndexEntryTags.kflidForm); string oldForm = null; int wsIndex = m_silCache.get_IntProp(hvoIndex, (int)ReversalIndex.ReversalIndexTags.kflidWritingSystem); ITsString tssEntry = m_silCache.get_MultiStringAlt(m_hvoOldSelection, (int)ReversalIndexEntry.ReversalIndexEntryTags.kflidReversalForm, wsIndex); if (tssEntry != null) oldForm = tssEntry.Text; if (m_hvoOldSelection != 0 && hvoObj != m_hvoOldSelection && (oldForm == null || oldForm.Length == 0)) { // Remove the old string from the dummy cache, since its length is 0. for (int i = 0; i < count; ++i) { if (m_hvoOldSelection == m_silCache.get_VecItem(hvoIndex, kFlidEntries, i)) { RemoveFromDummyCache(hvoIndex, i); break; } } } // If it's not the last index in the list, we can just go on editing it. if (hvoObj != lastEntryHvo) { m_hvoOldSelection = hvoObj; CheckHeight(); return; } // Even if it's the last object, if it's empty we don't need to do anything. if (tss.Length == 0) { CheckHeight(); return; } // Create a new object, and recreate a new empty object. count = m_silCache.get_VecSize(hvoIndex, kFlidEntries); // Assign a new dummy ID. m_dummyId--; // Insert it at the end of the list. m_vwCache.CacheReplace(hvoIndex, kFlidEntries, count, count, new int[] {m_dummyId}, 1); Cache.EnableUndo = false; // Things have changed in a way we can't Undo. // Set its 'form' to be an empty string in the appropriate writing system. ITsTextProps props = tss.get_PropertiesAt(0); int nVar; ws = props.GetIntPropValues((int)FwTextPropType.ktptWs, out nVar); //m_vwCache.CacheUnicodeProp(m_dummyId, (int)ReversalIndexEntry.ReversalIndexEntryTags.kflidForm, String.Empty, 0); //m_vwCache.CacheIntProp(m_dummyId, (int)ReversalIndexEntry.ReversalIndexEntryTags.kflidWritingSystem, ws); ITsString tssEmpty = m_tsf.MakeString("", ws); m_vwCache.CacheStringAlt(m_dummyId, (int)ReversalIndexEntry.ReversalIndexEntryTags.kflidReversalForm, ws, tssEmpty); // Refresh m_silCache.PropChanged(null, (int)PropChangeType.kpctNotifyAll, hvoIndex, kFlidEntries, count, 1, 0); // Reset selection. SelLevInfo[] rgvsli = new SelLevInfo[2]; rgvsli[0].cpropPrevious = 0; rgvsli[0].tag = kFlidEntries; rgvsli[0].ihvo = count - 1; rgvsli[1].cpropPrevious = 0; rgvsli[1].tag = kFlidIndices; rgvsli[1].ihvo = ihvoIndex; try { m_rootb.MakeTextSelection(0, rgvsli.Length, rgvsli, tag, 0, ichAnchor, ichEnd, ws, fAssocPrev, -1, null, true); } catch (Exception e) { Debug.WriteLine(e.ToString()); throw; } m_hvoOldSelection = hvoObj; CheckHeight(); }
/// <summary> /// Retrieves the selected objects and data from the selection range. /// </summary> /// <param name="clev">The number of levels of selection range results.</param> /// <param name="rgvsli">The selection range with clev levels of structure.</param> /// <param name="tag">The property of the bottom-level [0] object that is of interest.</param> /// <param name="curParaIndex">The index of the paragraph containing the selected text.</param> /// <param name="curSegIndex">The index of the segment containing the selected text.</param> /// <param name="curNoteIndex">if tag indicates a note, the note index in its segment sequence otherwise -1.</param> /// <param name="curSeg">The selected segment object</param> /// <param name="curNote">The selected note object or null if curNoteIndex is -1.</param> private void GetCurrentTextObjects(int clev, SelLevInfo[] rgvsli, int tag, out int curParaIndex, out int curSegIndex, out int curNoteIndex, out ISegment curSeg, out INote curNote) { curParaIndex = rgvsli[clev - 2].ihvo; var curPara = (IStTxtPara)RootStText.ParagraphsOS[curParaIndex]; Debug.Assert(curPara != null, "Moving from a non-exisiting paragraph in interlinear Doc."); curSegIndex = rgvsli[clev - 3].ihvo; curSeg = curPara.SegmentsOS[curSegIndex]; Debug.Assert(curSeg != null, "Moving from a non-exisiting segment in interlinear Doc."); curNote = null; curNoteIndex = -1; if (tag == NoteTags.kflidContent) { //if clev == 5 then we have both a Free Translation and some number of Notes //otherwise I assume we have only a Free Translation if clev == 4 if (clev == 5) { curNoteIndex = rgvsli[0].ihvo; //if there are multiple Notes the index could be more than 0 curNote = curSeg.NotesOS[curNoteIndex]; } } }
private bool TryGetWficLevelsAndEndLevels(IVwSelection vwselNew, out SelLevInfo[] wficLevels, out SelLevInfo[] endLevels) { endLevels = null; wficLevels = GetWficLevelsFromSelection(vwselNew); if (wficLevels == null) return false; SelLevInfo[] rgvsliEnd = GetOneEndPointOfSelection(vwselNew, true); // wficLevels[0] contains info about the sequence of wfics property. We want the corresponding // level in rgvsliEnd to have the same tag but not necessarily the same ihvo. // All the higher levels should be exactly the same. The loop checks this, and if successful // sets iend to the index of the property correponding to wficLevels[0]. endLevels = null; int iend; if (AreHigherLevelsSameObject(wficLevels, rgvsliEnd, out iend)) { endLevels = wficLevels.Clone() as SelLevInfo[]; endLevels[0] = new SelLevInfo(); // clone is SHALLOW; don't modify element of wficLevels. endLevels[0].ihvo = rgvsliEnd[iend].ihvo; endLevels[0].tag = wficLevels[0].tag; } return endLevels != null; }
public void AddNote(Command command) { IVwSelection sel = MakeSandboxSel(); // If there's no sandbox selection, there may be one in the site itself, perhaps in another // free translation. if (sel == null && RootBox != null) sel = 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 == StTxtParaTags.kflidSegments) { itagSegments = i; break; } } if (itagSegments == -1) return; // Enhance JohnT: throw? disable command? Give an error? int hvoSeg = rgvsli[itagSegments].hvo; var seg = Cache.ServiceLocator.GetObject(hvoSeg) as ISegment; UndoableUnitOfWorkHelper.Do(command.UndoText, command.RedoText, Cache.ActionHandlerAccessor, () => { var note = Cache.ServiceLocator.GetInstance<INoteFactory>().Create(); seg.NotesOS.Add(note); }); TryHideFocusBoxAndUninstall(); if (m_vc.LineChoices.IndexOf(InterlinLineChoices.kflidNote) < 0) { m_vc.LineChoices.Add(InterlinLineChoices.kflidNote); PersistAndDisplayChangedLineChoices(); } // Now try to make a new selection in the note we just made. // The elements of rgvsli from itagSegments onwards form a path to the segment. // In the segment we want the note propery, specifically the new one we just made. // We want to select at the start of it. // LT-12613: We're adding an extra segment here: SelLevInfo[] rgvsliNew = new SelLevInfo[rgvsli.Length - itagSegments + 2]; for (int i = 2; i < rgvsliNew.Length; i++) rgvsliNew[i] = rgvsli[i + itagSegments - 2]; rgvsliNew[0].ihvo = seg.NotesOS.Count - 1; rgvsliNew[0].tag = SegmentTags.kflidNotes; rgvsliNew[0].cpropPrevious = 0; // LT-12613: Define extra segment here: rgvsliNew[1].ihvo = 0; rgvsliNew[1].tag = Cache.MetaDataCacheAccessor.GetFieldId2(CmObjectTags.kClassId, "Self", false); rgvsliNew[1].cpropPrevious = 0; RootBox.MakeTextSelInObj(0, rgvsliNew.Length, rgvsliNew, 0, null, true, true, false, false, true); // Don't steal the focus from another window. See FWR-1795. if (ParentForm == Form.ActiveForm) Focus(); // So we can actually see the selection we just made. }
/// <summary> /// Updates the list of selected wfics as well as the current StTxtPara. /// </summary> /// <param name="wficLevels">The wfic levels.</param> /// <param name="iend">The iend.</param> private List<int> GetSelectedWfics(SelLevInfo[] wficLevels, int iend) { int hvoSegment = wficLevels[1].hvo; int flidWfics = wficLevels[0].tag; int ianchor = wficLevels[0].ihvo; // These two lines are in case the user selects "backwards" int first = Math.Min(ianchor, iend); int last = Math.Max(ianchor, iend); List<int> selectedWfics = new List<int>(); for (int i = first; i <= last; i++) selectedWfics.Add(Cache.GetVectorItem(hvoSegment, flidWfics, i)); return selectedWfics; }
/// <summary> /// Return the first non-null translation or note selection in the specified segment. /// The segment does not need to be the current occurance. /// </summary> /// <param name="segment">A valid segment.</param> /// <returns>The selection or null if there is no real translation or note.</returns> internal IVwSelection SelectFirstTranslationOrNote(ISegment segment) { if (segment == null) return null; int ws; int annotationFlid = GetFirstVisibleTranslationOrNoteFlid(segment, out ws); if (annotationFlid == 0) return null; int tagTextProp = ConvertTranslationOrNoteFlidToSegmentFlid(annotationFlid, segment, ws); SelLevInfo noteLevel = MakeInnerLevelForFreeformSelection(tagTextProp); // notes and translation lines have 3 levels: 2:para, 1:seg, 0:content or self property var vsli = new SelLevInfo[3]; vsli[0] = noteLevel; // note or translation line vsli[1].ihvo = segment.IndexInOwner; // specifies where segment is in para vsli[1].tag = StTxtParaTags.kflidSegments; vsli[2].ihvo = segment.Paragraph.IndexInOwner; // specifies where para is in IStText. vsli[2].tag = StTextTags.kflidParagraphs; int cPropPrevious = 0; // todo: other if not the first WS for tagTextProp var sel = RootBox.MakeTextSelection(0, vsli.Length, vsli, tagTextProp, cPropPrevious, 0, 0, 0, false, 0, null, true); Focus(); TryHideFocusBoxAndUninstall(); return sel; }
private static SelLevInfo[] GetWficLevelsFromSelLevInfo(SelLevInfo[] rgvsli) { if (rgvsli == null) return null; int itagWfic = GetWfiAnalysisIndexInSelLevInfoArray(rgvsli) + 1; if (itagWfic <= 0) return null; SelLevInfo[] result = new SelLevInfo[rgvsli.Length - itagWfic]; Array.Copy(rgvsli, itagWfic, result, 0, rgvsli.Length - itagWfic); return result; }
/// <summary> /// Overridden for subclasses needing a Sandbox. /// </summary> /// <param name="rgvsli"></param> /// <returns></returns> protected override IVwSelection MakeWordformSelection(SelLevInfo[] rgvsli) { // top prop is atomic, leave index 0. Specifies displaying the contents of the Text. IVwSelection sel; try { // This is fine for InterlinDocForAnalysis, since it treats the area that the sandbox // will fill as a picture. Not so good for panes (see above). sel = RootBox.MakeSelInObj(0, rgvsli.Length, rgvsli, 0, false); } catch (Exception e) { Debug.WriteLine(e.StackTrace); return null; } return sel; }
private static bool AreHigherLevelsSameObject(SelLevInfo[] wficLevels, SelLevInfo[] rgvsliEnd, out int iend) { iend = rgvsliEnd.Length - 1; for (int ianchor = wficLevels.Length - 1; ianchor > 0 && iend >= 0; ianchor--, iend--) { if (rgvsliEnd[iend].tag != wficLevels[ianchor].tag) return false; if (rgvsliEnd[iend].ihvo != wficLevels[ianchor].ihvo) return false; } if (iend < 0) return false; // not enough levels in the end selection, very unlikely. if (wficLevels[0].tag != rgvsliEnd[iend].tag) return false; return true; }