This class helps manage multiple changes to a record list. By default, it will suspend full Reloads initiated by PropChanged until we finish. During dispose, we'll ReloadList if we tried to reload the list via PropChanged.
Inheritance: FwDisposableBase
Example #1
0
		/// <summary>
		/// Initialize this as an IxCoreColleague
		/// </summary>
		/// <remarks> subclasses must call this from their Init.
		/// This was done, rather than providing an Init() here in the normal way,
		/// to drive home the point that the subclass must set m_fullyInitialized
		/// to true when it is fully initialized.</remarks>
		/// <param name="mediator"></param>
		/// <param name="configurationParameters"></param>
		protected void InitBase(Mediator mediator, XmlNode configurationParameters)
		{
			Debug.Assert(m_fullyInitialized == false, "No way we are fully initialized yet!");

			m_mediator = mediator;
			m_configurationParameters = configurationParameters;

			ReadParameters();

			RecordClerk clerk = ExistingClerk;
			if (clerk == null)
			{
				// NOTE: new clerks do not typically complete ReloadList()
				// until Clerk.ActivateUI() is set (eg. here in SetupDataContext()).
				// however, we should further delay loading the list
				// if the subclass is initializing sorters/filters.
				// so we use ListUpdateHelper below to delay reloading the list.
				clerk = Clerk;
				Debug.Assert(clerk != null);
			}
			// suspend any loading of the Clerk's list items until after a
			// subclass (possibly) initializes sorters/filters
			// in SetupDataContext()
			using (RecordClerk.ListUpdateHelper luh = new RecordClerk.ListUpdateHelper(clerk))
			{
				luh.ClearBrowseListUntilReload = true;
				clerk.UpdateOwningObjectIfNeeded();
				SetTreebarAvailability();
				AddPaneBar();

				// NB: It is critical that we get added *after* our RecordClerk,
				// so that it will get messages, for example about a change of cache, before we do.
				mediator.AddColleague(this);
				SetupDataContext();
			}
			// In case it hasn't yet been loaded, load it!  See LT-10185.
			if (!Clerk.ListLoadingSuppressed && Clerk.RequestedLoadWhileSuppressed)
				Clerk.UpdateList(true, true);
			ShowRecord();
		}
Example #2
0
		/// <summary>
		/// Initialize this as an IxCoreColleague
		/// </summary>
		/// <remarks> subclasses must call this from their Init.
		/// This was done, rather than providing an Init() here in the normal way,
		/// to drive home the point that the subclass must set m_fullyInitialized
		/// to true when it is fully initialized.</remarks>
		/// <param name="mediator"></param>
		/// <param name="configurationParameters"></param>
		protected void InitBase(Mediator mediator, XmlNode configurationParameters)
		{
			Debug.Assert(m_fullyInitialized == false, "No way we are fully initialized yet!");

			m_mediator = mediator;
			m_configurationParameters = configurationParameters;

			ReadParameters();

			RecordClerk clerk = ExistingClerk;
			bool fClerkAlreadySuppressed = false;
			bool fClerkWasCreated = false;
			if (clerk == null)
			{
				// We do NOT want to load the list as part of creating the clerk.
				// At earliest, we want to do so only when the ListUpdateHelper is disposed,
				// after the clerk and list are sufficiently initialized (e.g., with saved sorting and filtering
				// information) to sort correctly. This is part of a fairly convoluted attempt to prevent
				// sorting the list repeatedly during startup, even though startup involves many events
				// that normally require it to be resorted.
				// In this case the clerk will be created with its list already in the ListLoadingSuppressed state,
				// and already set to indicate that loading is necessary when suppression ends;
				// we want to pass FALSE to the ListUpdateHelper constructor, however, to pretend that the
				// list was NOT suppressed when the helper was created, so it will duly be sorted when
				// the helper is disposed.
				fClerkWasCreated = true;
				clerk = CreateClerk(false);
				Debug.Assert(clerk != null);
			}
			else
				fClerkAlreadySuppressed = clerk.ListLoadingSuppressed; // If we didn't create the clerk, someone else might have suppressed it.
			// suspend any loading of the Clerk's list items until after a
			// subclass (possibly) initializes sorters/filters
			// in SetupDataContext()
			bool didRestoreFromPersistence = false;
			using (var luh = new RecordClerk.ListUpdateHelper(clerk, fClerkAlreadySuppressed))
			{
				luh.ClearBrowseListUntilReload = true;
				clerk.UpdateOwningObjectIfNeeded();
				SetTreebarAvailability();
				AddPaneBar();

				//Historical comments here indicated that the Clerk should be processed by the mediator before the
				//view. This is handled by Priority now, RecordView is by default just after RecordClerk in the processing.
				mediator.AddColleague(this);
				SetupDataContext();
				// Only if it was just now created should we try to restore from what we persisted.
				// Otherwise (e.g., FWR-1128) we may miss changes made to the list in other tools.
				if (fClerkWasCreated)
					didRestoreFromPersistence = RestoreSortSequence();
				if (didRestoreFromPersistence)
					luh.ListWasRestored();
			}
			// In case it hasn't yet been loaded, load it!  See LT-10185.
			if (!didRestoreFromPersistence && !Clerk.ListLoadingSuppressed && Clerk.RequestedLoadWhileSuppressed)
				Clerk.UpdateList(true, true); // sluggishness culprit for LT-12844 was in here
			Clerk.SetCurrentFromRelatedClerk(); // See if some other clerk wants to influence our current object.
			ShowRecord();
		}
		private void LaunchRespellerDlgOnWord(ITsString tss)
		{
			if (tss == null || string.IsNullOrEmpty(tss.Text))
				return;
			FdoCache cache = m_mediator.PropertyTable.GetValue("cache") as FdoCache;
			int hvoWordform = WfiWordform.FindOrCreateWordform(cache, tss);
			if (hvoWordform == 0)
				return; // paranoia.
			IWfiWordform wf = WfiWordform.CreateFromDBObject(cache, hvoWordform);
			using (RecordClerk.ListUpdateHelper luh = new RecordClerk.ListUpdateHelper(m_mediator.PropertyTable.GetValue("ActiveClerk") as RecordClerk))
			{
				// Launch the Respeller Dlg.
				using (RespellerDlg dlg = new RespellerDlg())
				{
					XWindow xwindow = m_mediator.PropertyTable.GetValue("window") as XWindow;
					if (dlg.SetDlgInfo2(wf, m_mediator, m_configurationParameters))
					{
						dlg.ShowDialog(xwindow);
					}
					else
					{
						MessageBox.Show(MEStrings.ksCannotRespellWordform);
					}
				}
				// We assume that RespellerDlg made all the necessary changes to relevant lists.
				// no need to reload due to a propchange (e.g. change in paragraph contents).
				luh.TriggerPendingReloadOnDispose = false;
			}
		}
