/// <summary> /// Assumes the selection data belongs to a translation or note! /// Gets the InterlinLineChoices flid (id) and a meaningful interpretation of /// where the IP is in the translation or note text. /// If an empty translation note was selected, its tag is kTagUserPrompt. /// </summary> /// <param name="curSeg">The selected segment to get the translation or note text from.</param> /// <param name="curNote">null or the selected note</param> /// <param name="tag">The SegmentTags or NoteTags or kTagUserPrompt selected.</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="wid">Index of the writing system of the selection.</param> /// <param name="id">The returned InterlinLineChoices flid.</param> /// <param name="lineNum">Configured line number of the translation or note.</param> /// <param name="where">The returned meaningful interpretation of where the IP is in the translation or note text.</param> /// <param name="isRightToLeft">is set to <c>true</c> if the Configured line is right to left, false otherwise.</param> /// <param name="hasPrompt">is set to <c>true</c> if the line is an empty translation.</param> /// <returns> /// true if the information was found, false otherwise. /// </returns> private bool GetLineInfo(ISegment curSeg, INote curNote, int tag, int ichAnchor, int ichEnd, int wid, out int id, out int lineNum, out WhichEnd where, out bool isRightToLeft, out bool hasPrompt) { isRightToLeft = false; hasPrompt = false; var wsf = Cache.WritingSystemFactory; var ws = wsf.get_EngineOrNull(wid); if (ws != null) isRightToLeft = ws.RightToLeftScript; id = 0; lineNum = -1; where = WhichEnd.Neither; switch (tag) { case SegmentTags.kflidFreeTranslation: id = InterlinLineChoices.kflidFreeTrans; where = ExtremePositionInString(ichAnchor, ichEnd, curSeg.FreeTranslation.get_String(wid).Length, isRightToLeft); break; case SegmentTags.kflidLiteralTranslation: id = InterlinLineChoices.kflidLitTrans; where = ExtremePositionInString(ichAnchor, ichEnd, curSeg.LiteralTranslation.get_String(wid).Length, isRightToLeft); break; case NoteTags.kflidContent: Debug.Assert(curNote != null, "Moving from a non-exisiting note in interlinear Doc."); id = InterlinLineChoices.kflidNote; where = ExtremePositionInString(ichAnchor, ichEnd, curNote.Content.get_String(wid).Length, isRightToLeft); break; case kTagUserPrompt: // user prompt property for empty translation annotations // Is this free or literal? hasPrompt = true; id = m_vc.ActiveFreeformFlid; id = (id == SegmentTags.kflidLiteralTranslation) ? InterlinLineChoices.kflidLitTrans : InterlinLineChoices.kflidFreeTrans; if (wid == 0) wid = m_vc.ActiveFreeformWs; where = WhichEnd.Both; break; default: // not expected return false; } if (wid > 0) lineNum = LineChoices.IndexOf(id, wid); if (lineNum == -1) lineNum = LineChoices.IndexOf(id); return true; }
/// <summary> /// Detect that upward movement out of this segment or to an analysis /// in this same segment is needed. /// Considerations: /// Configured analysis lines preceed translation or note lines (currently). /// Analyses are stored as a sequence in the segement. /// Some analyses are punctuation that are skipped by the IP. /// Only analyses that have a word in them are considered "real". /// "Annotation" lines include translation lines (free and literal) and notes. /// Each translation or note in a diffeerent ws is a different line. /// Translations are stored in a segment as a multistring while notes are /// in a sequence of multistrings. /// Each note is repeated in each note line of a different ws. /// So, the IP may be in the first configured note, but not in the first note. /// </summary> /// <param name="e">The keyboard event being handled.</param> /// <param name="lines">The configured interlinear lines in display order.</param> /// <param name="lineNum">The current line in lines that has the selection (or IP).</param> /// <param name="curSeg">The segment that has the selection.</param> /// <param name="curNoteIndex">The note that is selected in the sequence.</param> /// <param name="where">Indicates where the IP is in the selected text if any.</param> /// <param name="isRightToLeft">true if the current line is RTL</param> /// <param name="isUpNewSeg">Output set to true if moving out of this segment.</param> /// <returns>true if the IP should be moved upward to an analysis in this segment.</returns> private bool DetectUpMove(KeyEventArgs e, IEnumerable<InterlinLineSpec> lines, int lineNum, ISegment curSeg, int curNoteIndex, WhichEnd where, bool isRightToLeft, out bool isUpNewSeg) { var linesBefore = lines.Take(lineNum); var annotationsBefore = linesBefore; bool hasPreviousAnalysis = false; if (linesBefore.Any()) // will have some lines if there are analyses { annotationsBefore = linesBefore.SkipWhile(line => line.WordLevel); hasPreviousAnalysis = linesBefore.Any(line => line.WordLevel); } bool hasPrevAnnotation = false; if (annotationsBefore.Any()) // if this is the first annotation, annotationsBefore is empty { bool hasNotesBefore = annotationsBefore.Any(line => line.Flid == InterlinLineChoices.kflidNote); hasPrevAnnotation = HasVisibleTranslationOrNote(curSeg, annotationsBefore); } else { // this is the first translation or note and it can't be a null note because it was selected bool noteIsFirstAnnotation = lines.ToArray()[lineNum].Flid == InterlinLineChoices.kflidNote; hasPrevAnnotation = noteIsFirstAnnotation && curNoteIndex > 0; // can have notes or empty notes before it } bool hasUpMotion = (e.KeyCode == Keys.Up) || (TextIsRightToLeft ? (e.KeyCode == Keys.Right && (where == WhichEnd.Right || where == WhichEnd.Both)) : (e.KeyCode == Keys.Left && (where == WhichEnd.Left || where == WhichEnd.Both))); bool isUpMove = hasUpMotion && !hasPrevAnnotation; isUpNewSeg = isUpMove && !isThereRealAnalysisInSegment(curSeg); // no puctuation, or analysis ws return isUpMove; }
/// <summary> /// Detect that downward movement out of this segment is needed. /// Considerations: /// Configured analysis lines preceed translation or note lines (currently). /// "Annotation" lines include translation lines (free and literal) and notes. /// Each translation or note in a diffeerent ws is a different line. /// Translations are stored in a segment as a multistring while notes are /// in a sequence of multistrings. /// Each note is repeated in each note line of a different ws. /// So, the IP may be in the last configured note, but not in the last note. /// </summary> /// <param name="e">The keyboard event being handled.</param> /// <param name="lines">The configured interlinear lines in display order.</param> /// <param name="lineNum">The current line in lines that has the selection (or IP).</param> /// <param name="curSeg">The segment that has the selection.</param> /// <param name="curNoteIndex">The note that is selected in the sequence.</param> /// <param name="isRightToLeft"></param> /// <param name="where">Indicates where the IP is in the selected text if any.</param> /// <returns>true if the IP should be moved upward to an analysis in this segment.</returns> private bool DetectDownMove(KeyEventArgs e, IEnumerable<InterlinLineSpec> lines, int lineNum, ISegment curSeg, int curNoteIndex, bool isRightToLeft, WhichEnd where) { var annotationsAfter = lines.Skip(lineNum + 1); bool hasFollowingAnnotation = false; if (annotationsAfter.Any()) // might not have any { bool hasNotesAfter = annotationsAfter.Any(line => line.Flid == InterlinLineChoices.kflidNote); hasFollowingAnnotation = HasVisibleTranslationOrNote(curSeg, annotationsAfter); } else { // this is the last translation or note and it can't be a null note because it was selected bool noteIsLastAnnotation = LineChoices[LineChoices.Count - 1].Flid == InterlinLineChoices.kflidNote; hasFollowingAnnotation = noteIsLastAnnotation && curNoteIndex < curSeg.NotesOS.Count - 1; } bool hasDownMotion = (e.KeyCode == Keys.Down) || (TextIsRightToLeft ? (e.KeyCode == Keys.Left && (where == WhichEnd.Left || where == WhichEnd.Both)) : (e.KeyCode == Keys.Right && (where == WhichEnd.Right || where == WhichEnd.Both))); return hasDownMotion && !hasFollowingAnnotation; }
public RopeAction(int ropeId, WhichEnd whichEnd) { this.ropeId = ropeId; this.whichEnd = whichEnd; }