Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions site/Site/Pages/Documentation/Controls/Customization.razor
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ public class AlertControl : ExecutableControl
cNode2.Title = "Hover on me";
_cDiagram.Controls.AddFor(cNode1, ControlsType.OnSelection).Add(new NodeInformationControl());
_cDiagram.Controls.AddFor(cNode2, ControlsType.OnHover).Add(new NodeInformationControl());
_cDiagram.Controls.AddFor(cNode2, ControlsType.AlwaysOn).Add(new NodeInformationControl());
_cDiagram.SelectModel(cNode1, false);

// Executable Control
Expand Down
98 changes: 45 additions & 53 deletions src/Blazor.Diagrams.Core/Controls/ControlsBehavior.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,57 +5,49 @@ namespace Blazor.Diagrams.Core.Controls;

public class ControlsBehavior : Behavior
{
public ControlsBehavior(Diagram diagram) : base(diagram)
{
Diagram.PointerEnter += OnPointerEnter;
Diagram.PointerLeave += OnPointerLeave;
Diagram.SelectionChanged += OnSelectionChanged;
}

private void OnSelectionChanged(SelectableModel model)
{
var controls = Diagram.Controls.GetFor(model);
if (controls is not { Type: ControlsType.OnSelection })
return;

if (model.Selected)
{
controls.Show();
}
else
{
controls.Hide();
}
}

private void OnPointerEnter(Model? model, PointerEventArgs e)
{
if (model == null)
return;

var controls = Diagram.Controls.GetFor(model);
if (controls is not { Type: ControlsType.OnHover })
return;

controls.Show();
}

private void OnPointerLeave(Model? model, PointerEventArgs e)
{
if (model == null)
return;

var controls = Diagram.Controls.GetFor(model);
if (controls is not { Type: ControlsType.OnHover })
return;

controls.Hide();
}

public override void Dispose()
{
Diagram.PointerEnter -= OnPointerEnter;
Diagram.PointerLeave -= OnPointerLeave;
Diagram.SelectionChanged -= OnSelectionChanged;
}
public ControlsBehavior(Diagram diagram) : base(diagram)
{
Diagram.PointerEnter += OnPointerEnter;
Diagram.PointerLeave += OnPointerLeave;
Diagram.SelectionChanged += OnSelectionChanged;
}

private void OnSelectionChanged(SelectableModel model)
{
var controls = Diagram.Controls.GetFor(model, ControlsType.OnSelection);
if (controls is null)
return;

if (model.Selected)
{
controls.Show();
}
else
{
controls.Hide();
}
}

private void OnPointerEnter(Model? model, PointerEventArgs e)
{
if (model == null)
return;

Diagram.Controls.GetFor(model, ControlsType.OnHover)?.Show();
}

private void OnPointerLeave(Model? model, PointerEventArgs e)
{
if (model == null)
return;

Diagram.Controls.GetFor(model, ControlsType.OnHover)?.Hide();
}

public override void Dispose()
{
Diagram.PointerEnter -= OnPointerEnter;
Diagram.PointerLeave -= OnPointerLeave;
Diagram.SelectionChanged -= OnSelectionChanged;
}
}
10 changes: 5 additions & 5 deletions src/Blazor.Diagrams.Core/Controls/ControlsContainer.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Blazor.Diagrams.Core.Models.Base;

