Merge pull request #96 from LukeOrdelmans/bugfix/track-outline-nodes-per-context

track/cache outline nodes per DesignContext, so they can be cleaned up
This commit is contained in:
Jochen Kühner 2022-12-21 12:11:52 +01:00 коммит произвёл GitHub
Родитель d6049349fa 811c1ae161
Коммит 12981b37b5
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 93 добавлений и 63 удалений

Просмотреть файл

@ -25,9 +25,6 @@ namespace ICSharpCode.WpfDesign.Designer.OutlineView
{
public class OutlineNode: OutlineNodeBase
{
//TODO: Reset with DesignContext
static Dictionary<DesignItem, IOutlineNode> outlineNodes = new Dictionary<DesignItem, IOutlineNode>();
protected OutlineNode(DesignItem designitem): base(designitem)
{
UpdateChildren();
@ -43,22 +40,14 @@ namespace ICSharpCode.WpfDesign.Designer.OutlineView
DummyPlacementType = PlacementType.Register("DummyPlacement");
}
public static IOutlineNode Create(DesignItem designItem)
{
IOutlineNode node = null;
if (designItem != null && !outlineNodes.TryGetValue(designItem, out node)) {
node = new OutlineNode(designItem);
outlineNodes[designItem] = node;
}
return node;
}
[Obsolete("prefer using DesignItem.CreateOutlineNode()")]
public static IOutlineNode Create(DesignItem designItem) => designItem.CreateOutlineNode();
void Selection_SelectionChanged(object sender, DesignItemCollectionEventArgs e)
{
IsSelected = DesignItem.Services.Selection.IsComponentSelected(DesignItem);
}
protected override void UpdateChildren()
{
Children.Clear();
@ -68,7 +57,7 @@ namespace ICSharpCode.WpfDesign.Designer.OutlineView
{
if (prp.Value != null) {
var propertyNode = PropertyOutlineNode.Create(prp);
var node = OutlineNode.Create(prp.Value);
var node = prp.Value.CreateOutlineNode();
propertyNode.Children.Add(node);
Children.Add(propertyNode);
}
@ -82,7 +71,7 @@ namespace ICSharpCode.WpfDesign.Designer.OutlineView
if (content.Value != null) {
if (!UpdateChildrenCore(new[] {content.Value})) {
var propertyNode = PropertyOutlineNode.Create(content);
var node = OutlineNode.Create(content.Value);
var node = content.Value.CreateOutlineNode();
propertyNode.Children.Add(node);
Children.Add(propertyNode);
}
@ -111,7 +100,7 @@ namespace ICSharpCode.WpfDesign.Designer.OutlineView
foreach (var item in items) {
if (ModelTools.CanSelectComponent(item)) {
if (Children.All(x => x.DesignItem != item)) {
var node = OutlineNode.Create(item);
var node = item.CreateOutlineNode();
if (index > -1) {
Children.Insert(index++, node);
retVal = true;
@ -139,5 +128,27 @@ namespace ICSharpCode.WpfDesign.Designer.OutlineView
return retVal;
}
internal class OutlineNodeService : IOutlineNodeService, IDisposable
{
readonly Dictionary<DesignItem, IOutlineNode> outlineNodes = new Dictionary<DesignItem, IOutlineNode>();
public IOutlineNode Create(DesignItem designItem)
{
IOutlineNode node = null;
if (designItem != null && !outlineNodes.TryGetValue(designItem, out node))
{
node = new OutlineNode(designItem);
outlineNodes[designItem] = node;
}
return node;
}
public void Dispose()
{
outlineNodes.Clear();
}
}
}
}

Просмотреть файл

@ -233,7 +233,7 @@ namespace ICSharpCode.WpfDesign.Designer.OutlineView
using (var moveTransaction = DesignItem.Context.OpenGroup("Item moved in outline view", nodes.Select(n => n.DesignItem).ToList()))
{
if (copy) {
nodes = nodes.Select(n => OutlineNode.Create(n.DesignItem.Clone())).ToList();
nodes = nodes.Select(n => n.DesignItem.Clone().CreateOutlineNode()).ToList();
} else {
foreach (var node in nodes) {
node.DesignItem.Remove();

Просмотреть файл

@ -79,7 +79,7 @@ namespace ICSharpCode.WpfDesign.Designer.PropertyGrid.Editors
if(control!=null){
TypeMappings.TryGetValue(control.GetType(), out _type);
if (_type != null) {
IOutlineNode node = OutlineNode.Create(item);
IOutlineNode node = item.CreateOutlineNode();
Outline.Root = node;
PropertyGridView.PropertyGrid.SelectedItems = item.Services.Selection.SelectedItems;
}

Просмотреть файл

@ -74,6 +74,7 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
this.Services.AddService(typeof(UndoService), new UndoService());
this.Services.AddService(typeof(ICopyPasteService), new CopyPasteService());
this.Services.AddService(typeof(IErrorService), new DefaultErrorService(this));
this.Services.AddService(typeof(IOutlineNodeService), new OutlineNode.OutlineNodeService());
this.Services.AddService(typeof(IOutlineNodeNameService), new OutlineNodeNameService());
this.Services.AddService(typeof(ViewService), new DefaultViewService(this));
this.Services.AddService(typeof(OptionService), new OptionService());

Просмотреть файл

@ -32,7 +32,7 @@ namespace ICSharpCode.WpfDesign.Tests.Designer.OutlineView
public void Intialize()
{
_grid = CreateGridContextWithDesignSurface("<Button/><StackPanel><Button/></StackPanel>");
_outline = OutlineNode.Create(_grid);
_outline = _grid.CreateOutlineNode();
Assert.IsNotNull(_outline);
}

Просмотреть файл

@ -40,7 +40,7 @@ namespace ICSharpCode.WpfDesign.Tests.Designer.OutlineView
public void Intialize()
{
_grid = CreateGridContextWithDesignSurface("<Button/><StackPanel><Button/></StackPanel>");
_outline = OutlineNode.Create(_grid);
_outline = _grid.CreateOutlineNode();
Assert.IsNotNull(_outline);
_gridButton = _grid.ContentProperty.CollectionElements[0];
@ -176,7 +176,7 @@ namespace ICSharpCode.WpfDesign.Tests.Designer.OutlineView
public void Intialize()
{
_grid = CreateGridContextWithDesignSurface("<Button/><StackPanel><Image/></StackPanel>");
_outline = OutlineNode.Create(_grid);
_outline = _grid.CreateOutlineNode();
Assert.IsNotNull(_outline);
_gridButton = _grid.ContentProperty.CollectionElements[0];

Просмотреть файл

@ -32,7 +32,7 @@ namespace ICSharpCode.WpfDesign.Tests.Designer.OutlineView
public void Intialize()
{
_grid = CreateGridContextWithDesignSurface("<Button/><StackPanel><Button/></StackPanel>");
_outline = OutlineNode.Create(_grid);
_outline = _grid.CreateOutlineNode();
Assert.IsNotNull(_outline);
var selection = _grid.Services.Selection;

Просмотреть файл

@ -354,7 +354,12 @@ namespace ICSharpCode.WpfDesign
/// Creates a copy of this design item.
/// </summary>
public abstract DesignItem Clone();
/// <summary>
/// Gets a <see cref="IOutlineNode"/> for this this design item.
/// </summary>
public IOutlineNode CreateOutlineNode() => Services.GetRequiredService<IOutlineNodeService>().Create(this);
/// <summary>
/// Gets a <see cref="Transform"/> that represents all transforms applied to the item's view.
/// </summary>

Просмотреть файл

@ -1,38 +1,38 @@
// Copyright (c) 2019 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace ICSharpCode.WpfDesign.Designer.OutlineView
{
public interface IOutlineNode
{
ISelectionService SelectionService { get; }
bool IsExpanded { get; set; }
DesignItem DesignItem { get; set; }
ServiceContainer Services { get; }
bool IsSelected { get; set; }
bool IsDesignTimeVisible { get; set; }
bool IsDesignTimeLocked { get; }
string Name { get; }
bool CanInsert(IEnumerable<IOutlineNode> nodes, IOutlineNode after, bool copy);
void Insert(IEnumerable<IOutlineNode> nodes, IOutlineNode after, bool copy);
ObservableCollection<IOutlineNode> Children { get; }
}
}
// Copyright (c) 2019 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace ICSharpCode.WpfDesign
{
public interface IOutlineNode
{
ISelectionService SelectionService { get; }
bool IsExpanded { get; set; }
DesignItem DesignItem { get; set; }
ServiceContainer Services { get; }
bool IsSelected { get; set; }
bool IsDesignTimeVisible { get; set; }
bool IsDesignTimeLocked { get; }
string Name { get; }
bool CanInsert(IEnumerable<IOutlineNode> nodes, IOutlineNode after, bool copy);
void Insert(IEnumerable<IOutlineNode> nodes, IOutlineNode after, bool copy);
ObservableCollection<IOutlineNode> Children { get; }
}
}

Просмотреть файл

@ -222,7 +222,20 @@ namespace ICSharpCode.WpfDesign
object GetDescription(DesignItemProperty designProperty);
}
#endregion
#region IOutlineNodeService
/// <summary>
/// Used to create Outline Nodes.
/// </summary>
public interface IOutlineNodeService
{
/// <summary>
/// Create Ouline Node for the DesignItem, returns cached item if available.
/// </summary>
IOutlineNode Create(DesignItem designItem);
}
#endregion
#region IOutlineNodeNameService
/// <summary>
/// Used to get a description for the Outline Node.

Просмотреть файл

@ -247,7 +247,7 @@ namespace ICSharpCode.XamlDesigner
DesignSurface.LoadDesigner(xmlReader, settings);
}
if (DesignContext.RootItem != null) {
OutlineRoot = OutlineNode.Create(DesignContext.RootItem);
OutlineRoot = DesignContext.RootItem.CreateOutlineNode();
UndoService.UndoStackChanged += new EventHandler(UndoService_UndoStackChanged);
}
RaisePropertyChanged("SelectionService");