Exemple #1
0
		private void VerifyChangeColumn(NotifyChangeSpy spy, CmIndirectAnnotation row0,
			ICmAnnotation[] ccasToMove, int hvoColumn, string message)
		{
			foreach (ICmAnnotation cca in ccasToMove)
				Assert.AreEqual(hvoColumn, cca.InstanceOfRAHvo, message);
			spy.AssertHasNotification(row0.Hvo, (int)CmIndirectAnnotation.CmIndirectAnnotationTags.kflidAppliesTo, 0, 2, 2);
		}
Exemple #2
0
		private void VerifyChangeRow(NotifyChangeSpy spy, CmIndirectAnnotation rowSrc, int[] ccasToMove,
			CmIndirectAnnotation rowDst, int hvoOriginalColumn, string message, int ihvoDest)
		{
			int i = ihvoDest;
			foreach (int cca in ccasToMove)
			{
				Assert.AreEqual(cca, rowDst.AppliesToRS[ihvoDest].Hvo, message);
				Assert.IsFalse(rowSrc.AppliesToRS.Contains(cca));
				ihvoDest++;
			}
			spy.AssertHasNotification(rowSrc.Hvo, (int)CmIndirectAnnotation.CmIndirectAnnotationTags.kflidAppliesTo);
			spy.AssertHasNotification(rowDst.Hvo, (int)CmIndirectAnnotation.CmIndirectAnnotationTags.kflidAppliesTo);
		}
Exemple #3
0
		private void VerifyInsertMarker(NotifyChangeSpy spy, CmIndirectAnnotation row0, ICmPossibility marker)
		{
			VerifyRow(0, "1a", 2);
			VerifyMarkerCca(0, 1, m_allColumns[1], marker.Hvo);
		}
Exemple #4
0
		// Make a column annotation for the specified column that groups the specified words
		// and append to the specified row.
		private CmIndirectAnnotation MakeColumnAnnotation(int icol, int[] words, CmIndirectAnnotation row)
		{
			return m_helper.MakeColumnAnnotation(icol, words, row);
		}
Exemple #5
0
		/// <summary>
		/// make one.
		/// </summary>
		public UndoSuppressCommentPrompt(TeStVc vc, CmIndirectAnnotation ft)
		{
			m_vc = vc;
			m_ft = ft;
		}
Exemple #6
0
		private void VerifyMoveAnnotationToSameRowLaterColBeforeMtm(int[] allParaWfics, NotifyChangeSpy spy,
			CmIndirectAnnotation cca0_1, int cExpectCSelect)
		{
			// Should have: added allParaWfics[1] to a new CCA in column 3 of row 0 (before moved text marker in col 4).
			VerifyRow(0, "1a", 3);
			VerifyCca(0, 0, m_allColumns[1], new int[] { allParaWfics[0] }, "");
			VerifyCca(0, 1, m_allColumns[3], new int[] { allParaWfics[1] }, "");
			VerifyCca(0, 2, m_allColumns[4], new int[] { cca0_1.Hvo }, ConstituentChartLogic.FTO_MovedTextBefore);
			Assert.AreEqual(cExpectCSelect, m_mockRibbon.CSelectFirstCalls);
			AssertUsedAnnotations(allParaWfics, 2);
			Assert.AreEqual(1, m_chart.RowsRS.Count, "should not add a row");
			// Verify various PropChanged calls.
			VerifyAnnotationListChange(allParaWfics, spy, 2, 1);
		}