namespace Blazor.Diagrams.Core.Controls;
Expand All @@ -16,17 +14,19 @@ public ControlsContainer(Model model, ControlsType type = ControlsType.OnSelecti
{
Model = model;
Type = type;

Visible = type == ControlsType.AlwaysOn;
}

public Model Model { get; }
public ControlsType Type { get; set; }
public ControlsType Type { get; init; }
public bool Visible { get; private set; }

public void Show()
{
if (Visible)
return;

Visible = true;
VisibilityChanged?.Invoke(Model);
}
Expand All @@ -35,7 +35,7 @@ public void Hide()
{
if (!Visible)
return;

Visible = false;
VisibilityChanged?.Invoke(Model);
}
Expand Down
96 changes: 71 additions & 25 deletions src/Blazor.Diagrams.Core/Controls/ControlsLayer.cs
Original file line number Diff line number Diff line change
@@ -1,61 +1,107 @@
using System;
using System.Collections.Generic;
using Blazor.Diagrams.Core.Models.Base;

namespace Blazor.Diagrams.Core.Controls;

public class ControlsLayer
{
private readonly Dictionary<Model, ControlsContainer> _containers;
private readonly Dictionary<(Model Model, ControlsType Type), ControlsContainer> _containers = new();

public event Action<Model>? ChangeCaused;

public ControlsLayer()
{
_containers = new Dictionary<Model, ControlsContainer>();
}

public IReadOnlyCollection<Model> Models => _containers.Keys;
public IEnumerable<Model> Models => _containers.Keys.Select(key => key.Model);
public IEnumerable<(Model Model, ControlsType Type)> ContainersKeys => _containers.Keys;

public ControlsContainer AddFor(Model model, ControlsType type = ControlsType.OnSelection)
{
if (_containers.ContainsKey(model))
return _containers[model];

var container = new ControlsContainer(model, type);
var key = (model, type);
if (_containers.TryGetValue(key, out ControlsContainer? container))
return container;

container = new(model, type);
container.VisibilityChanged += OnVisibilityChanged;
container.ControlsChanged += RefreshIfVisible;
model.Changed += RefreshIfVisible;
_containers.Add(model, container);

_containers.Add(key, container);

return container;
}

public ControlsContainer? GetFor(Model model)
public ControlsContainer? GetFor(Model model, ControlsType type)
{
return _containers.TryGetValue(model, out var container) ? container : null;
_containers.TryGetValue((model, type), out ControlsContainer? container);

return container;
}

public bool RemoveFor(Model model)
/// <summary>
/// Will return ALL registered containers for model. Null if no containers registered
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public IReadOnlyCollection<ControlsContainer>? GetFor(Model model)
{
List<ControlsContainer>? containers = new();
foreach (ControlsType type in (ControlsType[])Enum.GetValues(typeof(ControlsType)))
{
if (_containers.TryGetValue((model, type), out ControlsContainer? container))
containers.Add(container);
}

if (containers.Count == 0)
return null;

return containers.AsReadOnly();
}

public bool RemoveFor(Model model, ControlsType type)
{
if (!_containers.TryGetValue(model, out var container))
var key = (model, type);
if (!_containers.TryGetValue(key, out var container))
return false;

container.VisibilityChanged -= OnVisibilityChanged;
container.ControlsChanged -= RefreshIfVisible;
model.Changed -= RefreshIfVisible;
_containers.Remove(model);
_containers.Remove(key);
ChangeCaused?.Invoke(model);
return true;
}

public bool AreVisibleFor(Model model) => GetFor(model)?.Visible ?? false;
public bool RemoveFor(Model model)
{
bool removed = false;
foreach (ControlsType type in (ControlsType[])Enum.GetValues(typeof(ControlsType)))
{
var key = (model, type);
if (_containers.TryGetValue(key, out var container))
{
container.VisibilityChanged -= OnVisibilityChanged;
container.ControlsChanged -= RefreshIfVisible;
model.Changed -= RefreshIfVisible;
_containers.Remove(key);
ChangeCaused?.Invoke(model);
removed = true;
}

}

return removed;
}

public bool AreVisibleFor(Model model, ControlsType type) => GetFor(model, type)?.Visible ?? false;

private void RefreshIfVisible(Model cause)
{
if (!AreVisibleFor(cause))
return;

ChangeCaused?.Invoke(cause);
foreach (ControlsType type in (ControlsType[])Enum.GetValues(typeof(ControlsType)))
{
if (AreVisibleFor(cause, type))
{
ChangeCaused?.Invoke(cause);
return;
}
}

}

private void OnVisibilityChanged(Model cause) => ChangeCaused?.Invoke(cause);
Expand Down
3 changes: 2 additions & 1 deletion src/Blazor.Diagrams.Core/Controls/ControlsType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ namespace Blazor.Diagrams.Core.Controls;
public enum ControlsType
{
OnHover,
OnSelection
OnSelection,
AlwaysOn
}
3 changes: 1 addition & 2 deletions src/Blazor.Diagrams.Core/Layers/LinkLayer.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Blazor.Diagrams.Core.Anchors;
using Blazor.Diagrams.Core.Models.Base;
using System.Linq;

namespace Blazor.Diagrams.Core.Layers;

Expand Down Expand Up @@ -30,7 +29,7 @@ protected override void OnItemRemoved(BaseLinkModel link)
link.TargetChanged -= OnLinkTargetChanged;

Diagram.Controls.RemoveFor(link);
Remove(link.Links.ToList());
Remove(link.Links);
}

private static void OnLinkSourceChanged(BaseLinkModel link, Anchor old, Anchor @new)
Expand Down
56 changes: 28 additions & 28 deletions src/Blazor.Diagrams/Components/Controls/ControlsLayerRenderer.razor
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
@foreach (var model in BlazorDiagram.Controls.Models)
@foreach (var key in BlazorDiagram.Controls.ContainersKeys)
{
var controls = BlazorDiagram.Controls.GetFor(model)!;
if (!controls.Visible || controls.Count == 0)
continue;
var controls = BlazorDiagram.Controls.GetFor(key.Model, key.Type)!;
if (!controls.Visible || controls.Count == 0)
continue;

if (Svg && model.IsSvg())
{
<g class="controls" data-model-type="@model.GetType().Name" data-model-id="@model.Id">
@foreach (var control in controls)
{
var position = control.GetPosition(model);
if (position == null)
continue;
if (Svg && key.Model.IsSvg())
{
<g class="controls" data-model-type="@key.Model.GetType().Name" data-model-id="@key.Model.Id" @key="key">
@foreach (var control in controls)
{
var position = control.GetPosition(key.Model);
if (position == null)
continue;

@RenderControl(model, control, position, true)
}
</g>
}
else if (!Svg && !model.IsSvg())
{
<div class="controls" data-model-type="@model.GetType().Name" data-model-id="@model.Id">
@foreach (var control in controls)
{
var position = control.GetPosition(model);
if (position == null)
continue;
@RenderControl(key.Model, control, position, true)
}
</g>
}
else if (!Svg && !key.Model.IsSvg())
{
<div class="controls" data-model-type="@key.Model.GetType().Name" data-model-id="@key.Model.Id" @key="key">
@foreach (var control in controls)
{
var position = control.GetPosition(key.Model);
if (position == null)
continue;

@RenderControl(model, control, position, false)
}
</div>
}
@RenderControl(key.Model, control, position, false)
}
</div>
}
}
Loading