Skip to content

Commit aead7df

Browse files
lineNumberCommands:Replicating changes done to ILEditor
It's a really great examplle so need to make all those changes here that I made at this place: worksofliam/ILEditor#13
1 parent 80c6261 commit aead7df

9 files changed

+259
-192
lines changed

AvalonEdit.Pieces/LineInfo.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace AvalonEdit.Pieces
8+
{
9+
public class LineInfo
10+
{
11+
public int Number { get; set; }
12+
public System.Windows.Size RenderSize { get; set; }
13+
14+
15+
}
16+
}

AvalonEdit.Pieces/LineNumberDisplay.xaml

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,30 @@
77
mc:Ignorable="d"
88
x:Name="lineNumberDisplayCtl"
99
d:DesignHeight="300" d:DesignWidth="300">
10-
<DockPanel>
11-
<TextBlock Text="{Binding Path=Model.LineNumber, ElementName=lineNumberDisplayCtl}"
12-
Name="lineNumberTextBlock"
13-
MouseEnter="lineNumberTextBlock_MouseEnter">
14-
<TextBlock.Style>
15-
<Style TargetType="TextBlock">
16-
<Style.Triggers>
17-
<DataTrigger Binding="{Binding Path=Model.IsCommandMode, ElementName=lineNumberDisplayCtl}" Value="true">
18-
<Setter Property="Visibility" Value="Collapsed"/>
19-
</DataTrigger>
20-
</Style.Triggers>
21-
</Style>
22-
</TextBlock.Style>
23-
</TextBlock>
24-
<TextBox Text="{Binding Path=Model.CommandText, ElementName=lineNumberDisplayCtl}"
10+
<UserControl.Style>
11+
<Style TargetType="UserControl">
12+
<Style.Triggers>
13+
<DataTrigger Binding="{Binding Path=Model.IsInView, ElementName=lineNumberDisplayCtl}" Value="false">
14+
<Setter Property="Visibility" Value="Collapsed" />
15+
</DataTrigger>
16+
<DataTrigger Binding="{Binding Path=Model.IsInView, ElementName=lineNumberDisplayCtl}" Value="true">
17+
<Setter Property="Visibility" Value="Visible" />
18+
</DataTrigger>
19+
</Style.Triggers>
20+
</Style>
21+
</UserControl.Style>
22+
<DockPanel Height="{Binding Path=Model.ControlHeight, Mode=TwoWay, ElementName=lineNumberDisplayCtl}">
23+
<TextBox DockPanel.Dock="Left"
24+
MinWidth="25"
25+
Text="{Binding Path=Model.CommandText, ElementName=lineNumberDisplayCtl}"
2526
Name="lineNumberTextBox"
26-
MouseLeave="lineNumberTextBox_MouseLeave">
27-
<TextBox.Style>
28-
<Style TargetType="TextBox">
29-
<Style.Triggers>
30-
<DataTrigger Binding="{Binding Path=Model.IsCommandMode, ElementName=lineNumberDisplayCtl}" Value="false">
31-
<Setter Property="Visibility" Value="Collapsed"/>
32-
</DataTrigger>
33-
</Style.Triggers>
34-
</Style>
35-
</TextBox.Style>
27+
>
3628
</TextBox>
29+
<TextBlock DockPanel.Dock="Left"
30+
Text="{Binding Path=Model.LineNumber, ElementName=lineNumberDisplayCtl}"
31+
Name="lineNumberTextBlock"
32+
>
33+
</TextBlock>
34+
3735
</DockPanel>
3836
</UserControl>

AvalonEdit.Pieces/LineNumberDisplay.xaml.cs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,24 +36,8 @@ public LineNumberDisplayModel Model
3636
public LineNumberDisplay()
3737
{
3838
InitializeComponent();
39-
40-
this.Model = new LineNumberDisplayModel();
41-
this.Model.LineNumber = 99;
42-
}
43-
44-
45-
private void lineNumberTextBlock_MouseEnter(object sender, MouseEventArgs e)
46-
{
47-
var tb = sender as TextBlock;
48-
this.Model.IsCommandMode = true;
4939
}
5040