Exemple #7
0
		private bool DeleteFreeform(IVwSelection sel)
		{
			int hvoAnnotation;
			if (!CanDeleteFF(sel, out hvoAnnotation))
				return false;
			int hvoSeg, tagFF, ihvoFF, cpropPrevious;
			IVwPropertyStore vps;
			// NOTE: Do not use ihvoFF for updating the cache directly, because the display vector indices
			// does not necessarily correspond to the cache vector indices.
			sel.PropInfo(false, 1, out hvoSeg, out tagFF, out ihvoFF, out cpropPrevious, out vps);
			CmBaseAnnotation seg = new CmBaseAnnotation(Cache, hvoSeg);
			CmIndirectAnnotation ft = new CmIndirectAnnotation(Cache, hvoAnnotation);
			bool wasFt = ft.AnnotationTypeRAHvo == Cache.GetIdFromGuid(LangProject.kguidAnnFreeTranslation);
			StTxtPara para = seg.BeginObjectRA as StTxtPara;
			m_fdoCache.DeleteObject(hvoAnnotation);
			m_fdoCache.PropChanged(null, PropChangeType.kpctNotifyAll, hvoSeg, tagFF, ihvoFF, 0, 1);
			if (wasFt && para != null)
				FreeTransEditMonitor.UpdateMainTransFromSegmented(para, Cache.LangProject.CurAnalysisWssRS.HvoArray);
			return true; // handled
		}
			/// <summary>
			/// </summary>
			/// <param name="cbaSegTargetHvo"></param>
			/// <param name="cbaSegSrcHvo"></param>
			/// <param name="segmentFFCommentsBeforeSegBreakEdit_begin"></param>
			/// <param name="segmentFFCommentsBeforeSegBreakEdit_end"></param>
			/// <param name="segmentFFsAfterMerge"></param>
			private void ValidateMergedFreeformAnnotations(int cbaSegTargetHvo, int cbaSegSrcHvo,
				List<int> segmentFFCommentsBeforeMerge_target,
				List<int> segmentFFCommentsBeforeMerge_src,
				FdoObjectSet<ICmIndirectAnnotation> segmentFFsAfterMerge)
			{
				int segDefn_note = Cache.GetIdFromGuid(LangProject.kguidAnnNote);
				Dictionary<int, List<ICmIndirectAnnotation>> typeToAnnBeforeMergeBegin =
					AnnotationAdjuster.MakeAnnTypeToAnnDictionary(Cache, segmentFFCommentsBeforeMerge_target);
				Dictionary<int, List<ICmIndirectAnnotation>> typeToAnnAfterMerge =
					AnnotationAdjuster.MakeAnnTypeToAnnDictionary(segmentFFsAfterMerge);
				List<ICmIndirectAnnotation> srcNotes = new List<ICmIndirectAnnotation>();
				foreach (int srcFreeformAnnHvo in segmentFFCommentsBeforeMerge_src)
				{
					ICmIndirectAnnotation srcFreeformAnn = new CmIndirectAnnotation(Cache, srcFreeformAnnHvo) as ICmIndirectAnnotation;
					ICmIndirectAnnotation realSrcFreeformAnn = new CmIndirectAnnotation(Cache, ffsClonedToReal[srcFreeformAnn.Hvo]);
					List<ICmIndirectAnnotation> targetAnns;
					List<ICmIndirectAnnotation> mergedAnns;
					Assert.IsTrue(typeToAnnAfterMerge.TryGetValue(srcFreeformAnn.AnnotationTypeRAHvo, out mergedAnns),
							"Expected src ff annotation to be in the merged set.");
					// see if we can find the annotation on the target segment matching the same type.
					// if so, we should have merged into its comment.
					if (srcFreeformAnn.AnnotationTypeRAHvo != segDefn_note &&
						typeToAnnBeforeMergeBegin.TryGetValue(srcFreeformAnn.AnnotationTypeRAHvo, out targetAnns))
					{
						Assert.IsFalse(realSrcFreeformAnn.IsRealObject, "Expected merged ff to have been deleted.");
						Assert.AreEqual(1, targetAnns.Count, "We only expect to have one annotation of this type.");
						int hvoTargetFF = targetAnns[0].Hvo;
						// see if we can find src comment in the same ws as the target.
						ICmIndirectAnnotation targetFreeformAnn = new CmIndirectAnnotation(Cache, hvoTargetFF) as ICmIndirectAnnotation;
						foreach (int wsTarget in Cache.LangProject.CurrentAnalysisAndVernWss)
						{
							// assume that the first ws-run indicates the ws of this multistring.
							ITsString tssTargetComment = targetFreeformAnn.Comment.GetAlternativeTss(wsTarget);
							ITsString tssSrcComment = srcFreeformAnn.Comment.GetAlternativeTss(wsTarget);
							string sTarget = "";
							string sSrc = "";
							if (tssTargetComment.Length > 0)
							{
								sTarget = tssTargetComment.Text + " ";
							}
							if (tssSrcComment.Length > 0)
							{
								sSrc = tssSrcComment.Text;
							}
							if (tssTargetComment.Text == null && tssSrcComment.Text == null)
							{
								Assert.AreEqual(null,
									typeToAnnAfterMerge[srcFreeformAnn.AnnotationTypeRAHvo][0].Comment.GetAlternativeTss(wsTarget).Text,
									"Expected annotation comments to be merged.");
							}
							else
							{
								Assert.AreEqual(sTarget + sSrc,
									typeToAnnAfterMerge[srcFreeformAnn.AnnotationTypeRAHvo][0].Comment.GetAlternativeTss(wsTarget).Text,
									"Expected annotation comments to be merged.");
							}
						}
					}
					else
					{
						Assert.IsTrue(mergedAnns.IndexOf(realSrcFreeformAnn) != -1);
						Assert.IsTrue(realSrcFreeformAnn.IsRealObject, "Expected merged ff to have been deleted.");
						if (srcFreeformAnn.AnnotationTypeRAHvo == segDefn_note)
						{
							srcNotes.Add(srcFreeformAnn);
							// find this Note in the merged list
						}
						foreach (int wsSrc in Cache.LangProject.CurrentAnalysisAndVernWss)
						{
							// assume that the first ws-run indicates the ws of this multistring.
							ITsString tssSrcComment = srcFreeformAnn.Comment.GetAlternativeTss(wsSrc);
							ITsString tssMovedComment = realSrcFreeformAnn.Comment.GetAlternativeTss(wsSrc);
							Assert.IsNotNull(tssMovedComment);
							Assert.AreEqual(tssSrcComment.Text, tssMovedComment.Text,
								"Expected annotation comments to be identical.");
						}
					}
				}
				// make sure all the merged ff annotations point to the target and none point to the old src segment
				// it's a note or not found on the target, just move the AppliesToRC item to the target.
				// make sure it's not pointing to the old segment.
				foreach (ICmIndirectAnnotation ciaMergedFF in segmentFFsAfterMerge)
				{
					Assert.IsFalse(ciaMergedFF.AppliesToRS.Contains(cbaSegSrcHvo),
						"Expected freeform annotation to no longer reference a merged annotation.");
					// make sure it's pointing to the new segment.
					Assert.IsTrue(ciaMergedFF.AppliesToRS.Contains(cbaSegTargetHvo),
						"Expected freeform annotation to reference target annotation.");
				}
				// make sure we have the expected number of notes.
				List<ICmIndirectAnnotation> mergedNotes;
				if (!typeToAnnAfterMerge.TryGetValue(segDefn_note, out mergedNotes))
					mergedNotes = new List<ICmIndirectAnnotation>();
				List<ICmIndirectAnnotation> targetNotes;
				if (!typeToAnnBeforeMergeBegin.TryGetValue(segDefn_note, out targetNotes))
					targetNotes = new List<ICmIndirectAnnotation>();
				Assert.AreEqual(targetNotes.Count + srcNotes.Count, mergedNotes.Count,
					"Expected the same number of freeform annotations.");
			}
		private void AddSegment(StTxtPara para, int ichMin, int ichLim, string ft)
		{
			// Since this is an in-memory test, we can't use CmBaseAnnotation.CreateUnownedCba.
			CmBaseAnnotation seg = new CmBaseAnnotation();
			Cache.LangProject.AnnotationsOC.Add(seg);
			seg.AnnotationTypeRAHvo = m_hvoSegAnnDefn;
			seg.BeginOffset = ichMin;
			seg.EndOffset = ichLim;
			seg.BeginObjectRA = para;
			seg.EndObjectRA = para;
			if (Cache.MainCacheAccessor.get_IsPropInCache(para.Hvo, kflidSegments, (int)CellarModuleDefns.kcptReferenceSequence, 0))
			{
				int cseg = Cache.GetVectorSize(para.Hvo, kflidSegments);
				m_scrInMemoryCache.CacheAccessor.CacheReplace(para.Hvo, kflidSegments, cseg, cseg, new int[] {seg.Hvo}, 1);
			}
			else
			{
				// Don't want to just read it, because that actually parses the paragraph. If it's not already in memory
				// this is the first one, so just make it so.
				Cache.VwCacheDaAccessor.CacheVecProp(para.Hvo, kflidSegments, new int[] {seg.Hvo}, 1);
			}
			if (ft != null)
			{
				// Since this is an in-memory test, we can't use CmIndirectAnnotation.CreateUnownedIndirectAnnotation.
				CmIndirectAnnotation ftAnn = new CmIndirectAnnotation();
				Cache.LangProject.AnnotationsOC.Add(ftAnn);
				ftAnn.AnnotationTypeRAHvo = m_hvoFtAnnDefn;
				ftAnn.AppliesToRS.Append(seg);
				ftAnn.Comment.SetAlternative(ft, Cache.DefaultAnalWs);
				m_scrInMemoryCache.CacheAccessor.CacheObjProp(seg.Hvo, kflidFT, ftAnn.Hvo);
			}
		}
		/// <summary>
		/// Verify that the paragraph has the expected number of segments with the expected free translations.
		/// Lengths should be the lengths of the segments.
		/// </summary>
		private void VerifySegments(StTxtPara para, string[] freeTranslations, int[] lengths, string label)
		{
			int cseg = Cache.GetVectorSize(para.Hvo, kflidSegments);
			Assert.AreEqual(freeTranslations.Length, cseg);
			int i = 0;
			int cumLength = 0;
			foreach (string ft in freeTranslations)
			{
				int hvoSeg = Cache.GetVectorItem(para.Hvo, kflidSegments, i);
				CmBaseAnnotation seg = new CmBaseAnnotation(Cache, hvoSeg);
				Assert.AreEqual(cumLength, seg.BeginOffset, label + " - beginOffset " + i);
				cumLength += lengths[i];
				Assert.AreEqual(cumLength, seg.EndOffset, label + " - endOffset " + i);
				Assert.AreEqual(m_hvoSegAnnDefn, seg.AnnotationTypeRAHvo, label + " - seg ann type " + i);
				if (ft != null)
				{
					int hvoFt = Cache.GetObjProperty(hvoSeg, kflidFT);
					Assert.IsTrue(hvoFt != 0, label + "ft present " + i);
					CmIndirectAnnotation ftAnn = new CmIndirectAnnotation(Cache, hvoFt);
					Assert.AreEqual(ft, ftAnn.Comment.AnalysisDefaultWritingSystem.Text, label + " - comment " + i);
					Assert.AreEqual(m_hvoFtAnnDefn, ftAnn.AnnotationTypeRAHvo, label + " - ft type " + i);
					Assert.AreEqual(1, ftAnn.AppliesToRS.Count, label + " - appliesTo length " + i);
					Assert.AreEqual(seg.Hvo, ftAnn.AppliesToRS.HvoArray[0], label + " - applies to val " + i);
				}
				i++;
			}
		}
