/// <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;
		}
Beispiel #4
0
 public RopeAction(int ropeId, WhichEnd whichEnd)
 {
     this.ropeId   = ropeId;
     this.whichEnd = whichEnd;
 }