Browse Source

Fix SD-1787 - Memory Leak in ContextActionsBulbPopup

pull/14/head
Daniel Grunwald 15 years ago
parent
commit
3b45327b37
  1. 8
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
  2. 7
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
  3. 43
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActionsRenderer.cs

8
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs

@ -217,10 +217,11 @@ namespace ICSharpCode.AvalonEdit.AddIn
TextCopied(this, e); TextCopied(this, e);
} }
protected virtual void DisposeTextEditor(TextEditor textEditor) protected virtual void DisposeTextEditor(CodeEditorView textEditor)
{ {
// detach IconBarMargin from IconBarManager // detach IconBarMargin from IconBarManager
textEditor.TextArea.LeftMargins.OfType<IconBarMargin>().Single().TextView = null; textEditor.TextArea.LeftMargins.OfType<IconBarMargin>().Single().TextView = null;
textEditor.Dispose();
} }
void textEditor_GotFocus(object sender, RoutedEventArgs e) void textEditor_GotFocus(object sender, RoutedEventArgs e)
@ -332,9 +333,9 @@ namespace ICSharpCode.AvalonEdit.AddIn
// remove secondary editor // remove secondary editor
this.Children.Remove(secondaryTextEditor); this.Children.Remove(secondaryTextEditor);
this.Children.Remove(gridSplitter); this.Children.Remove(gridSplitter);
secondaryTextEditorAdapter.Language.Detach();
DisposeTextEditor(secondaryTextEditor); DisposeTextEditor(secondaryTextEditor);
secondaryTextEditor = null; secondaryTextEditor = null;
secondaryTextEditorAdapter.Language.Detach();
secondaryTextEditorAdapter = null; secondaryTextEditorAdapter = null;
gridSplitter = null; gridSplitter = null;
this.RowDefinitions.RemoveAt(this.RowDefinitions.Count - 1); this.RowDefinitions.RemoveAt(this.RowDefinitions.Count - 1);
@ -574,6 +575,9 @@ namespace ICSharpCode.AvalonEdit.AddIn
if (errorPainter != null) if (errorPainter != null)
errorPainter.Dispose(); errorPainter.Dispose();
this.Document = null; this.Document = null;
DisposeTextEditor(primaryTextEditor);
if (secondaryTextEditor != null)
DisposeTextEditor(secondaryTextEditor);
} }
} }
} }

7
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs

@ -34,7 +34,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
/// There can be two CodeEditorView instances in a single CodeEditor if split-view /// There can be two CodeEditorView instances in a single CodeEditor if split-view
/// is enabled. /// is enabled.
/// </summary> /// </summary>
public class CodeEditorView : SharpDevelopTextEditor public class CodeEditorView : SharpDevelopTextEditor, IDisposable
{ {
public ITextEditor Adapter { get; set; } public ITextEditor Adapter { get; set; }
@ -61,6 +61,11 @@ namespace ICSharpCode.AvalonEdit.AddIn
SetupTabSnippetHandler(); SetupTabSnippetHandler();
} }
public virtual void Dispose()
{
contextActionsRenderer.Dispose();
}
protected override string FileName { protected override string FileName {
get { return this.Adapter.FileName; } get { return this.Adapter.FileName; }
} }

43
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActionsRenderer.cs

@ -18,7 +18,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
/// <summary> /// <summary>
/// Renders Popup with context actions on the left side of the current line in the editor. /// Renders Popup with context actions on the left side of the current line in the editor.
/// </summary> /// </summary>
public class ContextActionsRenderer public sealed class ContextActionsRenderer : IDisposable
{ {
readonly CodeEditorView editorView; readonly CodeEditorView editorView;
ITextEditor Editor { get { return this.editorView.Adapter; } } ITextEditor Editor { get { return this.editorView.Adapter; } }
@ -36,12 +36,11 @@ namespace ICSharpCode.AvalonEdit.AddIn
public bool IsEnabled public bool IsEnabled
{ {
get { get {
try { string fileName = this.Editor.FileName;
string fileName = this.Editor.FileName; if (String.IsNullOrEmpty(fileName))
return fileName.EndsWith(".cs") || fileName.EndsWith(".vb");
} catch {
return false; return false;
} return fileName.EndsWith(".cs", StringComparison.OrdinalIgnoreCase)
|| fileName.EndsWith(".vb", StringComparison.OrdinalIgnoreCase);
} }
} }
@ -59,10 +58,16 @@ namespace ICSharpCode.AvalonEdit.AddIn
this.delayMoveTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(delayMoveMilliseconds) }; this.delayMoveTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(delayMoveMilliseconds) };
this.delayMoveTimer.Stop(); this.delayMoveTimer.Stop();
this.delayMoveTimer.Tick += TimerMoveTick; this.delayMoveTimer.Tick += TimerMoveTick;
WorkbenchSingleton.Workbench.ViewClosed += WorkbenchSingleton_Workbench_ViewClosed;
WorkbenchSingleton.Workbench.ActiveViewContentChanged += WorkbenchSingleton_Workbench_ActiveViewContentChanged; WorkbenchSingleton.Workbench.ActiveViewContentChanged += WorkbenchSingleton_Workbench_ActiveViewContentChanged;
} }
public void Dispose()
{
ClosePopup();
WorkbenchSingleton.Workbench.ActiveViewContentChanged -= WorkbenchSingleton_Workbench_ActiveViewContentChanged;
delayMoveTimer.Stop();
}
void ContextActionsRenderer_KeyDown(object sender, KeyEventArgs e) void ContextActionsRenderer_KeyDown(object sender, KeyEventArgs e)
{ {
if (this.popup == null) if (this.popup == null)
@ -131,26 +136,14 @@ namespace ICSharpCode.AvalonEdit.AddIn
this.popup.IsHiddenActionsExpanded = false; this.popup.IsHiddenActionsExpanded = false;
this.popup.ViewModel = null; this.popup.ViewModel = null;
} }
void WorkbenchSingleton_Workbench_ViewClosed(object sender, ViewContentEventArgs e)
{
try {
// prevent memory leaks
if (e.Content.PrimaryFileName == this.Editor.FileName) {
WorkbenchSingleton.Workbench.ViewClosed -= WorkbenchSingleton_Workbench_ViewClosed;
WorkbenchSingleton.Workbench.ActiveViewContentChanged -= WorkbenchSingleton_Workbench_ActiveViewContentChanged;
}
} catch {}
}
void WorkbenchSingleton_Workbench_ActiveViewContentChanged(object sender, EventArgs e) void WorkbenchSingleton_Workbench_ActiveViewContentChanged(object sender, EventArgs e)
{ {
ClosePopup(); // open the popup again if in current file
try { IViewContent activeViewContent = WorkbenchSingleton.Workbench.ActiveViewContent;
// open the popup again if in current file if (activeViewContent != null && activeViewContent.PrimaryFileName == this.Editor.FileName)
if (((IViewContent)WorkbenchSingleton.Workbench.ActiveContent).PrimaryFileName == this.Editor.FileName) CaretPositionChanged(this, EventArgs.Empty);
CaretPositionChanged(this, EventArgs.Empty); else // otherwise close popup
} catch {} ClosePopup();
} }
} }
} }

Loading…
Cancel
Save