diff --git a/Src/LexText/Discourse/ConstituentChart.cs b/Src/LexText/Discourse/ConstituentChart.cs index 6aeaa6287f..483fabc5c9 100644 --- a/Src/LexText/Discourse/ConstituentChart.cs +++ b/Src/LexText/Discourse/ConstituentChart.cs @@ -1064,7 +1064,7 @@ private static InterAreaBookmark GetAncestorBookmark(Control curLevelControl, IS if (myParent is InterlinMaster) { string tool = (myParent as InterlinMaster).CurrentTool; - return InterlinMaster.m_bookmarks[new Tuple(tool, basedOnRa.Guid)]; + return InterlinMaster.Bookmarks[new Tuple(tool, basedOnRa.Guid)]; } return GetAncestorBookmark(myParent as Control, basedOnRa); } diff --git a/Src/LexText/Interlinear/InterAreaBookmark.cs b/Src/LexText/Interlinear/InterAreaBookmark.cs index 330d0dc8c5..6fe07aa02f 100644 --- a/Src/LexText/Interlinear/InterAreaBookmark.cs +++ b/Src/LexText/Interlinear/InterAreaBookmark.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2015 SIL International +// Copyright (c) 2015 SIL International // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) @@ -45,6 +45,8 @@ internal void Init(InterlinMaster interlinMaster, LcmCache cache, PropertyTable m_propertyTable = propertyTable; } + public bool IsPropertyTableDisposed => m_propertyTable.IsDisposed; + /// /// Saves the given AnalysisOccurrence in the InterlinMaster. /// diff --git a/Src/LexText/Interlinear/InterlinMaster.cs b/Src/LexText/Interlinear/InterlinMaster.cs index ceb02d2617..6c44d978c3 100644 --- a/Src/LexText/Interlinear/InterlinMaster.cs +++ b/Src/LexText/Interlinear/InterlinMaster.cs @@ -62,6 +62,18 @@ public string CurrentTool get { return m_currentTool; } } + public static Dictionary, InterAreaBookmark> Bookmarks + { + get { + if (m_bookmarks == null) + { + m_bookmarks = new Dictionary, InterAreaBookmark>(); + } + RemoveStaleBookmarks(); + return m_bookmarks; + } + } + /// /// Numbers identifying the main tabs in the interlinear text. /// @@ -96,6 +108,24 @@ internal string BookmarkId get { return m_vectorName ?? ""; } } + private static void RemoveStaleBookmarks() + { + // Remove stale bookmarks that came from a Window > New Window being closed. + IList> staleKeys = new List>(); + foreach (var key in m_bookmarks.Keys) + { + InterAreaBookmark mark = m_bookmarks[key]; + if (mark.IsPropertyTableDisposed) + { + staleKeys.Add(key); + } + } + foreach (var key in staleKeys) + { + m_bookmarks.Remove(key); + } + } + /// /// Something sometimes insists on giving the tab control focus when switching tabs. /// This defeats ctrl-tab to move between tabs. @@ -343,7 +373,7 @@ internal void SaveBookMark() if (!fSaved) { InterAreaBookmark mark; - if(m_bookmarks.TryGetValue(new Tuple(CurrentTool, RootStText.Guid), out mark)) + if(Bookmarks.TryGetValue(new Tuple(CurrentTool, RootStText.Guid), out mark)) { //We only want to persist the save if we are in the interlinear edit, not the concordance view mark.Save(curAnalysis, CurrentTool.Equals("interlinearTexts"), IndexOfTextRecord); @@ -352,7 +382,7 @@ internal void SaveBookMark() { mark = new InterAreaBookmark(this, Cache, m_propertyTable); mark.Restore(IndexOfTextRecord); - m_bookmarks.Add(new Tuple(CurrentTool, RootStText.Guid), mark); + Bookmarks.Add(new Tuple(CurrentTool, RootStText.Guid), mark); } } } @@ -430,9 +460,9 @@ private bool SaveBookmarkFromRootBox(IVwRootBox rb) //if there is a bookmark for this text with this tool, then save it, if not some logic error brought us here, //but simply not saving a bookmark which doesn't exist seems better than crashing. naylor 3/2012 var key = new Tuple(CurrentTool, RootStText.Guid); - if (m_bookmarks.ContainsKey(key)) + if (Bookmarks.ContainsKey(key)) { - m_bookmarks[key].Save(IndexOfTextRecord, iPara, Math.Min(ichAnchor, ichEnd), Math.Max(ichAnchor, ichEnd), true); + Bookmarks[key].Save(IndexOfTextRecord, iPara, Math.Min(ichAnchor, ichEnd), Math.Max(ichAnchor, ichEnd), true); } return true; @@ -727,9 +757,9 @@ public override void Init(Mediator mediator, PropertyTable propertyTable, XmlNod m_tcPane.StyleSheet = m_styleSheet; m_tcPane.Visible = true; } - if (m_bookmarks != null && m_bookmarks.Count > 0) + if (Bookmarks.Count > 0) { - foreach (InterAreaBookmark bookmark in m_bookmarks.Values) + foreach (InterAreaBookmark bookmark in Bookmarks.Values) { bookmark.Init(this, Cache, propertyTable); } @@ -1012,10 +1042,10 @@ private int SetConcordanceBookmarkAndReturnRoot(int hvoRoot) if (!m_fRefreshOccurred && m_bookmarks != null && text != null) { InterAreaBookmark mark; - if (!m_bookmarks.TryGetValue(new Tuple(CurrentTool, text.Guid), out mark)) + if (!Bookmarks.TryGetValue(new Tuple(CurrentTool, text.Guid), out mark)) { mark = new InterAreaBookmark(this, Cache, m_propertyTable); - m_bookmarks.Add(new Tuple(CurrentTool, text.Guid), mark); + Bookmarks.Add(new Tuple(CurrentTool, text.Guid), mark); } mark.Save(point, false, IndexOfTextRecord); @@ -1033,10 +1063,10 @@ private void CreateOrRestoreBookmark(IStText stText) if (stText != null) { InterAreaBookmark mark; - if (m_bookmarks.TryGetValue(new Tuple(CurrentTool, stText.Guid), out mark)) + if (Bookmarks.TryGetValue(new Tuple(CurrentTool, stText.Guid), out mark)) mark.Restore(IndexOfTextRecord); else - m_bookmarks.Add(new Tuple(CurrentTool, stText.Guid), new InterAreaBookmark(this, Cache, m_propertyTable)); + Bookmarks.Add(new Tuple(CurrentTool, stText.Guid), new InterAreaBookmark(this, Cache, m_propertyTable)); } } @@ -1069,10 +1099,10 @@ private void SelectAnnotation() if (Clerk.CurrentObjectHvo == 0 || Clerk.SuspendLoadingRecordUntilOnJumpToRecord) return; // Use a bookmark, if we've set one. - if ((RootStText != null && ((ICmObject)RootStText).IsValidObject) && m_bookmarks.ContainsKey(new Tuple(CurrentTool, RootStText.Guid)) && - m_bookmarks[new Tuple(CurrentTool, RootStText.Guid)].IndexOfParagraph >= 0 && CurrentInterlinearTabControl is IHandleBookmark) + if ((RootStText != null && ((ICmObject)RootStText).IsValidObject) && Bookmarks.ContainsKey(new Tuple(CurrentTool, RootStText.Guid)) && + Bookmarks[new Tuple(CurrentTool, RootStText.Guid)].IndexOfParagraph >= 0 && CurrentInterlinearTabControl is IHandleBookmark) { - (CurrentInterlinearTabControl as IHandleBookmark).SelectBookmark(m_bookmarks[new Tuple(CurrentTool, RootStText.Guid)]); + (CurrentInterlinearTabControl as IHandleBookmark).SelectBookmark(Bookmarks[new Tuple(CurrentTool, RootStText.Guid)]); } } @@ -1449,7 +1479,7 @@ private void m_tabCtrl_Deselecting(object sender, TabControlCancelEventArgs e) { //At this point m_tabCtrl.SelectedIndex is set to the value of the tabPage //we are leaving. - if (RootStText != null && m_bookmarks.ContainsKey(new Tuple(CurrentTool, RootStText.Guid))) + if (RootStText != null && Bookmarks.ContainsKey(new Tuple(CurrentTool, RootStText.Guid))) SaveBookMark(); } } diff --git a/Src/LexText/Interlinear/RawTextPane.cs b/Src/LexText/Interlinear/RawTextPane.cs index 6149f00abe..5ca65cc9b2 100644 --- a/Src/LexText/Interlinear/RawTextPane.cs +++ b/Src/LexText/Interlinear/RawTextPane.cs @@ -690,7 +690,7 @@ private void RawTextPane_VisibleChanged(object sender, EventArgs e) { if (CanFocus) { - var bookmark = InterlinMaster.m_bookmarks[new Tuple(CurrentTool, RootObject.Guid)]; + var bookmark = InterlinMaster.Bookmarks[new Tuple(CurrentTool, RootObject.Guid)]; MakeTextSelectionAndScrollToView(bookmark.BeginCharOffset, bookmark.EndCharOffset, 0, bookmark.IndexOfParagraph); VisibleChanged -= RawTextPane_VisibleChanged;