protected override bool OnRightMouseUp(Point pt, Rectangle rcSrcRoot, Rectangle rcDstRoot) { IVwSelection sel = RootBox.MakeSelAt(pt.X, pt.Y, rcSrcRoot, rcDstRoot, false); TextSelInfo tsi = new TextSelInfo(sel); return HandleRightClickOnObject(tsi.Hvo(false)); }
/// <summary> /// Create one. /// </summary> /// <param name="owner"></param> /// <param name="sda"></param> /// <param name="site"></param> /// <param name="updateDescription"></param> /// <param name="fTurnOnMonitor">if true, start monitoring. if false, suspend/disable monitoring.</param> /// <param name="fSuppressRecordingPriorSelection">True for operations (currently only ReplaceAll) /// where we do not want to record the prior selection. This prevents calling editinghelper.OnAboutToEdit, /// which therefore doesn't save info about the current selection. The current actual effect /// is to suppress the work of the AnnotationAdjuster for the selected paragraphs.</param> public DataUpdateMonitor(Control owner, ISilDataAccess sda, IVwRootSite site, string updateDescription, bool fTurnOnMonitor, bool fSuppressRecordingPriorSelection) { // DataUpdateMonitor may be nested, so make sure we're not already monitoring the site. m_fTurnOnMonitor = fTurnOnMonitor && (site == null || !s_sitesMonitoring.Contains(site)); if (!m_fTurnOnMonitor) { return; } // register this site as being monitored. if (site != null) { s_sitesMonitoring.Add(site); } Debug.Assert(sda != null); if (s_UpdateSemaphores.ContainsKey(sda)) { UpdateSemaphore semaphore = s_UpdateSemaphores[sda]; if (semaphore.fDataUpdateInProgress) { throw new Exception("Concurrent access on Database detected"); } // Set ((static semaphore) members) for this data update semaphore.fDataUpdateInProgress = true; semaphore.sDescr = updateDescription; } else { s_UpdateSemaphores[sda] = new UpdateSemaphore(true, updateDescription); } m_Owner = owner; m_sda = sda; m_rootSite = site; if (m_rootSite != null) { m_editingHelper = ((IRootSite)m_rootSite).EditingHelper; } // store original selection info. // Note, some of its internals are computed from the actual selection // which can get changed during the life of DataUpdateMonitor. // But its properties and Hvo(fEndPoint) should remain the same. if (m_editingHelper != null && !fSuppressRecordingPriorSelection) { m_tsi = new TextSelInfo(m_editingHelper.EditedRootBox); m_editingHelper.OnAboutToEdit(); } // Set wait cursor if (owner != null) { m_oldCursor = owner.Cursor; owner.Cursor = Cursors.WaitCursor; } }
private void EnsureSyncText() { if (m_selHelper != null && m_selHelper.Selection != null && m_selHelper.Selection.RootBox != null) { TextSelInfo tsi = new TextSelInfo(m_selHelper.Selection); m_selHelper.RootSite.RootBox.PropChanged(tsi.HvoAnchor, tsi.TagAnchor, 0, 0, 0); if (tsi.Hvo(false) != tsi.Hvo(true)) { m_selHelper.RootSite.RootBox.PropChanged(tsi.Hvo(true), tsi.Tag(true), 0, 0, 0); } } }
private void OnShowInReversalIndex(object sender, EventArgs e) { TextSelInfo tsi = new TextSelInfo(m_rootb); int hvo = tsi.HvoAnchor; if (hvo < 0) hvo = ConvertDummiesToReal(hvo); if (hvo == 0) return; // If the entry is a subentry, we have to find the main entry owned directly by // the reversal index. Otherwise, the jump would go to the first entry in the // index. FdoCache cache = Cache; IReversalIndexEntry rie = ReversalIndexEntry.CreateFromDBObject(cache, hvo); hvo = rie.MainEntry.Hvo; m_mediator.PostMessage("FollowLink", SIL.FieldWorks.FdoUi.FwLink.Create("reversalToolEditComplete", cache.GetGuidFromId(hvo), cache.ServerName, cache.DatabaseName)); }
protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); if (e.Button == MouseButtons.Left && (ModifierKeys & Keys.Control) == Keys.Control) { // Control-click: take the first jump-to-tool command from the right-click menu for this location. // Create a selection where we right clicked IVwSelection sel = GetSelectionAtPoint(new Point(e.X, e.Y), false); TextSelInfo tsi = new TextSelInfo(sel); int hvoTarget = tsi.Hvo(false); // May be (for example) dummy ID used for type-ahead object in reference vector list. if (hvoTarget == 0 || !Cache.ServiceLocator.IsValidObjectId(hvoTarget)) return; using (ReferenceBaseUi ui = GetCmObjectUiForRightClickMenu(hvoTarget)) { ui.HandleCtrlClick(Mediator, this); } } }
internal string BuildCurrentMorphsString(IVwSelection sel) { CheckDisposed(); int ichSel = -1; int hvoObj = 0; int tag = 0; int ws = 0; if (sel != null) { TextSelInfo selInfo = new TextSelInfo(sel); ws = selInfo.WsAltAnchor; ichSel = selInfo.IchAnchor; hvoObj = selInfo.HvoAnchor; tag = selInfo.TagAnchor; } // for now, we'll just configure getting the string for the primary morpheme line. ws = this.VernWsForPrimaryMorphemeLine; m_ichSel = -1; ITsStrBldr builder = TsStrBldrClass.Create(); ITsString space = TsStringUtils.MakeTss(" ", ws); ISilDataAccess sda = m_sandbox.Caches.DataAccess; ITsString tssWordform = m_sandbox.SbWordForm(ws); // we're dealing with a phrase if there are spaces in the word. bool fBaseWordIsPhrase = SandboxBase.IsPhrase(tssWordform.Text); int cmorphs = m_sda.get_VecSize(m_hvoSbWord, SandboxBase.ktagSbWordMorphs); for (int imorph = 0; imorph < cmorphs; ++imorph) { int hvoMorph = m_sda.get_VecItem(m_hvoSbWord, SandboxBase.ktagSbWordMorphs, imorph); if (imorph != 0) { builder.ReplaceTsString(builder.Length, builder.Length, space); // add a second space to separate morphs in a phrase. if (fBaseWordIsPhrase) builder.ReplaceTsString(builder.Length, builder.Length, space); } int hvoMorphForm = sda.get_ObjectProp(hvoMorph, SandboxBase.ktagSbMorphForm); if (hvoMorph == hvoObj && tag == SandboxBase.ktagSbMorphPrefix) m_ichSel = builder.Length + ichSel; builder.ReplaceTsString(builder.Length, builder.Length, sda.get_StringProp(hvoMorph, SandboxBase.ktagSbMorphPrefix)); if (hvoMorphForm == hvoObj && tag == SandboxBase.ktagSbNamedObjName) m_ichSel = builder.Length + ichSel; builder.ReplaceTsString(builder.Length, builder.Length, sda.get_MultiStringAlt(hvoMorphForm, SandboxBase.ktagSbNamedObjName, ws)); if (hvoMorph == hvoObj && tag == SandboxBase.ktagSbMorphPostfix) m_ichSel = builder.Length + ichSel; builder.ReplaceTsString(builder.Length, builder.Length, sda.get_StringProp(hvoMorph, SandboxBase.ktagSbMorphPostfix)); } if (cmorphs == 0) { if (m_hvoSbWord == hvoObj && tag == SandboxBase.ktagMissingMorphs) m_ichSel = ichSel; m_morphString = SandboxBase.InterlinComboHandler.StrFromTss(tssWordform); } else { m_morphString = SandboxBase.InterlinComboHandler.StrFromTss(builder.GetString()); } return m_morphString; }
protected virtual void UndoReplaceSegmentBreakwithNonSegmentBreak(TextSelInfo tsiBeforeIns2) { m_rtp.OnUndo(); m_rtp.ValidateUndoRedo(tsiBeforeIns2); }
protected virtual void RedoReplaceSegmentBreakWithNonSegmentBreak(TextSelInfo tsiAfterIns2) { m_rtp.OnRedo(); m_rtp.ValidateUndoRedo(tsiAfterIns2); }
virtual protected void RedoInsertSegmentBreakAfter1stTwfic(TextSelInfo tsiBeforeBackspace) { m_rtp.OnRedo(); m_rtp.ValidateUndoRedo(tsiBeforeBackspace); }
internal void ValidateDeletedState(string del, TextSelInfo tsiInitial) { ValidateDeletedState(del, tsiInitial, EditAction.Delete); }
internal void ValidateInsertedState(string ins, TextSelInfo tsiInitial) { int ichInsertionPointInitial = Math.Min(tsiInitial.IchAnchor, tsiInitial.IchEnd); TextSelInfo tsiAfterEdit = this.CurrentSelectionInfo; Assert.AreEqual(tsiInitial.AnchorText.Length + ins.Length, tsiAfterEdit.AnchorText.Length); // check our cursor has advanced Assert.AreEqual(ichInsertionPointInitial + ins.Length, tsiAfterEdit.IchAnchor); Assert.AreEqual(ins, tsiAfterEdit.AnchorText.Substring(ichInsertionPointInitial, ins.Length)); // now validate against expected annotations. ValidateStTextAnnotations(tsiInitial.HvoAnchor); }
private void OnKeyDownAndPress(Keys key, out TextSelInfo tsiBeforeEdit) { using (new StateTransitionHelper(this, m_expectedTextAnnotationsDefnsAfterUndo, m_expectedTextAnnotationsDefnsAfterEdits)) { tsiBeforeEdit = this.CurrentSelectionInfo; HandleKeyDownAndKeyPress(key); } }
internal void PasteFromClipboard(out TextSelInfo tsiBeforeEdit) { using (new StateTransitionHelper(this, m_expectedTextAnnotationsDefnsAfterUndo, m_expectedTextAnnotationsDefnsAfterEdits)) { tsiBeforeEdit = this.CurrentSelectionInfo; EditingHelper.PasteClipboard(true); } }
internal ParagraphBuilder GetParagraphBuilder(TextSelInfo tsi) { return GetParagraphBuilder(tsi.HvoAnchor); }
internal void OnRedo(out TextSelInfo tsiBeforeRedo, out UndoResult ures) { using (new StateTransitionHelper(this, m_expectedTextAnnotationsDefnsAfterUndo, m_expectedTextAnnotationsDefnsAfterRedo)) { tsiBeforeRedo = this.CurrentSelectionInfo; Cache.Redo(out ures); if (ures == UndoResult.kuresRefresh) ResyncAllParaContents(); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Executes in two distinct scenarios. /// 1. If disposing is true, the method has been called directly /// or indirectly by a user's code via the Dispose method. /// Both managed and unmanaged resources can be disposed. /// 2. If disposing is false, the method has been called by the /// runtime from inside the finalizer and you should not reference (access) /// other managed objects, as they already have been garbage collected. /// Only unmanaged resources can be disposed. /// </summary> /// <param name="disposing">if set to <c>true</c> [disposing].</param> /// <remarks> /// If any exceptions are thrown, that is fine. /// If the method is being done in a finalizer, it will be ignored. /// If it is thrown by client code calling Dispose, /// it needs to be handled by fixing the bug. /// If subclasses override this method, they should call the base implementation. /// </remarks> /// ------------------------------------------------------------------------------------ protected virtual void Dispose(bool disposing) { //Debug.WriteLineIf(!disposing, "****************** " + GetType().Name + " 'disposing' is false. ******************"); // Must not be run more than once. if (m_isDisposed) { return; } if (disposing && m_fTurnOnMonitor) { try { // Dispose managed resources here. if (m_sda != null) { UpdateSemaphore semaphore = s_UpdateSemaphores[m_sda]; Debug.Assert(semaphore.fDataUpdateInProgress); // Remember selection so that we can try to reconstruct it after the PropChangeds SelectionHelper selection = SelectionHelper.Create(m_rootSite); TextSelInfo tsiAfterEdit = null; if (selection != null) { tsiAfterEdit = new TextSelInfo(selection.Selection); } bool fAdjustedChangeInfo = false; foreach (VwChangeInfo changeInfo in semaphore.changeInfoQueue) { int ivIns = changeInfo.ivIns; int cvDel = changeInfo.cvDel; int cvIns = changeInfo.cvIns; // Note: m_sda.MetaDataCache increments an internal com object // ref count that may not get cleared until you do // Marshal.FinalReleaseComObject on it. if it doesn't get cleared // it may hang tests. IFwMetaDataCache mdc = m_sda.MetaDataCache; if (!fAdjustedChangeInfo && mdc != null && tsiAfterEdit != null && m_editingHelper != null && m_editingHelper.MonitorTextEdits) { // if the selection-edit resulted in keeping the cursor in the same paragraph // we may need to do some more adjustments because views code // calculates VwChangeInfo based upon a string comparison, which does not // accurately tell us where the string was actually changed if the inserted // characters match those character positions in the original string. // For example changing "this is the old text" by inserting "this is the new text, but " // at the beginning results in the string "this is the old text, but this is the new text" // In that example the views code StringCompare would say ivIns started at "old text" // rather than the beginning of the string, since "this is the " matches the old string. // The first condition prevents our trying to make these adjustments when we have a multi-para // (end-before-anchor) selection. if (m_tsi.Hvo(true) == m_tsi.Hvo(false) && m_tsi.HvoAnchor == tsiAfterEdit.HvoAnchor && m_tsi.HvoAnchor == changeInfo.hvo && m_tsi.TagAnchor == changeInfo.tag) { // Our insertion point can be at the beginning or end of the range. int ichInsertionPointOrig = Math.Min(m_tsi.IchAnchor, m_tsi.IchEnd); // we may need to adjust ivIns, but not for MultiStrings, since // ivIns in that case is a ws, not an offset. int flidtype = mdc.GetFieldType((uint)changeInfo.tag); if (flidtype == (int)CellarModuleDefns.kcptBigString || flidtype == (int)CellarModuleDefns.kcptString) { // if the anchor has moved back after a delete, use it as a starting point if (!m_tsi.IsRange && cvDel > 0 && ivIns < m_tsi.IchAnchor) { if (ivIns + cvDel == m_tsi.IchAnchor) { // user did backspace from insertion point, so effectively // move the IP back the number of characters deleted. ivIns = Math.Max(m_tsi.IchAnchor - cvDel, 0); } // ctrl-del can also cause this, but in that case, characters // after the IP may have been deleted, too. Seems best not to try to adjust. } else { // use the original IP, since changeInfo uses CompareStrings // to calculate it, and that can be wrong when pasted string has // characters that coincidentally match the original string. ivIns = ichInsertionPointOrig; } } // if the initial selection is a range selection in the same paragraph // set the number of deleted characters to be the difference between // the begin and end offsets. if (m_tsi.HvoAnchor == m_tsi.Hvo(true) && m_tsi.IsRange) { cvDel = Math.Abs(m_tsi.IchEnd - m_tsi.IchAnchor); } // Review: do we expect this string to be Normalized already? // Review: should we do nothing if the pasted string contains newline, or set cvIns to the // length of the text after the last newline, or what?? if (InsertedTss != null && InsertedTss.Text != null && InsertedTss.Text.IndexOf(Environment.NewLine) == -1) { cvIns = InsertedTss.Length; } // indicate we've adjusted the changeInfo for the next PropChange. // this should be done only once per edit action. fAdjustedChangeInfo = true; } } m_sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, changeInfo.hvo, changeInfo.tag, ivIns, cvIns, cvDel); } semaphore.fDataUpdateInProgress = false; semaphore.sDescr = string.Empty; semaphore.changeInfoQueue.Clear(); // It is possible that the PropChanged caused a regenerate of the view. This // turned our selection invalid. Try to recover it. if (selection != null && !selection.IsValid) { selection.SetSelection(false); } // This needs to be called after setting the selection. It can cause // AnnotationAdjuster.EndKeyPressed() to be called which expects a // selection to be set. if (m_editingHelper != null) { m_editingHelper.OnFinishedEdit(); } // It is possible that OnFinishedEdit() caused a regenerate of the view. This // turned our selection invalid. Try to recover it. if (selection != null && !selection.IsValid) { selection.SetSelection(false); } } } finally { // In case anything goes wrong, if we possibly can, do this anyway, other wise the pane // may be more-or-less permanently locked. if (m_rootSite != null) { s_sitesMonitoring.Remove(m_rootSite); } // end Wait Cursor // Since it needs m_Owner, this must be done when 'disposing' is true, // as that is a disposable object, which may be gone in // Finalizer mode. if (m_Owner != null) { m_Owner.Cursor = m_oldCursor; } } } // Dispose unmanaged resources here, whether disposing is true or false. m_sda = null; m_Owner = null; m_rootSite = null; m_oldCursor = null; m_tsi = null; m_tssIns = null; m_isDisposed = true; }
virtual protected void DeleteSegmentBreakAfter1stTwfic(StTxtPara para0, out TextSelInfo tsiBeforeBackspace, out TextSelInfo tsiAfterBackspace) { m_rtp.OnBackspace(out tsiBeforeBackspace); tsiAfterBackspace = m_rtp.CurrentSelectionInfo; m_rtp.ValidateBackspaceState(".", tsiBeforeBackspace); m_rtp.ValidateParagraphContents(para0, ParagraphContents[0]); }
internal void ValidateDeletedState(string del, TextSelInfo tsiInitial, EditAction action) { int ichInsertionPointInitial = Math.Min(tsiInitial.IchAnchor, tsiInitial.IchEnd); TextSelInfo tsiAfterEdit = this.CurrentSelectionInfo; Assert.AreEqual(tsiInitial.AnchorLength - del.Length, tsiAfterEdit.AnchorLength); if (action == EditAction.Backspace) { // check our cursor has retreated Assert.AreEqual(ichInsertionPointInitial - del.Length, tsiAfterEdit.IchAnchor); } else if (action == EditAction.Delete) { // check our cursor is in the same location Assert.AreEqual(ichInsertionPointInitial, tsiAfterEdit.IchAnchor, "Expected same cursor position on a delete."); } // now validate against expected annotations. ValidateStTextAnnotations(tsiInitial.HvoAnchor); }
virtual protected void RedoDeleteSegmentBreakAfter1stTwfic(TextSelInfo tsiAfterBackspace) { m_rtp.OnRedo(); m_rtp.ValidateUndoRedo(tsiAfterBackspace); }
internal void ValidateReplacedState(string del, string ins, TextSelInfo tsiInitial) { int ichInsertionPointInitial = Math.Min(tsiInitial.IchAnchor, tsiInitial.IchEnd); TextSelInfo tsiAfterEdit = this.CurrentSelectionInfo; // calculate and validate the expected length of the edited text Assert.AreEqual(tsiInitial.AnchorLength - del.Length + ins.Length, tsiAfterEdit.AnchorLength); // validate our expected cursor is at the end of the pasted text. Assert.AreEqual(ichInsertionPointInitial + ins.Length, tsiAfterEdit.IchAnchor); string actualIns = tsiAfterEdit.AnchorLength > 0 ? tsiAfterEdit.AnchorText.Substring(ichInsertionPointInitial, ins.Length) : ""; Assert.AreEqual(ins, actualIns); // now validate against expected annotations. ValidateStTextAnnotations(tsiInitial.HvoAnchor); }
protected virtual void UndoReplaceSegBreakWithAnotherSegBreak(TextSelInfo tsiBeforeIns1) { m_rtp.OnUndo(); m_rtp.ValidateUndoRedo(tsiBeforeIns1); }
internal void ValidateUndoRedo(UndoResult uresExpected, UndoResult uresActual, TextSelInfo tsiExpectedAfterUndoRedo) { Assert.AreEqual(uresExpected, uresActual, "UndoResult"); ValidateUndoRedo(tsiExpectedAfterUndoRedo); }
protected virtual void ReplaceSegBreakWithAnotherSegBreak(StTxtPara para0, out TextSelInfo tsiBeforeIns1, out TextSelInfo tsiAfterIns1) { int ichMin = para0.Contents.Text.IndexOf("."); m_rtp.SetSelection(para0, ichMin, ichMin + 1); m_rtp.OnInsert("?", out tsiBeforeIns1); tsiAfterIns1 = m_rtp.CurrentSelectionInfo; m_rtp.ValidateReplacedState(".", "?", tsiBeforeIns1); string sAfterReplace1 = "xxxpus xxxyalola xxxnihimbilira? xxxnihimbilira xxxpus xxxyalola. xxxhesyla xxxnihimbilira."; m_rtp.ValidateParagraphContents(para0, sAfterReplace1); }
internal void ValidateUndoRedo(TextSelInfo tsiExpectedAfterUndoRedo) { TextSelInfo tsiAfterEdit = ValidateUndoRedoRaw(tsiExpectedAfterUndoRedo); ValidateStTextAnnotations(tsiAfterEdit.HvoAnchor); }
private void ReplaceVerseText(StTxtPara para, int bcvToReplace, string replacement, out TextSelInfo tsiBeforeEdit, out TextSelInfo tsiAfterEdit) { (m_draftView.EditingHelper as TeEditingHelper).SelectVerseText((new ScrReference(bcvToReplace, Paratext.ScrVers.English)), null); tsiBeforeEdit = new TextSelInfo(m_draftView.RootBox); // para.Contents.Text.IndexOf("Verse three does not have the key term in it.") int ichMin = tsiBeforeEdit.IchAnchor; int ichLim = tsiBeforeEdit.IchEnd; m_scrInMemoryCache.ModifyRunAt(para, ichMin, ichLim, replacement); // not sure if this is necessary, since we aren't altering reference structure, just their locations. IScrSection section = (para.Owner as CmObject).Owner as IScrSection; section.AdjustReferences(); (m_draftView.EditingHelper as TeEditingHelper).SelectVerseText((new ScrReference(bcvToReplace, Paratext.ScrVers.English)), null); tsiAfterEdit = new TextSelInfo(m_draftView.RootBox); }
internal TextSelInfo ValidateUndoRedoRaw(TextSelInfo tsiExpectedAfterUndoRedo) { TextSelInfo tsiAfterEdit = this.CurrentSelectionInfo; Assert.AreEqual(tsiExpectedAfterUndoRedo.AnchorLength, tsiAfterEdit.AnchorLength); Assert.AreEqual(tsiExpectedAfterUndoRedo.IchAnchor, tsiAfterEdit.IchAnchor); Assert.AreEqual(tsiExpectedAfterUndoRedo.IchEnd, tsiAfterEdit.IchEnd); Assert.AreEqual(tsiExpectedAfterUndoRedo.AnchorText, tsiAfterEdit.AnchorText); Assert.AreEqual(tsiExpectedAfterUndoRedo.HvoAnchor, tsiAfterEdit.HvoAnchor); return tsiAfterEdit; }
private void EnsureSyncText() { if (m_selHelper != null && m_selHelper.Selection != null && m_selHelper.Selection.RootBox != null) { TextSelInfo tsi = new TextSelInfo(m_selHelper.Selection); m_selHelper.RootSite.RootBox.PropChanged(tsi.HvoAnchor, tsi.TagAnchor, 0, 0, 0); if (tsi.Hvo(false) != tsi.Hvo(true)) m_selHelper.RootSite.RootBox.PropChanged(tsi.Hvo(true), tsi.Tag(true), 0, 0, 0); } }
internal void ValidateParagraphContents(TextSelInfo tsi, string expectedContents) { Assert.AreEqual(expectedContents, tsi.AnchorLength > 0 ? tsi.AnchorText : ""); ValidateParagraphAnnotations(tsi.HvoAnchor); }
protected override bool OnRightMouseUp(Point pt, Rectangle rcSrcRoot, Rectangle rcDstRoot) { // if we don't install the selection here, a previous selection may give us // spurious results later on when handling the UI this right click brings up; // see LT-12154. IVwSelection sel = RootBox.MakeSelAt(pt.X, pt.Y, rcSrcRoot, rcDstRoot, true); TextSelInfo tsi = new TextSelInfo(sel); return HandleRightClickOnObject(tsi.Hvo(false)); }
internal void ValidateParagraphContentsRaw(TextSelInfo tsi, string expectedContents) { Assert.AreEqual(expectedContents, tsi.AnchorLength > 0 ? tsi.AnchorText : ""); }
protected override void OnKeyDown(KeyEventArgs e) { // detect whether the user is doing a range selection with the keyboard within // a freeform annotation, and try to keep the selection within the bounds of the editable selection. (LT-2910) if (RootBox != null && (e.Modifiers & Keys.Shift) == Keys.Shift) { TextSelInfo tsi = new TextSelInfo(RootBox); int hvoAnchor = tsi.HvoAnchor; if (hvoAnchor != 0) { ICmObject coAnchor = Cache.ServiceLocator.GetInstance<ICmObjectRepository>().GetObject(hvoAnchor); if ((coAnchor is ISegment && (tsi.TagAnchor == SegmentTags.kflidFreeTranslation || tsi.TagAnchor == SegmentTags.kflidLiteralTranslation)) || (coAnchor is INote && tsi.TagAnchor == NoteTags.kflidContent)) { // we are in a segment-level annotation. if (e.KeyCode == Keys.Home) { // extend the selection to the beginning of the comment. SelectionHelper selHelper = SelectionHelper.GetSelectionInfo(tsi.Selection, this); selHelper.IchEnd = 0; selHelper.MakeRangeSelection(RootBox, true); return; } } } } // LT-9570 for the Tree Translation line, Susanna wanted Enter to copy Word Glsses // into the Free Translation line. Note: DotNetBar is not handling shortcut="Enter" // for the XML <command id="CmdAddWordGlossesToFreeTrans"... if (RootBox != null && e.KeyCode == Keys.Enter) OnAddWordGlossesToFreeTrans(null); // LT-4029 Capture arrow keys from inside the translation lines and notes. var change = HandleArrowKeys(e); // LT-12097 Right and left arrow keys from an empty translation line (part of the issue) // The up and down arrows work, so here we changed the event appropriately to up or down. if (change != ArrowChange.Handled) { KeyEventArgs e2; switch (change) { // might need to change the key event so the base method will handle it right. case ArrowChange.Down: e2 = new System.Windows.Forms.KeyEventArgs(Keys.Down); break; case ArrowChange.Up: e2 = new System.Windows.Forms.KeyEventArgs(Keys.Up); break; case ArrowChange.None: e2 = e; break; default: e2 = e; break; } base.OnKeyDown(e2); } }
virtual protected void InsertSegmentBreakAfter1stTwfic(StTxtPara para0, out TextSelInfo tsiBeforeIns) { m_rtp.SetCursor(para0, "xxxpus".Length); m_rtp.OnInsert(".", out tsiBeforeIns); m_rtp.ValidateInsertedState(".", tsiBeforeIns); string sAfterInsert = "xxxpus. xxxyalola xxxnihimbilira. xxxnihimbilira xxxpus xxxyalola. xxxhesyla xxxnihimbilira."; m_rtp.ValidateParagraphContents(para0, sAfterInsert); }
/// <summary> /// This computes and saves the information needed to ensure the insertion point is /// placed on the correct line of a multilingual annotation when replacing a user /// prompt. See LT-9421. /// </summary> private void SetCpropPreviousForInsert() { m_cpropPrevForInsert = -1; if (RootBox != null) { var tsi = new TextSelInfo(RootBox); if (tsi.Selection == null) return; var co = Cache.ServiceLocator.GetInstance<ICmObjectRepository>().GetObject(tsi.HvoAnchor); var freeAnn = co as ICmIndirectAnnotation; if (tsi.TagAnchor == SimpleRootSite.kTagUserPrompt && freeAnn != null) { var helper = SelectionHelper.GetSelectionInfo(tsi.Selection, this); int wsField = 0; if (tsi.TssAnchor != null && tsi.TssAnchor.Length > 0) wsField = TsStringUtils.GetWsAtOffset(tsi.TssAnchor, 0); else return; var rgsli = helper.GetLevelInfo(SelectionHelper.SelLimitType.Anchor); var itagSegments = -1; for (var i = rgsli.Length; --i >= 0; ) { if (rgsli[i].tag == StTxtParaTags.kflidSegments) { itagSegments = i; break; } } if (itagSegments >= 0) { int hvoSeg = rgsli[itagSegments].hvo; var annType = freeAnn.AnnotationTypeRA; int idx = 0; var choices = m_vc.LineChoices; for (int i = choices.FirstFreeformIndex; i < choices.Count; ) { var ffAannType = m_vc.SegDefnFromFfFlid(choices[i].Flid); if (ffAannType == annType) { idx = i; 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 += choices.AdjacentWssAtIndex(i).Length; } int[] rgws = choices.AdjacentWssAtIndex(idx); for (int i = 0; i < rgws.Length; ++i) { if (rgws[i] == wsField) { m_cpropPrevForInsert = i; break; } } } } } }