51-
private void lineNumberTextBox_MouseLeave(object sender, MouseEventArgs e)
52-
{
53-
var tb = sender as TextBox;
54-
this.Model.IsCommandMode = false;
55-
56-
}
5741

5842

5943

AvalonEdit.Pieces/LineNumberDisplayModel.cs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,24 @@ public int LineNumber
1515
set { this.SetValue(() => this.LineNumber, value); }
1616
}
1717

18+
public string CommandText
19+
{
20+
get { return this.GetValue(() => this.CommandText); }
21+
set { this.SetValue(() => this.CommandText, value); }
22+
}
1823

19-
public bool IsCommandMode
24+
// each line number is a specific height
25+
public double ControlHeight
2026
{
21-
get { return this.GetValue(() => this.IsCommandMode); }
22-
set { this.SetValue(() => this.IsCommandMode, value); }
27+
get { return this.GetValue(() => this.ControlHeight); }
28+
set { this.SetValue(() => this.ControlHeight, value); }
2329
}
2430

25-
public string CommandText
31+
32+
public bool IsInView
2633
{
27-
get { return this.GetValue(() => this.CommandText); }
28-
set { this.SetValue(() => this.CommandText, value); }
34+
get { return this.GetValue(() => this.IsInView); }
35+
set { this.SetValue(() => this.IsInView, value); }
2936
}
3037

3138

AvalonEdit.Pieces/LineNumberMarginAdorner.cs