Example #4
0
		internal override void HandleContentChange(int hvo, int ivMin, int cvIns, int cvDel)
		{
			RawTextPane rtp = m_parentEditingHelper.Callbacks as RawTextPane;
			if (rtp == null)
				return;
			if (AlreadyHandledMovingAnnotations(hvo))
				return;
			using (RecordClerk.ListUpdateHelper luh = new RecordClerk.ListUpdateHelper(rtp.Clerk))
			{
				luh.SkipShowRecord = true;
				base.HandleContentChange(hvo, ivMin, cvIns, cvDel);
				// in general we don't want to reload the primary clerk
				// while we are editing, since that can be expensive.
				if (rtp.Clerk != null && rtp.Clerk.IsPrimaryClerk)
				{
					luh.TriggerPendingReloadOnDispose = false;
					// in some cases we may also want to do Clerk.RemoveInvalidItems()
					// to help prevent the user from crashing when they click on it.
				}
			}
		}
		/// <summary>
		/// Launch the Respeller dlg.
		/// </summary>
		/// <param name="argument">The xCore Command object.</param>
		/// <returns>true</returns>
		public bool OnLaunchRespellerDlg(object argument)
		{
			CheckDisposed();
			if (!InFriendliestTool)		// See LT-8641.
			{
				LaunchRespellerDlgOnWord(ActiveWord());
				return true;
			}
			using (RecordClerk.ListUpdateHelper luh = new RecordClerk.ListUpdateHelper(m_mediator.PropertyTable.GetValue("ActiveClerk") as RecordClerk))
			{
				// Launch the Respeller Dlg.
				using (RespellerDlg dlg = new RespellerDlg())
				{
					XWindow xwindow = m_mediator.PropertyTable.GetValue("window") as XWindow;
					if (dlg.SetDlgInfo(m_mediator, m_configurationParameters))
					{
						dlg.ShowDialog(xwindow);
					}
					else
					{
						MessageBox.Show(MEStrings.ksCannotRespellWordform);
					}
				}
				// We assume that RespellerDlg made all the necessary changes to relevant lists.
				// no need to reload due to a propchange (e.g. change in paragraph contents).
				luh.TriggerPendingReloadOnDispose = false;
			}
			return true;
		}
Example #6
0
		public override void PropChanged(int hvo, int tag, int ivMin, int cvIns, int cvDel)
		{
			ConcordanceItemsVirtualHandler cvh = VirtualHandler as ConcordanceItemsVirtualHandler;
			// in the special case of including/removing Scripture ids, we want to treat it like a change in a filter
			// so we really want to try to reload rather than clearing our list.
			if (tag == LangProject.InterlinearTextsFlid(m_cache))
			{
				cvh.LoadRequested = true;
			}
			// by default, we don't want to reload this tool due to PropChanges, unless it's our property.
			using (RecordClerk.ListUpdateHelper luh = new RecordClerk.ListUpdateHelper(Clerk))
			{
				base.PropChanged(hvo, tag, ivMin, cvIns, cvDel);
				// we DO want to reload if our property changed, or we've set LoadRequested.
				// otherwise, we'll try to live with things being out of a valid state.
				luh.TriggerPendingReloadOnDispose = (tag == Flid && hvo == m_owningObject.Hvo || cvh.LoadRequested == true);
			}
			// if we delete a text, then we need to clear the list of concordance matches since
			// some of them may be pointing to the deleted text.  See LT-7130.
			if (hvo == m_cache.LangProject.Hvo && tag < 0 && cvIns < cvDel)
			{
				RecordClerk clerk = m_mediator.PropertyTable.GetValue("ActiveClerk") as RecordClerk;
				if (clerk != null && clerk.VirtualFlid == tag && clerk is InterlinearTextsRecordClerk)
					base.NeedToReloadVirtualProperty = true;
			}
		}
