Skip to content

Commit 1fede19

Browse files
authored
Merge pull request #257 from miroiu/feature/230-connection-text-background
Draw background rectangle for connection labels
2 parents 1e4d360 + 547c0b9 commit 1fede19

5 files changed

Lines changed: 161 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@
22

33
#### **In development**
44

5-
> - Breaking Changes:
65
> - Features:
6+
> - Added ConnectionTemplateSelector, DecoratorTemplateSelector and PendingConnectionTemplateSelector to NodifyEditor to allow selecting the data template based on custom rules
7+
> - Added TextBackground, TextPadding and TextCornerRadius dependency properties to BaseConnection to allow styling the background of the connection text
8+
> - Added DrawTextBackground to BaseConnection to allow customizing the drawing of the text background
79
> - Bugfixes:
10+
> - Fixed focus navigation exception when the editor is collapsed
11+
> - Fixed connection focus outline drawing inner overlapping lines
12+
> - Fixed connection focus outline not updating on directional arrow animation
813
914
#### **Version 7.1.0**
1015

Examples/Nodify.Playground/Editor/NodifyEditorView.xaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@
7777
Value="{StaticResource SquareConnectorColor}" />
7878
<Setter Property="OutlineBrush"
7979
Value="{StaticResource SquareConnectorOutline}" />
80+
<Setter Property="TextBackground"
81+
Value="{StaticResource SquareConnectorColor}" />
8082
</DataTrigger>
8183
<DataTrigger Binding="{Binding Input.Shape}"
8284
Value="{x:Static local:ConnectorShape.Triangle}">
@@ -86,6 +88,8 @@
8688
Value="{StaticResource TriangleConnectorColor}" />
8789
<Setter Property="OutlineBrush"
8890
Value="{StaticResource TriangleConnectorOutline}" />
91+
<Setter Property="TextBackground"
92+
Value="{StaticResource TriangleConnectorColor}" />
8993
</DataTrigger>
9094
<Trigger Property="IsMouseDirectlyOver"
9195
Value="True">
@@ -129,6 +133,12 @@
129133
Opacity="0.15" />
130134
</Setter.Value>
131135
</Setter>
136+
<Setter Property="TextBackground"
137+
Value="{StaticResource Connection.StrokeBrush}" />
138+
<Setter Property="TextPadding"
139+
Value="4 2" />
140+
<Setter Property="TextCornerRadius"
141+
Value="3" />
132142
<Setter Property="ToolTip"
133143
Value="Double click to split" />
134144
<Setter Property="Source"

Nodify/Connections/BaseConnection.cs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ public abstract class BaseConnection : Shape, IKeyboardFocusTarget<FrameworkElem
138138
public static readonly DependencyProperty FocusVisualPaddingProperty = DependencyProperty.Register(nameof(FocusVisualPadding), typeof(double), typeof(BaseConnection), new FrameworkPropertyMetadata(BoxValue.Double1, FrameworkPropertyMetadataOptions.AffectsRender));
139139
public static readonly DependencyProperty ForegroundProperty = TextBlock.ForegroundProperty.AddOwner(typeof(BaseConnection));
140140
public static readonly DependencyProperty TextProperty = TextBlock.TextProperty.AddOwner(typeof(BaseConnection), new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.AffectsRender));
141+
public static readonly DependencyProperty TextBackgroundProperty = DependencyProperty.Register(nameof(TextBackground), typeof(Brush), typeof(BaseConnection), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));
142+
public static readonly DependencyProperty TextPaddingProperty = DependencyProperty.Register(nameof(TextPadding), typeof(Thickness), typeof(BaseConnection), new FrameworkPropertyMetadata(BoxValue.Thickness2, FrameworkPropertyMetadataOptions.AffectsRender));
143+
public static readonly DependencyProperty TextCornerRadiusProperty = DependencyProperty.Register(nameof(TextCornerRadius), typeof(double), typeof(BaseConnection), new FrameworkPropertyMetadata(BoxValue.Double0, FrameworkPropertyMetadataOptions.AffectsRender));
141144
public static readonly DependencyProperty FontSizeProperty = TextElement.FontSizeProperty.AddOwner(typeof(BaseConnection));
142145
public static readonly DependencyProperty FontFamilyProperty = TextElement.FontFamilyProperty.AddOwner(typeof(BaseConnection));
143146
public static readonly DependencyProperty FontWeightProperty = TextElement.FontWeightProperty.AddOwner(typeof(BaseConnection));
@@ -423,6 +426,36 @@ public string? Text
423426
set => SetValue(TextProperty, value);
424427
}
425428