Lines changed: 61 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Collections.ObjectModel;
34
using System.Linq;
45
using System.Text;
56
using System.Threading.Tasks;
@@ -13,121 +14,108 @@ namespace AvalonEdit.Pieces
1314
public class LineNumberMarginAdorner : Adorner
1415
{
1516

16-
public LineNumberMarginAdorner(LineNumberMarginWithCommands marginElement)
17+
public LineNumberMarginAdorner(LineNumberMarginWithCommands marginElement,
18+
System.Windows.Size lineNumberDisplaySize)
1719
: base(marginElement)
1820
{
21+
this.listView = new LineNumbersListView();
22+
this.listView.Width = lineNumberDisplaySize.Width; // constrain width
23+
this.AddVisualChild(this.listView); // this has to be there for events and interaction to work
24+
// update the adorner layer
25+
AdornerLayer.GetAdornerLayer(marginElement).Update();
26+
27+
// setup events that we will need to use to modify our list of line numbers
1928
marginElement.LineNumbersChangedDelayedEvent += MarginElement_LineNumbersChangedDelayedEvent;
20-
29+
marginElement.MaxLineNumberLengthChanged += MarginElement_MaxLineNumberLengthChanged;
30+
31+
// need to initially populate line numbers that are already there
32+
populateLineNumbers(marginElement.uiLineInfoList, this.listView.LineNumbers);
2133
}
2234

23-
public class LineNumberDisplayControlInfo
35+
private void MarginElement_MaxLineNumberLengthChanged(object sender, MaxLineNumberLengthChangedEventArgs args)
2436
{
25-
public LineNumberMarginWithCommands.LineInfo LineInfo { get; set; }
26-
public LineNumberDisplay Control { get; set; }
37+
// width of list needs to change
38+
this.listView.Width = args.NewSize.Width;
2739
}
2840

29-
private List<LineNumberDisplayControlInfo> Controls = new List<LineNumberDisplayControlInfo>();
30-
private List<Visual> visualChildTracker = new List<Visual>();
3141

32-
private void ClearVisualChilds()
42+
private void populateLineNumbers(List<LineInfo> textLineInfoList,
43+
ObservableCollection<LineNumberDisplayModel> visualLines)
3344
{
34-
foreach( var _child in this.visualChildTracker.ToList())
45+
// determine what needs to be created and what needs hidden
46+
var nonExistantTextLines = from t in textLineInfoList
47+
where !visualLines.Any(v => v.LineNumber == t.Number)
48+
select t;
49+
50+
var visualsToHide = from v in visualLines
51+
where !textLineInfoList.Any(t => t.Number == v.LineNumber)
52+
select v;
53+
54+
var visualsToShow = from v in visualLines
55+
where textLineInfoList.Any(t => t.Number == v.LineNumber)
56+
select v;
57+
58+
// create
59+
foreach (var t in nonExistantTextLines)
3560
{
36-
this.visualChildTracker.Remove(_child);
37-
this.RemoveVisualChild(_child);
61+
visualLines.Add(new LineNumberDisplayModel
62+
{
63+
IsInView = true,
64+
LineNumber = t.Number,
65+
ControlHeight = t.RenderSize.Height
66+
});
3867
}
39-
}
4068

41-
private void AddVisualChildWithTracking(Visual _child)
42-
{
43-
this.AddVisualChild(_child);
44-
this.visualChildTracker.Add(_child);
69+
// hide
70+
foreach (var v in visualsToHide)
71+
{
72+
v.IsInView = false;
73+
}
74+
75+
// show
76+
foreach (var v in visualsToShow)
77+
{
78+
v.IsInView = true;
79+
}
4580
}
4681

4782
private void MarginElement_LineNumbersChangedDelayedEvent(object sendor, EventArgs args)
4883
{
49-
this.Controls.Clear();
50-
this.ClearVisualChilds();
5184
var margin = sendor as LineNumberMarginWithCommands;
52-
if( margin != null && margin.uiLineInfoList != null)
53-
{
54-
foreach( var info in margin.uiLineInfoList)
55-
{
56-
var ctrl = new LineNumberDisplayControlInfo
57-
{
58-
LineInfo = info
59-
};
60-
61-
ctrl.Control = new LineNumberDisplay();
62-
ctrl.Control.Model.LineNumber = ctrl.LineInfo.Number;
63-
64-
this.Controls.Add(ctrl);
65-
this.AddVisualChildWithTracking(ctrl.Control);
66-
}
67-
68-
// update the adorner layer
69-
AdornerLayer.GetAdornerLayer(margin).Update();
70-
}
85+
populateLineNumbers(margin.uiLineInfoList, this.listView.LineNumbers);
7186
}
7287

7388

89+
private LineNumbersListView listView;
90+
7491

7592

7693
protected override int VisualChildrenCount
7794
{
7895
get
7996
{
80-
if(this.Controls.Any())
81-
{
82-
return this.Controls.Count;
83-
}else
84-
{
85-
return 0;
86-
}
97+
return 1;
8798
}
8899
}
89100

90101
protected override Visual GetVisualChild(int index)
91102
{
92-
return this.Controls[index].Control;
103+
if (index != 0) throw new ArgumentOutOfRangeException();
104+
return listView;
93105
}
94106

95107

96108
protected override Size MeasureOverride(Size constraint)
97109
{
98-
if(this.Controls.Any())
99-
{
100-
var last = this.Controls.Last();
101-
foreach( var ctrl in this.Controls)
102-
{
103-
ctrl.Control.Measure(constraint);
104-
}
105-
return last.Control.DesiredSize;
106-
}else
107-
{
108-
return new Size(0,0);
109-
}
110+
listView.Measure(constraint);
111+
return listView.DesiredSize;
110112
}
111113

112114

113115
protected override Size ArrangeOverride(Size finalSize)
114116
{
115-
116-
if(this.Controls.Any())
117-
{
118-
var last = this.Controls.Last();
119-
120-
foreach(var ctrl in this.Controls)
121-
{
122-
ctrl.Control.Arrange(new Rect(new Point(0, ctrl.LineInfo.uiYPos), finalSize));
123-
}
124-
125-
return new Size(last.Control.ActualWidth, last.Control.ActualHeight);
126-
}else
127-
{
128-
return new Size(0, 0);
129-
}
130-
117+
listView.Arrange(new Rect(new Point(0, 0), finalSize));
118+
return new Size(listView.ActualWidth, listView.ActualHeight);
131119
}
132120

133121
}

0 commit comments

Comments
 (0)