Example #7
0
		public override void PropChanged(int hvo, int tag, int ivMin, int cvIns, int cvDel)
		{
			CheckDisposed();
			if (m_fUpdatingList && tag == m_flidOwningItemToConvertToReal)
				return;	// we're already in the process of changing our list.
			using (RecordClerk.ListUpdateHelper luh = new RecordClerk.ListUpdateHelper(Clerk))
			{
				base.PropChanged(hvo, tag, ivMin, cvIns, cvDel);
			}
		}
Example #8
0
		public override void PropChanged(int hvo, int tag, int ivMin, int cvIns, int cvDel)
		{
			CheckDisposed();

			if (m_fUpdatingList &&
				(tag == m_flid ||
				tag == (int)WfiWordform.WfiWordformTags.kflidForm ||
				tag == (int)WordformInventory.WordformInventoryTags.kflidWordforms))
			{
				return;	// we're already in the process of changing our list.
			}

			// if we've added or removed an occurrence of a wordform, then update the relevant items in our list.
			int hvoWordform = 0;
			switch (tag)
			{
				default:
					// ktagWordformOccurrences isn't a constant,
					// so it can't be in its own case statement.
					if (tag == ktagWordformOccurrences)
						hvoWordform = hvo;
					break;
				case (int)WfiWordform.WfiWordformTags.kflidForm:
					WordformInventory.OnChangedWordformsOC();
					hvoWordform = hvo;
					break;
				case (int)WordformInventory.WordformInventoryTags.kflidWordforms:
					WordformInventory.OnChangedWordformsOC();
					if (cvDel > 0)
					{
						RemoveUnwantedSortItems(null);
						// Only quit, if none were also added.
						// If they were also added, then it will end up calling the base class impl.
						if (cvIns == 0)
							return;
					}
					break;
				case (int)LangProject.LangProjectTags.kflidTexts:
				case (int)Text.TextTags.kflidContents:
					m_fReloadConcordanceTexts = true;
					break;
				case (int)StText.StTextTags.kflidParagraphs: // Fall through.
				case (int)StTxtPara.StTxtParaTags.kflidContents:
					// we should mark the owning text as being modified.
					// how do we detect that a paragraph has been deleted?
					//m_fReloadConcordanceTexts = true;
					break;
			}

			// update the display of any word that has changed its occurrences
			// Enhance: we could expand this to include changes to other properties in our columns.
			if (hvoWordform != 0)
			{
				List<int> wordformsList;
				// try to avoid reloading our ConcordanceWordforms if it's not already loaded.
				if (VirtualHandler.IsPropInCache(Cache.MainCacheAccessor, m_owningObject.Hvo, 0))
				{
					wordformsList = new List<int>(m_cache.GetVectorProperty(m_owningObject.Hvo, m_flid, true));
					int owningIndex = wordformsList.IndexOf(hvoWordform);
					if (owningIndex >= 0)
					{
						try
						{
							// Don't apply filters while we're editing away.  See LT-7607.
							m_fEnableFilters = false;
							ReplaceListItem(hvoWordform);
						}
						finally
						{
							m_fEnableFilters = true;
						}
						return;
					}
				}
			}

			// in general, we don't want to reload this list due to PropChanges
			// since that could take a long time.
			// We'll just let the list figure out if it needs to reload
			// next time we re-enter the tool or the user does Refresh.
			using (RecordClerk.ListUpdateHelper luh = new RecordClerk.ListUpdateHelper(Clerk))
			{
				base.PropChanged(hvo, tag, ivMin, cvIns, cvDel);
				// if LangProject.InterlinearTexts has changed, we do
				// want to reload the list, otherwise we don't.
				if (tag != vtagInterlinearTexts)
					luh.TriggerPendingReloadOnDispose = false;
			}
		}
Example #9
0
		public override void PropChanged(int hvo, int tag, int ivMin, int cvIns, int cvDel)
		{
			using (RecordClerk.ListUpdateHelper luh = new RecordClerk.ListUpdateHelper(Clerk))
			{
				// don't reload the entire list via propchanges.  just indicate we need to reload.
				luh.TriggerPendingReloadOnDispose = false;
				base.PropChanged(hvo, tag, ivMin, cvIns, cvDel);

				// even if RecordList is in m_fUpdatingList mode, we still want to make sure
				// our alternate list figures out wheter it needs to reload as well.
				if (m_fUpdatingList)
					TryHandleUpdateOrMarkPendingReload(hvo, tag, ivMin, cvIns, cvDel);
			}
		}