Exemple #11
0
		/// <summary>
		/// Copy the free translations from the source to the destination. This is designed to be used on the
		/// output of CopyObject. (It will not remove or merge any existing Segments or FTs, and assumes
		/// the structure of the two books matches exactly.)
		/// Enhance JohnT: we could fairly easily copy literal translations, notes, Wfics as well.
		/// 1. sql1 should allow the additional annotation type(s).
		/// 2. for Wfic, sql1 should retrieve instanceOf
		/// 3. for Wfic, Code should copy InstanceOf as well as other stuff to new annotations.
		/// 4. For literal translations and notes, sql2 and 3 need to include additional annotation types.
		/// For Wfics, a complication is that the instanceOf target for a saved version Wfic may possibly
		/// not be guaranteed to be preserved. We should probably not copy any Wfic which has no instanceOf.
		/// </summary>
		/// <param name="source"></param>
		/// <param name="dest"></param>
		void CopyFreeTranslations(IScrBook source, IScrBook dest)
		{
			FdoCache cache = source.Cache;
			int segmentDefn = cache.GetIdFromGuid(LangProject.kguidAnnTextSegment);
			int ftSegmentDefn = cache.GetIdFromGuid(LangProject.kguidAnnFreeTranslation);
			if (segmentDefn == 0 || ftSegmentDefn == 0)
				return; // Running tests without enough structure to do this.

			// Build a dictionary mapping corresponding paragraphs in the original and copy.
			Dictionary<int, int> paraMap = new Dictionary<int, int>();
			for (int isec = 0; isec < source.SectionsOS.Count; isec++)
			{
				IScrSection sourceSec = source.SectionsOS[isec];
				IScrSection destSec = dest.SectionsOS[isec];
				MapText(sourceSec.ContentOA, destSec.ContentOA, paraMap);
				MapText(sourceSec.HeadingOA, destSec.HeadingOA, paraMap);
			}
			for (int ifn = 0; ifn < source.FootnotesOS.Count; ++ifn)
			{
				IStFootnote sourceFn = source.FootnotesOS[ifn];
				IStFootnote destFn = dest.FootnotesOS[ifn];
				MapText(sourceFn, destFn, paraMap);
			}
			MapText(source.TitleOA, dest.TitleOA, paraMap);

			// For every segment pointing to a title or footnote paragraph that matches, the query returns
			// 2 * the number of sections identical results.  Thus, DISTINCT is needed to create the proper
			// set of copies of the segments.
			string sql1 =
				@"select DISTINCT seg.id, seg.BeginOffset, seg.EndOffset, seg.BeginObject, seg.WritingSystem
				from ScrBook book
				join CmObject sec on sec.Owner$ = book.id
				join CmObject txt_fn on txt_fn.Owner$ = sec.id or txt_fn.Owner$ = book.id
				join CmObject para on para.Owner$ = txt_fn.id
				join CmBaseAnnotation_ seg on seg.BeginObject = para.id and seg.AnnotationType = " + segmentDefn + @"
				where book.id = " + source.Hvo;
			List<int[]> segInfo = DbOps.ReadIntArray(cache, sql1, null, 5);
			// Map the original segment HVOs onto the copies.
			Dictionary<int, int> segMap = new Dictionary<int, int>(segInfo.Count);

			Logger.WriteEvent("Creating base annotations");
			foreach (int[] info in segInfo)
			{
				int hvoPara = paraMap[info[3]];
				// REVIEW (SteveMiller): Don't we want the CmBaseAnnotation.Flid, too?
				string sql4 =
					@"DECLARE @id INT;
					INSERT INTO CmObject (Class$) VALUES (37);
					SET @Id = @@IDENTITY;
					INSERT INTO CmAnnotation (Id, AnnotationType) VALUES (@Id, " +
					segmentDefn + @");
					INSERT INTO CmBaseAnnotation
						(Id, BeginOffset, EndOffset, BeginObject, EndObject, WritingSystem)
						VALUES (@Id, " + info[1] + @", " + info[2] + @", " +
									   hvoPara + @", " + hvoPara + @", " + (info[4] == 0 ? "null" : info[4].ToString()) + @");
					SELECT @id;";
				int hvo;
				if (DbOps.ReadOneIntFromCommand(cache, sql4, null, out hvo))
					segMap[info[0]] = hvo;
			}
			/*
			 * JT: "In revision 12, you moved the actual copy loop into SQL. Unfortunately, in the
			 * process, the new code simply copies the BeginObject from the old segment to the new.
			 * It is supposed to point the new segment to the corresponding paragraph in
			 * the copy, as looked up in paraMap. The result is to duplicate the segments on the
			 * old book's paragraphs instead of copying them to the new.
			string sql4 =
				@"SET TRANSACTION ISOLATION LEVEL SERIALIZABLE -- so we're the only ones inserting
				DECLARE @Id INT, @BeginOffset INT, @Flid INT, @EndOffset INT,
					@BeginObject INT, @EndObject INT, @WritingSystem INT, @ClassId INT;
				SELECT @ClassId = Id FROM Class$ WHERE Name = 'CmBaseAnnotation';
				DECLARE curBA CURSOR LOCAL STATIC FORWARD_ONLY READ_ONLY FOR
					select DISTINCT seg.BeginOffset, seg.Flid, seg.EndOffset,
						seg.BeginObject, seg.EndObject, seg.WritingSystem
					from ScrBook book
					join CmObject sec on sec.Owner$ = book.id
					join CmObject txt_fn on txt_fn.Owner$ = sec.id or txt_fn.Owner$ = book.id
					join CmObject para on para.Owner$ = txt_fn.id
					join CmBaseAnnotation_ seg on seg.BeginObject = para.id
						and seg.AnnotationType = " + segmentDefn + @"
					where book.id = " + source.Hvo + @"
				OPEN curBA;
				FETCH curBA INTO @BeginOffset, @Flid, @EndOffset, @BeginObject, @EndObject, @WritingSystem;
				WHILE @@FETCH_STATUS = 0 BEGIN
					INSERT INTO CmObject (Class$) VALUES (@ClassId);
					SET @Id = @@IDENTITY;
					INSERT INTO CmAnnotation (Id, AnnotationType)
						VALUES (@Id, " + segmentDefn + @");
					INSERT INTO CmBaseAnnotation
						(Id, BeginOffset, Flid, EndOffset, BeginObject, EndObject, WritingSystem)
						VALUES
						(@Id, @BeginOffset, @Flid, @EndOffset, @BeginObject, @EndObject, @WritingSystem);
					FETCH curBA INTO @BeginOffset, @Flid, @EndOffset, @BeginObject, @EndObject, @WritingSystem;
				END
				CLOSE curBA;
				DEALLOCATE curBA;
				SET TRANSACTION ISOLATION LEVEL READ COMMITTED";
			DbOps.ExecuteStatementNoResults(cache, sql4, null);
			*/

			Logger.WriteEvent("Getting WS in use in BT's");
			// Get a list of all the writing systems we care about (all the ones that have any data for the interesting FT annotations).
			string sql2 =
				@"select DISTINCT com.ws
				from ScrBook book
				join CmObject sec on sec.Owner$ = book.id
				join CmObject txt_fn on txt_fn.Owner$ = sec.id or txt_fn.Owner$ = book.id
				join CmObject para on para.Owner$ = txt_fn.id
				join CmBaseAnnotation_ seg on seg.BeginObject = para.id and seg.AnnotationType = " + segmentDefn + @"
				join CmIndirectAnnotation_AppliesTo ft_at on ft_at.dst = seg.id
				join CmIndirectAnnotation_ ft on ft.id = ft_at.src and ft.AnnotationType = " + ftSegmentDefn + @"
				join CmAnnotation_Comment com on ft.id = com.obj
				where book.id = " + source.Hvo + @"
				group by com.ws";

			int[] wss = DbOps.ReadIntArrayFromCommand(cache, sql2, null);
			const int kflidComment = (int)CmAnnotation.CmAnnotationTags.kflidComment;

			Dictionary<int, int> ftMap = new Dictionary<int, int>();
			foreach (int ws in wss)
			{
				Logger.WriteEvent("Starting to copy for WS = " + ws);
				// For performance, and to populate the free translation virtual property, preload all the
				// free translations of the source text.
				// DISTINCT would be useful here to minimize db access traffic and duplicated insertions
				// into the cache, but isn't allowed because com.txt is NTEXT and com.fmt is IMAGE.
				// An alternative would be to split it into two queries, one for the sections and the
				// other for the title and footnotes, but then we'd have two round trips to the database,
				// which might be slower overall. (UNION won't work to combine the two queries because it
				// implies DISTINCT!)
				// The duplicate results don't cause errors here, because they're all written to the cache,
				// which replaces one copy with another without complaining.
				string sql3 =
					@"select seg.id, ft.id, com.txt, com.fmt
				from ScrBook book
				join CmObject sec on sec.Owner$ = book.id
				join CmObject txt_fn on txt_fn.Owner$ = sec.id or txt_fn.Owner$ = book.id
				join CmObject para on para.Owner$ = txt_fn.id
				join CmBaseAnnotation_ seg on seg.BeginObject = para.id and seg.AnnotationType = " + segmentDefn + @"
				join CmIndirectAnnotation_AppliesTo ft_at on ft_at.dst = seg.id
				join CmIndirectAnnotation_ ft on ft.id = ft_at.src and ft.AnnotationType = " + ftSegmentDefn + @"
				left outer join CmAnnotation_Comment com on ft.id = com.obj and com.ws = " + ws + @"
				where book.id = " + source.Hvo;

				int kflidFT = StTxtPara.SegmentFreeTranslationFlid(cache);
				IDbColSpec dcs = DbColSpecClass.Create();
				dcs.Push((int)DbColType.koctBaseId, 0, 0, 0); // segment ID column is base.
				dcs.Push((int)DbColType.koctObj, 1, kflidFT, 0); // ft annotation is property kflidFT of the segment
				dcs.Push((int)DbColType.koctMlsAlt, 2, kflidComment, ws); // then comes the text of the comment
				dcs.Push((int)DbColType.koctFmt, 2, kflidComment, ws); // and the string format information of the comment.
				Logger.WriteEvent("Loading annotations for WS = " + ws);
				cache.VwOleDbDaAccessor.Load(sql3, dcs, 0, 0, null, false);

				// Now we've preloaded the old FTs and comments, copy to new.
				Logger.WriteEvent("Processing annotations for WS = " + ws);
				foreach (KeyValuePair<int, int> pair in segMap)
				{
					int ftSrc = cache.GetObjProperty(pair.Key, kflidFT);
					if (ftSrc == 0)
						continue; // label segment
					int ftDst = m_cache.GetObjProperty(pair.Value, kflidFT);
					ICmIndirectAnnotation ft;
					if (ftDst == 0)
					{
						ft = CmIndirectAnnotation.CreateUnownedIndirectAnnotation(cache);
						ft.AppliesToRS.Append(pair.Value);
						ft.AnnotationTypeRAHvo = ftSegmentDefn;
						Cache.VwCacheDaAccessor.CacheObjProp(pair.Value, kflidFT, ft.Hvo);
					}
					else
					{
						// Already exists: presumably from a different iteration with a different WS.
						ft = new CmIndirectAnnotation(m_cache, ftDst);
					}
					cache.SetMultiStringAlt(ft.Hvo, kflidComment, ws,
						cache.GetMultiStringAlt(ftSrc, kflidComment, ws));
					ftMap[ftSrc] = ft.Hvo;
				}
				Logger.WriteEvent("Copying complete for WS = " + ws);
			}

			// Update any ScrScriptureNote with old FT hvo in its BeginObject or EndObject, or an
			// old para hvo in its BeginObject or EndObject.
			Logger.WriteEvent("Updating Scripture Annotation Refereneces");
			foreach (IScrScriptureNote note in this.BookAnnotationsOS[dest.CanonicalNum - 1].NotesOS)
			{
				if (ftMap.ContainsKey(note.BeginObjectRAHvo))
					note.BeginObjectRAHvo = ftMap[note.BeginObjectRAHvo];
				if (ftMap.ContainsKey(note.EndObjectRAHvo))
					note.EndObjectRAHvo = ftMap[note.EndObjectRAHvo];
				if (paraMap.ContainsKey(note.BeginObjectRAHvo))
					note.BeginObjectRAHvo = paraMap[note.BeginObjectRAHvo];
				if (paraMap.ContainsKey(note.EndObjectRAHvo))
					note.EndObjectRAHvo = paraMap[note.EndObjectRAHvo];
			}
			Logger.WriteEvent("CopyFreeTranslations complete");
		}
Exemple #12
0
		/// -----------------------------------------------------------------------------------
		/// <summary>
		/// Create a segmented back translation for this paragraph.
		/// </summary>
		/// <param name="para"></param>
		/// <param name="segmentBTsForPara"></param>
		/// -----------------------------------------------------------------------------------
		private void CreateSegmentedBackTranslation(IStTxtPara para, List<BTSegment> segmentBTsForPara)
		{
			int[] paraSegs;
			int wsBt = m_cache.DefaultAnalWs;	// this only affects caching...
			ICmBaseAnnotation[] segments = BtConverter.GetMainParaSegments(para, wsBt, out paraSegs);
			Debug.Assert(segmentBTsForPara.Count == segments.Length);
			int kflidFT = StTxtPara.SegmentFreeTranslationFlid(m_cache);
			for (int i = 0; i < segmentBTsForPara.Count; ++i)
			{
				BTSegment bts = segmentBTsForPara[i];
				// dummy segments have a comment type "back translation" for ws = 0.
				if (bts.GetBackTransForWs(0) != null)
					continue;
				int hvoFT = m_cache.GetObjProperty(segments[i].Hvo, kflidFT);
				ICmIndirectAnnotation ft = new CmIndirectAnnotation(m_cache, hvoFT);
				foreach (int ws in bts.AvailableBackTranslations)
					ft.Comment.SetAlternative(bts.GetBackTransForWs(ws), ws);
				foreach (IScrScriptureNote note in bts.Annotations)
				{
					note.BeginObjectRAHvo = ft.Hvo;
					note.EndObjectRAHvo = ft.Hvo;
				}
			}
		}
Exemple #13
0
		/// -----------------------------------------------------------------------------------
		/// <summary>
		/// Replace the user prompt with the text the user typed.  This method is called from
		/// the views code when the user prompt is edited.
		/// </summary>
		/// <param name="vwsel">Current selection in rootbox where this prop was updated</param>
		/// <param name="hvo">Hvo of the paragraph</param>
		/// <param name="tag">Tag</param>
		/// <param name="frag">Fragment</param>
		/// <param name="tssVal">Text the user just typed</param>
		/// <returns>possibly modified ITsString.</returns>
		/// <remarks>The return value is currently ignored in production code, but we use it
		/// in our tests.</remarks>
		/// -----------------------------------------------------------------------------------
		public override ITsString UpdateProp(IVwSelection vwsel, int hvo, int tag, int frag,
			ITsString tssVal)
		{
			CheckDisposed();

			Debug.Assert(tag == SimpleRootSite.kTagUserPrompt, "Got an unexpected tag");
			Debug.Assert(vwsel != null, "Got a null selection!");
			Debug.Assert(vwsel.IsValid, "Got an invalid selection!");
			IVwRootBox rootbox = vwsel.RootBox;

			// If a (typically Chinese) character composition is in progress, replacing the prompt will
			// destroy the selection and end the composition, causing weird typing problems (TE-8267).
			// Ending the composition does another Commit, which ensures that this will eventually be
			// called when there is NOT a composition in progress.
			if (rootbox.IsCompositionInProgress)
				return tssVal;

			// Remove the UserPrompt pseudo-property from the text the user typed.
			// when appropriate also ensure the correct writing system.
			// The correct WS is m_wsDefault in the view constructor
			ITsStrBldr bldr = (ITsStrBldr)tssVal.GetBldr();
			if (frag != (int)CmAnnotation.CmAnnotationTags.kflidComment)
			{
				bldr.SetIntPropValues(0, bldr.Length, (int)FwTextPropType.ktptWs,
									  (int)FwTextPropVar.ktpvDefault, m_wsDefault);
			}
			// Delete the user prompt property from the string (TE-3994)
			bldr.SetIntPropValues(0, bldr.Length, SimpleRootSite.ktptUserPrompt, -1, -1);
			tssVal = bldr.GetString();

			// 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);
			// Prior to the Commit in selection changed which causes this UpdateProp to be called,
			// earlier selection changed code has expanded the selection (because it is in a user prompt)
			// to the whole prompt. It is therefore a range selection, and the value of fAssocPrev we got
			// is useless. We want to make a selection associated with the previous character at the END of
			// the range.

			if (frag == (int)CmAnnotation.CmAnnotationTags.kflidComment)
			{
				// If the length is zero...we need to suppress replacing the comment with a prompt.
				if (tssVal.Length == 0)
					m_hvoSuppressCommentPrompt = hvo;
				CmIndirectAnnotation ann = new CmIndirectAnnotation(Cache, hvo);
				if (ann.Comment.GetAlternative(BackTranslationWS).Length == 0)
				{
					// Undo needs to unset suppressing the comment prompt.
					Cache.ActionHandlerAccessor.AddAction(new UndoSuppressCommentPrompt(this, ann));
				}
				// Turn the prompt property off for future typing, too.
				ITsPropsBldr pb = ttp.GetBldr();
				pb.SetIntPropValues(SimpleRootSite.ktptUserPrompt, -1, -1);
				ann.Comment.SetAlternative(tssVal, BackTranslationWS);
				rootbox.MakeTextSelection(ihvoRoot, cvsli, rgvsli,
					(int)CmAnnotation.CmAnnotationTags.kflidComment, cpropPrevious, ichEnd, ichEnd,
					BackTranslationWS, fAssocPrev, ihvoEnd, pb.GetTextProps(), true);
				return tssVal;
			}

			ReplacePromptUndoAction undoAction =
				new ReplacePromptUndoAction(hvo, m_cache, m_updatedPrompts);

			if (m_cache.ActionHandlerAccessor != null)
				m_cache.ActionHandlerAccessor.AddAction(undoAction);

			// Mark the user prompt as having been updated - will not show prompt again.
			// Note: ReplacePromptUndoAction:Undo removes items from the Set.
			m_updatedPrompts.Add(hvo);

			// Replace the ITsString in the paragraph or translation
			// - this destroys the selection because we replace the user prompt.
			StTxtPara para;
			CmTranslation trans;
			ITsTextProps props = StyleUtils.CharStyleTextProps(null, m_wsDefault);
			if (frag == (int)CmTranslation.CmTranslationTags.kflidTranslation)
			{
				trans = new CmTranslation(Cache, hvo);
				trans.Translation.GetAlternative(m_wsDefault).UnderlyingTsString = tssVal;
				undoAction.ParaHvo = trans.OwnerHVO;

				// now set the selection to the end of the text that was just put in.
				ichAnchor = ichEnd;
				rootbox.MakeTextSelection(ihvoRoot, cvsli, rgvsli,
					(int)CmTranslation.CmTranslationTags.kflidTranslation, cpropPrevious, ichAnchor, ichEnd,
					m_wsDefault, true, ihvoEnd, props, true);
			}
			else
			{
				para = new StTxtPara(Cache, hvo);
				para.Contents.UnderlyingTsString = tssVal;
				undoAction.ParaHvo = hvo;

				// now set the selection to the end of the text that was just put in.
				ichAnchor = ichEnd;
				rootbox.MakeTextSelection(ihvoRoot, cvsli, rgvsli,
					(int)StTxtPara.StTxtParaTags.kflidContents, cpropPrevious, ichAnchor, ichEnd,
					m_wsDefault, true, ihvoEnd, props, true);
			}

			return tssVal;
		}
Exemple #14
0
		private CmIndirectAnnotation MakeMovedTextAnnotation(int icol, CmIndirectAnnotation target,
			CmIndirectAnnotation row, string marker)
		{
			return m_helper.MakeMovedTextAnnotation(icol, target, row, marker);
		}
Exemple #15
0
		internal void CallMakeMovedFrom(int icolActual, int icolMovedFrom, CmIndirectAnnotation rowActual,
			CmIndirectAnnotation rowMovedFrom, int[] wficsToMove)
		{
			MakeMovedFrom(new ChartLocation(icolActual, rowActual), new ChartLocation(icolMovedFrom, rowMovedFrom), wficsToMove);
		}
Exemple #16
0
		private void VerifyDeleteCcas(NotifyChangeSpy spy, CmIndirectAnnotation row0)
		{
			VerifyRow(0, "1a", 0);
			spy.AssertHasNotification(row0.Hvo, (int)CmIndirectAnnotation.CmIndirectAnnotationTags.kflidAppliesTo, 0, 0, 1);
		}
Exemple #17
0
		private void VerifyMoveSecondAnnotationToSameCol(int[] allParaWfics,
			CmIndirectAnnotation cca0_1, NotifyChangeSpy spy, int cExpectCSelect)
		{
			// Should have: added allParaWfics[1] to cca0_1 (and not have added rows or CCAs)
			VerifyRow(0, "1a", 1); // still 1 CCA, shouldn't make a new one.
			VerifyCca(0, 0, m_allColumns[1], new int[] { allParaWfics[0], allParaWfics[1] }, "");
			Assert.AreEqual(cExpectCSelect, m_mockRibbon.CSelectFirstCalls);
			AssertUsedAnnotations(allParaWfics, 2);
			Assert.AreEqual(1, m_chart.RowsRS.Count, "should not add a row");
			// Verify various PropChanged calls.
			VerifyAnnotationListChange(allParaWfics, spy, 2, 1);
		}
		/// <summary>
		/// Verify that FindFirstCcaWithWfics() finds the given 'testCca' as the first CCA in 'list'
		/// </summary>
		/// <param name="testCca"></param>
		/// <param name="list"></param>
		/// <param name="message"></param>
		private void VerifyFirstCca(CmIndirectAnnotation testCca, List<ICmAnnotation> list, string message)
		{
			ICmIndirectAnnotation cca = m_logic.CallFindFirstCcaWithWfics(list);
			Assert.IsNotNull(cca, message);
			Assert.AreEqual(testCca.Hvo, cca.Hvo, message);
		}
		internal CmIndirectAnnotation MakeMovedTextAnnotation(int icol, CmIndirectAnnotation target,
			CmIndirectAnnotation rowAnn, string marker)
		{
			CmIndirectAnnotation cca = MakeIndirectAnnotation();
			if (target != null)
				cca.AppliesToRS.Append(target);
			InitializeCca(cca, icol, rowAnn);
			cca.Comment.AnalysisDefaultWritingSystem.Text = marker;
			return cca;
		}