1
1
using System ;
2
2
using System . Collections . Generic ;
3
+ using System . Collections . ObjectModel ;
3
4
using System . Linq ;
4
5
using System . Text ;
5
6
using System . Threading . Tasks ;
@@ -13,121 +14,108 @@ namespace AvalonEdit.Pieces
13
14
public class LineNumberMarginAdorner : Adorner
14
15
{
15
16
16
- public LineNumberMarginAdorner ( LineNumberMarginWithCommands marginElement )
17
+ public LineNumberMarginAdorner ( LineNumberMarginWithCommands marginElement ,
18
+ System . Windows . Size lineNumberDisplaySize )
17
19
: base ( marginElement )
18
20
{
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
19
28
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 ) ;
21
33
}
22
34
23
- public class LineNumberDisplayControlInfo
35
+ private void MarginElement_MaxLineNumberLengthChanged ( object sender , MaxLineNumberLengthChangedEventArgs args )
24
36
{
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 ;
27
39
}
28
40
29
- private List < LineNumberDisplayControlInfo > Controls = new List < LineNumberDisplayControlInfo > ( ) ;
30
- private List < Visual > visualChildTracker = new List < Visual > ( ) ;
31
41
32
- private void ClearVisualChilds ( )
42
+ private void populateLineNumbers ( List < LineInfo > textLineInfoList ,
43
+ ObservableCollection < LineNumberDisplayModel > visualLines )
33
44
{
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 )
35
60
{
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
+ } ) ;
38
67
}
39
- }
40
68
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
+ }
45
80
}
46
81
47
82
private void MarginElement_LineNumbersChangedDelayedEvent ( object sendor , EventArgs args )
48
83
{
49
- this . Controls . Clear ( ) ;
50
- this . ClearVisualChilds ( ) ;
51
84
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 ) ;
71
86
}
72
87
73
88
89
+ private LineNumbersListView listView ;
90
+
74
91
75
92
76
93
protected override int VisualChildrenCount
77
94
{
78
95
get
79
96
{
80
- if ( this . Controls . Any ( ) )
81
- {
82
- return this . Controls . Count ;
83
- } else
84
- {
85
- return 0 ;
86
- }
97
+ return 1 ;
87
98
}
88
99
}
89
100
90
101
protected override Visual GetVisualChild ( int index )
91
102
{
92
- return this . Controls [ index ] . Control ;
103
+ if ( index != 0 ) throw new ArgumentOutOfRangeException ( ) ;
104
+ return listView ;
93
105
}
94
106
95
107
96
108
protected override Size MeasureOverride ( Size constraint )
97
109
{
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 ;
110
112
}
111
113
112
114
113
115
protected override Size ArrangeOverride ( Size finalSize )
114
116
{
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 ) ;
131
119
}
132
120
133
121
}
0 commit comments