429+
/// <summary>
430+
/// Gets or sets the padding around the text of the connection. Only applied if <see cref="TextBackground"/> is not null.
431+
/// </summary>
432+
public Thickness TextPadding
433+
{
434+
get => (Thickness)GetValue(TextPaddingProperty);
435+
set => SetValue(TextPaddingProperty, value);
436+
}
437+
438+
/// <summary>
439+
/// Gets or sets the corner radius of the text background. Only applied if <see cref="TextBackground"/> is not null.
440+
/// </summary>
441+
public double TextCornerRadius
442+
{
443+
get => (double)GetValue(TextCornerRadiusProperty);
444+
set => SetValue(TextCornerRadiusProperty, value);
445+
}
446+
447+
/// <summary>
448+
/// Gets or sets the background brush of the text. If null, no background is drawn.
449+
/// </summary>
450+
/// <remarks>
451+
/// Customize the appearance of the text background by setting the <see cref="TextPadding"/> and <see cref="TextCornerRadius"/> properties.
452+
/// </remarks>
453+
public Brush? TextBackground
454+
{
455+
get => (Brush?)GetValue(TextBackgroundProperty);
456+
set => SetValue(TextBackgroundProperty, value);
457+
}
458+
426459
/// <inheritdoc cref="TextElement.FontSize" />
427460
[TypeConverter(typeof(FontSizeConverter))]
428461
public double FontSize
@@ -980,7 +1013,16 @@ protected override void OnRender(DrawingContext drawingContext)
9801013
var text = new FormattedText(Text, CultureInfo.CurrentUICulture, FlowDirection, typeface, FontSize, Foreground ?? Stroke, dpi);
9811014

9821015
(Vector sourceOffset, Vector targetOffset) = GetOffset();
983-
drawingContext.DrawText(text, GetTextPosition(text, Source + sourceOffset, Target + targetOffset));
1016+
1017+
var textPosition = GetTextPosition(text, Source + sourceOffset, Target + targetOffset);
1018+
1019+
if (TextBackground != null)
1020+
{
1021+
var textSize = new Size(text.Width, text.Height);
1022+
DrawTextBackground(drawingContext, new Rect(textPosition, textSize));
1023+
}
1024+
1025+
drawingContext.DrawText(text, textPosition);
9841026
}
9851027

9861028
if (AdornerLayer != null && Container is { IsKeyboardFocused: true })
@@ -989,6 +1031,24 @@ protected override void OnRender(DrawingContext drawingContext)
9891031
}
9901032
}
9911033

1034+
protected virtual void DrawTextBackground(DrawingContext drawingContext, Rect bounds)
1035+
{
1036+
var padding = TextPadding;
1037+
double radius = TextCornerRadius;
1038+
1039+
var rectSize = new Size(bounds.Width + padding.Left + padding.Right, bounds.Height + padding.Bottom + padding.Top);
1040+
var rect = new Rect(bounds.Location - new Vector(padding.Left, padding.Top), rectSize);
1041+
1042+
if (OutlineBrush != null)
1043+
{
1044+
var outlineRect = rect;
1045+
outlineRect.Inflate(OutlineThickness, OutlineThickness);
1046+
drawingContext.DrawRoundedRectangle(OutlineBrush, null, outlineRect, radius, radius);
1047+
}
1048+
1049+
drawingContext.DrawRoundedRectangle(Stroke, null, rect, radius, radius);
1050+
}
1051+
9921052
internal void UpdateFocusVisual()
9931053
{
9941054
if (AdornerLayer != null)

docs/api/Nodify_BaseConnection.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,42 @@ public string Text { get; set; }
453453

454454
[String](https://docs.microsoft.com/en-us/dotnet/api/System.String)
455455

456+
### TextBackground
457+
458+
Gets or sets the background brush of the text. If null, no background is drawn.
459+
460+
```csharp
461+
public Brush TextBackground { get; set; }
462+
```
463+
464+
**Property Value**
465+
466+
[Brush](https://docs.microsoft.com/en-us/dotnet/api/System.Windows.Media.Brush)
467+
468+
### TextCornerRadius
469+
470+
Gets or sets the corner radius of the text background. Only applied if [BaseConnection.TextBackground](Nodify_BaseConnection#textbackground) is not null.
471+
472+
```csharp
473+
public double TextCornerRadius { get; set; }
474+
```
475+
476+
**Property Value**
477+
478+
[Double](https://docs.microsoft.com/en-us/dotnet/api/System.Double)
479+
480+
### TextPadding
481+
482+
Gets or sets the padding around the text of the connection. Only applied if [BaseConnection.TextBackground](Nodify_BaseConnection#textbackground) is not null.
483+
484+
```csharp
485+
public Thickness TextPadding { get; set; }
486+
```
487+
488+
**Property Value**
489+
490+
[Thickness](https://docs.microsoft.com/en-us/dotnet/api/System.Windows.Thickness)
491+
456492
## Methods
457493

458494
### DrawArrowGeometry(StreamGeometryContext, Point, Point, ConnectionDirection, ArrowHeadShape, Orientation)
@@ -575,6 +611,18 @@ protected virtual void DrawRectangleArrowhead(StreamGeometryContext context, Poi
575611

576612
`orientation` [Orientation](https://docs.microsoft.com/en-us/dotnet/api/System.Windows.Controls.Orientation)
577613

614+
### DrawTextBackground(DrawingContext, Rect)
615+
616+
```csharp
617+
protected virtual void DrawTextBackground(DrawingContext drawingContext, Rect bounds);
618+
```
619+
620+
**Parameters**
621+
622+
`drawingContext` [DrawingContext](https://docs.microsoft.com/en-us/dotnet/api/System.Windows.Media.DrawingContext)
623+
624+
`bounds` [Rect](https://docs.microsoft.com/en-us/dotnet/api/System.Windows.Rect)
625+
578626
### GetIsSelectable(UIElement)
579627

580628
```csharp

docs/api/Nodify_NodifyEditor.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,18 @@ public DataTemplate ConnectionTemplate { get; set; }
462462

463463
[DataTemplate](https://docs.microsoft.com/en-us/dotnet/api/System.Windows.DataTemplate)
464464

465+
### ConnectionTemplateSelector
466+
467+
Gets or sets the custom logic for choosing a template for [BaseConnection](Nodify_BaseConnection).
468+
469+
```csharp
470+
public DataTemplateSelector ConnectionTemplateSelector { get; set; }
471+
```
472+
473+
**Property Value**
474+
475+
[DataTemplateSelector](https://docs.microsoft.com/en-us/dotnet/api/System.Windows.Controls.DataTemplateSelector)
476+
465477
### CuttingCompletedCommand
466478

467479
Invoked when a cutting operation is completed.
@@ -570,6 +582,18 @@ public DataTemplate DecoratorTemplate { get; set; }
570582

571583
[DataTemplate](https://docs.microsoft.com/en-us/dotnet/api/System.Windows.DataTemplate)
572584

585+
### DecoratorTemplateSelector
586+
587+
Gets or sets the custom logic for choosing a template for [DecoratorContainer](Nodify_DecoratorContainer).
588+
589+
```csharp
590+
public DataTemplateSelector DecoratorTemplateSelector { get; set; }
591+
```
592+
593+
**Property Value**
594+
595+
[DataTemplateSelector](https://docs.microsoft.com/en-us/dotnet/api/System.Windows.Controls.DataTemplateSelector)
596+
573597
### DisableAutoPanning
574598

575599
Gets or sets whether to disable the auto panning when selecting or dragging near the edge of the editor configured by [NodifyEditor.AutoPanEdgeDistance](Nodify_NodifyEditor#autopanedgedistance).
@@ -1016,6 +1040,18 @@ public DataTemplate PendingConnectionTemplate { get; set; }
10161040

10171041
[DataTemplate](https://docs.microsoft.com/en-us/dotnet/api/System.Windows.DataTemplate)
10181042

1043+
### PendingConnectionTemplateSelector
1044+
1045+
Gets or sets the custom logic for choosing a template for [NodifyEditor.PendingConnection](Nodify_NodifyEditor#pendingconnection).
1046+
1047+
```csharp
1048+
public DataTemplateSelector PendingConnectionTemplateSelector { get; set; }
1049+
```
1050+
1051+
**Property Value**
1052+
1053+
[DataTemplateSelector](https://docs.microsoft.com/en-us/dotnet/api/System.Windows.Controls.DataTemplateSelector)
1054+
10191055
### PushedArea
10201056

10211057
Gets the currently pushed area while [NodifyEditor.IsPushingItems](Nodify_NodifyEditor#ispushingitems) is true.

0 commit comments

Comments
 (0)