Browse Source

SD-1592: folding controls are customizable

pull/15/head
Siegfried Pammer 15 years ago
parent
commit
272502e229
  1. 1
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
  2. 121
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Options/HighlightingOptions.xaml.cs
  3. 21
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingElementGenerator.cs
  4. 67
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingMargin.cs
  5. 18
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingMarginMarker.cs

1
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs

@ -511,6 +511,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
string language = this.SyntaxHighlighting != null ? this.SyntaxHighlighting.Name : null; string language = this.SyntaxHighlighting != null ? this.SyntaxHighlighting.Name : null;
CustomizableHighlightingColorizer.ApplyCustomizationsToDefaultElements(this, FetchCustomizations(language)); CustomizableHighlightingColorizer.ApplyCustomizationsToDefaultElements(this, FetchCustomizations(language));
BracketHighlightRenderer.ApplyCustomizationsToRendering(this.bracketRenderer, FetchCustomizations(language)); BracketHighlightRenderer.ApplyCustomizationsToRendering(this.bracketRenderer, FetchCustomizations(language));
HighlightingOptions.ApplyToFolding(this, FetchCustomizations(language));
this.TextArea.TextView.Redraw(); // manually redraw if default elements didn't change but customized highlightings did this.TextArea.TextView.Redraw(); // manually redraw if default elements didn't change but customized highlightings did
} }

121
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Options/HighlightingOptions.xaml.cs

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel; using System.ComponentModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -10,7 +11,9 @@ using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Media; using System.Windows.Media;
using System.Xml; using System.Xml;
using ICSharpCode.AvalonEdit.Editing; using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Folding;
using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Highlighting.Xshd; using ICSharpCode.AvalonEdit.Highlighting.Xshd;
using ICSharpCode.AvalonEdit.Rendering; using ICSharpCode.AvalonEdit.Rendering;
@ -32,14 +35,70 @@ namespace ICSharpCode.AvalonEdit.AddIn.Options
textEditor.Document.UndoStack.SizeLimit = 0; textEditor.Document.UndoStack.SizeLimit = 0;
textEditor.Options = CodeEditorOptions.Instance; textEditor.Options = CodeEditorOptions.Instance;
bracketHighlighter = new BracketHighlightRenderer(textEditor.TextArea.TextView); bracketHighlighter = new BracketHighlightRenderer(textEditor.TextArea.TextView);
foldingManager = FoldingManager.Install(textEditor.TextArea);
CodeEditorOptions.Instance.BindToTextEditor(textEditor); CodeEditorOptions.Instance.BindToTextEditor(textEditor);
} }
BracketHighlightRenderer bracketHighlighter; BracketHighlightRenderer bracketHighlighter;
FoldingManager foldingManager;
List<CustomizedHighlightingColor> customizationList; List<CustomizedHighlightingColor> customizationList;
#region Folding
// TODO : probably move this to a separate class!
public const string FoldingControls = "Folding controls";
public const string FoldingSelectedControls = "Selected folding controls";
public const string FoldingTextMarkers = "Folding markers";
static SolidColorBrush CreateFrozenBrush(Color color)
{
SolidColorBrush brush = new SolidColorBrush(color);
brush.Freeze();
return brush;
}
public static void ApplyToFolding(TextEditor editor, IEnumerable<CustomizedHighlightingColor> customisations)
{
bool assignedFoldingMarker = false, assignedSelectedFoldingControls = false, assignedFoldingTextMarkers = false;
editor.ClearValue(FoldingMargin.FoldingMarkerBrushProperty);
editor.ClearValue(FoldingMargin.FoldingMarkerBackgroundBrushProperty);
editor.ClearValue(FoldingMargin.SelectedFoldingMarkerBrushProperty);
editor.ClearValue(FoldingMargin.SelectedFoldingMarkerBackgroundBrushProperty);
FoldingElementGenerator.TextBrush = FoldingElementGenerator.DefaultTextBrush;
foreach (CustomizedHighlightingColor color in customisations) {
switch (color.Name) {
case FoldingControls:
if (assignedFoldingMarker)
continue;
assignedFoldingMarker = true;
if (color.Foreground != null)
editor.SetValue(FoldingMargin.FoldingMarkerBrushProperty, CreateFrozenBrush(color.Foreground.Value));
if (color.Background != null)
editor.SetValue(FoldingMargin.FoldingMarkerBackgroundBrushProperty, CreateFrozenBrush(color.Background.Value));
break;
case FoldingSelectedControls:
if (assignedSelectedFoldingControls)
continue;
assignedSelectedFoldingControls = true;
if (color.Foreground != null)
editor.SetValue(FoldingMargin.SelectedFoldingMarkerBrushProperty, CreateFrozenBrush(color.Foreground.Value));
if (color.Background != null)
editor.SetValue(FoldingMargin.SelectedFoldingMarkerBackgroundBrushProperty, CreateFrozenBrush(color.Background.Value));
break;
case FoldingTextMarkers:
if (assignedFoldingTextMarkers)
continue;
assignedFoldingTextMarkers = true;
if (color.Foreground != null)
FoldingElementGenerator.TextBrush = CreateFrozenBrush(color.Foreground.Value);
break;
}
}
}
#endregion
XshdSyntaxDefinition LoadBuiltinXshd(string name) XshdSyntaxDefinition LoadBuiltinXshd(string name)
{ {
using (Stream s = typeof(HighlightingManager).Assembly.GetManifestResourceStream(name)) { using (Stream s = typeof(HighlightingManager).Assembly.GetManifestResourceStream(name)) {
@ -193,6 +252,62 @@ namespace ICSharpCode.AvalonEdit.AddIn.Options
bracketHighlight = new CustomizedHighlightingItem(customizationList, bracketHighlight, language, canSetFont: false); bracketHighlight = new CustomizedHighlightingItem(customizationList, bracketHighlight, language, canSetFont: false);
bracketHighlight.PropertyChanged += item_PropertyChanged; bracketHighlight.PropertyChanged += item_PropertyChanged;
listBox.Items.Add(bracketHighlight); listBox.Items.Add(bracketHighlight);
// Create entry for "Folding controls"
IHighlightingItem foldingControls = new SimpleHighlightingItem(
FoldingControls,
ta => {
ta.Document.Text = "This" + Environment.NewLine +
"is a folding" + Environment.NewLine +
"example";
foldingManager.CreateFolding(0, 10);
})
{
Foreground = Colors.Gray,
Background = Colors.White
};
foldingControls = new CustomizedHighlightingItem(customizationList, foldingControls, null, canSetFont: false);
if (language != null)
foldingControls = new CustomizedHighlightingItem(customizationList, foldingControls, language, canSetFont: false);
foldingControls.PropertyChanged += item_PropertyChanged;
listBox.Items.Add(foldingControls);
// Create entry for "Selected folding controls"
IHighlightingItem selectedFoldingControls = new SimpleHighlightingItem(
FoldingSelectedControls,
ta => {
ta.Document.Text = "This" + Environment.NewLine +
"is a folding" + Environment.NewLine +
"example";
foldingManager.CreateFolding(0, 10);
})
{
Foreground = Colors.Black,
Background = Colors.White
};
selectedFoldingControls = new CustomizedHighlightingItem(customizationList, selectedFoldingControls, null, canSetFont: false);
if (language != null)
selectedFoldingControls = new CustomizedHighlightingItem(customizationList, selectedFoldingControls, language, canSetFont: false);
selectedFoldingControls.PropertyChanged += item_PropertyChanged;
listBox.Items.Add(selectedFoldingControls);
// Create entry for "Folding text markers"
IHighlightingItem foldingTextMarker = new SimpleHighlightingItem(
FoldingTextMarkers,
ta => {
ta.Document.Text = "This" + Environment.NewLine +
"is a folding" + Environment.NewLine +
"example";
foldingManager.CreateFolding(0, 10).IsFolded = true;
})
{
Foreground = Colors.Gray
};
foldingTextMarker = new CustomizedHighlightingItem(customizationList, foldingTextMarker, null, canSetFont: false, canSetBackground: false);
if (language != null)
foldingControls = new CustomizedHighlightingItem(customizationList, foldingTextMarker, language, canSetFont: false, canSetBackground: false);
foldingTextMarker.PropertyChanged += item_PropertyChanged;
listBox.Items.Add(foldingTextMarker);
} }
void item_PropertyChanged(object sender, PropertyChangedEventArgs e) void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
@ -226,8 +341,10 @@ namespace ICSharpCode.AvalonEdit.AddIn.Options
if (xshd != null) { if (xshd != null) {
var customizationsForCurrentLanguage = customizationList.Where(c => c.Language == null || c.Language == xshd.Name); var customizationsForCurrentLanguage = customizationList.Where(c => c.Language == null || c.Language == xshd.Name);
CustomizableHighlightingColorizer.ApplyCustomizationsToDefaultElements(textEditor, customizationsForCurrentLanguage); CustomizableHighlightingColorizer.ApplyCustomizationsToDefaultElements(textEditor, customizationsForCurrentLanguage);
ApplyToFolding(textEditor, customizationsForCurrentLanguage);
var item = (IHighlightingItem)listBox.SelectedItem; var item = (IHighlightingItem)listBox.SelectedItem;
TextView textView = textEditor.TextArea.TextView; TextView textView = textEditor.TextArea.TextView;
foldingManager.Clear();
textView.LineTransformers.Remove(colorizer); textView.LineTransformers.Remove(colorizer);
colorizer = null; colorizer = null;
if (item != null) { if (item != null) {

21
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingElementGenerator.cs

@ -99,10 +99,10 @@ namespace ICSharpCode.AvalonEdit.Folding
if (string.IsNullOrEmpty(title)) if (string.IsNullOrEmpty(title))
title = "..."; title = "...";
var p = new VisualLineElementTextRunProperties(CurrentContext.GlobalTextRunProperties); var p = new VisualLineElementTextRunProperties(CurrentContext.GlobalTextRunProperties);
p.SetForegroundBrush(Brushes.Gray); p.SetForegroundBrush(textBrush);
var textFormatter = TextFormatterFactory.Create(CurrentContext.TextView); var textFormatter = TextFormatterFactory.Create(CurrentContext.TextView);
var text = FormattedTextElement.PrepareText(textFormatter, title, p); var text = FormattedTextElement.PrepareText(textFormatter, title, p);
return new FoldingLineElement(foldingSection, text, foldedUntil - offset); return new FoldingLineElement(foldingSection, text, foldedUntil - offset) { textBrush = textBrush };
} else { } else {
return null; return null;
} }
@ -112,6 +112,8 @@ namespace ICSharpCode.AvalonEdit.Folding
{ {
readonly FoldingSection fs; readonly FoldingSection fs;
internal Brush textBrush;
public FoldingLineElement(FoldingSection fs, TextLine text, int documentLength) : base(text, documentLength) public FoldingLineElement(FoldingSection fs, TextLine text, int documentLength) : base(text, documentLength)
{ {
this.fs = fs; this.fs = fs;
@ -119,7 +121,7 @@ namespace ICSharpCode.AvalonEdit.Folding
public override TextRun CreateTextRun(int startVisualColumn, ITextRunConstructionContext context) public override TextRun CreateTextRun(int startVisualColumn, ITextRunConstructionContext context)
{ {
return new FoldingLineTextRun(this, this.TextRunProperties); return new FoldingLineTextRun(this, this.TextRunProperties) { textBrush = textBrush };
} }
protected internal override void OnMouseDown(MouseButtonEventArgs e) protected internal override void OnMouseDown(MouseButtonEventArgs e)
@ -135,6 +137,8 @@ namespace ICSharpCode.AvalonEdit.Folding
sealed class FoldingLineTextRun : FormattedTextRun sealed class FoldingLineTextRun : FormattedTextRun
{ {
internal Brush textBrush;
public FoldingLineTextRun(FormattedTextElement element, TextRunProperties properties) public FoldingLineTextRun(FormattedTextElement element, TextRunProperties properties)
: base(element, properties) : base(element, properties)
{ {
@ -144,9 +148,18 @@ namespace ICSharpCode.AvalonEdit.Folding
{ {
var metrics = Format(double.PositiveInfinity); var metrics = Format(double.PositiveInfinity);
Rect r = new Rect(origin.X, origin.Y - metrics.Baseline, metrics.Width, metrics.Height); Rect r = new Rect(origin.X, origin.Y - metrics.Baseline, metrics.Width, metrics.Height);
drawingContext.DrawRectangle(null, new Pen(Brushes.Gray, 1), r); drawingContext.DrawRectangle(null, new Pen(textBrush, 1), r);
base.Draw(drawingContext, origin, rightToLeft, sideways); base.Draw(drawingContext, origin, rightToLeft, sideways);
} }
} }
public static readonly Brush DefaultTextBrush = Brushes.Gray;
static Brush textBrush = DefaultTextBrush;
public static Brush TextBrush {
get { return textBrush; }
set { textBrush = value; }
}
} }
} }

67
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingMargin.cs

@ -27,6 +27,54 @@ namespace ICSharpCode.AvalonEdit.Folding
internal const double SizeFactor = Constants.PixelPerPoint; internal const double SizeFactor = Constants.PixelPerPoint;
#region Brushes
public static readonly DependencyProperty FoldingMarkerBrushProperty =
DependencyProperty.RegisterAttached("FoldingMarkerBrush", typeof(Brush), typeof(FoldingMargin),
new FrameworkPropertyMetadata(Brushes.Gray, FrameworkPropertyMetadataOptions.Inherits, OnUpdateBrushes));
public Brush FoldingMarkerBrush {
get { return (Brush)GetValue(FoldingMarkerBrushProperty); }
set { SetValue(FoldingMarkerBrushProperty, value); }
}
public static readonly DependencyProperty FoldingMarkerBackgroundBrushProperty =
DependencyProperty.RegisterAttached("FoldingMarkerBackgroundBrush", typeof(Brush), typeof(FoldingMargin),
new FrameworkPropertyMetadata(Brushes.White, FrameworkPropertyMetadataOptions.Inherits, OnUpdateBrushes));
public Brush FoldingMarkerBackgroundBrush {
get { return (Brush)GetValue(FoldingMarkerBackgroundBrushProperty); }
set { SetValue(FoldingMarkerBackgroundBrushProperty, value); }
}
public static readonly DependencyProperty SelectedFoldingMarkerBrushProperty =
DependencyProperty.RegisterAttached("SelectedFoldingMarkerBrush",
typeof(Brush), typeof(FoldingMargin),
new FrameworkPropertyMetadata(Brushes.Black, FrameworkPropertyMetadataOptions.Inherits, OnUpdateBrushes));
public Brush SelectedFoldingMarkerBrush {
get { return (Brush)GetValue(SelectedFoldingMarkerBrushProperty); }
set { SetValue(SelectedFoldingMarkerBrushProperty, value); }
}
public static readonly DependencyProperty SelectedFoldingMarkerBackgroundBrushProperty =
DependencyProperty.RegisterAttached("SelectedFoldingMarkerBackgroundBrush",
typeof(Brush), typeof(FoldingMargin),
new FrameworkPropertyMetadata(Brushes.White, FrameworkPropertyMetadataOptions.Inherits, OnUpdateBrushes));
public Brush SelectedFoldingMarkerBackgroundBrush {
get { return (Brush)GetValue(SelectedFoldingMarkerBackgroundBrushProperty); }
set { SetValue(SelectedFoldingMarkerBackgroundBrushProperty, value); }
}
static void OnUpdateBrushes(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.Property.Name == FoldingMarkerBrushProperty.Name)
foldingControlPen = MakeFrozenPen((Brush)e.NewValue);
if (e.Property.Name == SelectedFoldingMarkerBrushProperty.Name)
selectedFoldingControlPen = MakeFrozenPen((Brush)e.NewValue);
}
#endregion
/// <inheritdoc/> /// <inheritdoc/>
protected override Size MeasureOverride(Size availableSize) protected override Size MeasureOverride(Size availableSize)
{ {
@ -85,6 +133,7 @@ namespace ICSharpCode.AvalonEdit.Folding
VisualLine = line, VisualLine = line,
FoldingSection = fs FoldingSection = fs
}; };
markers.Add(m); markers.Add(m);
AddVisualChild(m); AddVisualChild(m);
@ -108,8 +157,8 @@ namespace ICSharpCode.AvalonEdit.Folding
return markers[index]; return markers[index];
} }
static readonly Pen grayPen = MakeFrozenPen(Brushes.Gray); static Pen foldingControlPen = MakeFrozenPen((Brush)FoldingMarkerBrushProperty.DefaultMetadata.DefaultValue);
static readonly Pen blackPen = MakeFrozenPen(Brushes.Black); static Pen selectedFoldingControlPen = MakeFrozenPen((Brush)SelectedFoldingMarkerBrushProperty.DefaultMetadata.DefaultValue);
static Pen MakeFrozenPen(Brush brush) static Pen MakeFrozenPen(Brush brush)
{ {
@ -152,7 +201,7 @@ namespace ICSharpCode.AvalonEdit.Folding
if (end < viewEndOffset && !fs.IsFolded) { if (end < viewEndOffset && !fs.IsFolded) {
int textLineNr = GetTextLineIndexFromOffset(allTextLines, end); int textLineNr = GetTextLineIndexFromOffset(allTextLines, end);
if (textLineNr >= 0) { if (textLineNr >= 0) {
endMarker[textLineNr] = grayPen; endMarker[textLineNr] = foldingControlPen;
} }
} }
if (end > maxEndOffset && fs.StartOffset < viewStartOffset) { if (end > maxEndOffset && fs.StartOffset < viewStartOffset) {
@ -162,12 +211,12 @@ namespace ICSharpCode.AvalonEdit.Folding
if (maxEndOffset > 0) { if (maxEndOffset > 0) {
if (maxEndOffset > viewEndOffset) { if (maxEndOffset > viewEndOffset) {
for (int i = 0; i < colors.Length; i++) { for (int i = 0; i < colors.Length; i++) {
colors[i] = grayPen; colors[i] = foldingControlPen;
} }
} else { } else {
int maxTextLine = GetTextLineIndexFromOffset(allTextLines, maxEndOffset); int maxTextLine = GetTextLineIndexFromOffset(allTextLines, maxEndOffset);
for (int i = 0; i <= maxTextLine; i++) { for (int i = 0; i <= maxTextLine; i++) {
colors[i] = grayPen; colors[i] = foldingControlPen;
} }
} }
} }
@ -183,17 +232,17 @@ namespace ICSharpCode.AvalonEdit.Folding
int endTextLineNr = GetTextLineIndexFromOffset(allTextLines, end); int endTextLineNr = GetTextLineIndexFromOffset(allTextLines, end);
if (!marker.FoldingSection.IsFolded && endTextLineNr >= 0) { if (!marker.FoldingSection.IsFolded && endTextLineNr >= 0) {
if (marker.IsMouseDirectlyOver) if (marker.IsMouseDirectlyOver)
endMarker[endTextLineNr] = blackPen; endMarker[endTextLineNr] = selectedFoldingControlPen;
else if (endMarker[endTextLineNr] == null) else if (endMarker[endTextLineNr] == null)
endMarker[endTextLineNr] = grayPen; endMarker[endTextLineNr] = foldingControlPen;
} }
int startTextLineNr = GetTextLineIndexFromOffset(allTextLines, marker.FoldingSection.StartOffset); int startTextLineNr = GetTextLineIndexFromOffset(allTextLines, marker.FoldingSection.StartOffset);
if (startTextLineNr >= 0) { if (startTextLineNr >= 0) {
for (int i = startTextLineNr + 1; i < colors.Length && i - 1 != endTextLineNr; i++) { for (int i = startTextLineNr + 1; i < colors.Length && i - 1 != endTextLineNr; i++) {
if (marker.IsMouseDirectlyOver) if (marker.IsMouseDirectlyOver)
colors[i] = blackPen; colors[i] = selectedFoldingControlPen;
else if (colors[i] == null) else if (colors[i] == null)
colors[i] = grayPen; colors[i] = foldingControlPen;
} }
} }
} }

18
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingMarginMarker.cs

@ -53,25 +53,27 @@ namespace ICSharpCode.AvalonEdit.Folding
protected override void OnRender(DrawingContext drawingContext) protected override void OnRender(DrawingContext drawingContext)
{ {
Pen blackPen = new Pen(Brushes.Black, 1); FoldingMargin margin = VisualParent as FoldingMargin;
blackPen.StartLineCap = PenLineCap.Square; Pen activePen = new Pen(margin.SelectedFoldingMarkerBrush, 1);
blackPen.EndLineCap = PenLineCap.Square; Pen inactivePen = new Pen(margin.FoldingMarkerBrush, 1);
activePen.StartLineCap = inactivePen.StartLineCap = PenLineCap.Square;
activePen.EndLineCap = inactivePen.EndLineCap = PenLineCap.Square;
Size pixelSize = PixelSnapHelpers.GetPixelSize(this); Size pixelSize = PixelSnapHelpers.GetPixelSize(this);
Rect rect = new Rect(pixelSize.Width / 2, Rect rect = new Rect(pixelSize.Width / 2,
pixelSize.Height / 2, pixelSize.Height / 2,
this.RenderSize.Width - pixelSize.Width, this.RenderSize.Width - pixelSize.Width,
this.RenderSize.Height - pixelSize.Height); this.RenderSize.Height - pixelSize.Height);
drawingContext.DrawRectangle(Brushes.White, drawingContext.DrawRectangle(
IsMouseDirectlyOver ? blackPen : new Pen(Brushes.Gray, 1), IsMouseDirectlyOver ? margin.SelectedFoldingMarkerBackgroundBrush : margin.FoldingMarkerBackgroundBrush,
rect); IsMouseDirectlyOver ? activePen : inactivePen, rect);
double middleX = rect.Left + rect.Width / 2; double middleX = rect.Left + rect.Width / 2;
double middleY = rect.Top + rect.Height / 2; double middleY = rect.Top + rect.Height / 2;
double space = PixelSnapHelpers.Round(rect.Width / 8, pixelSize.Width) + pixelSize.Width; double space = PixelSnapHelpers.Round(rect.Width / 8, pixelSize.Width) + pixelSize.Width;
drawingContext.DrawLine(blackPen, drawingContext.DrawLine(activePen,
new Point(rect.Left + space, middleY), new Point(rect.Left + space, middleY),
new Point(rect.Right - space, middleY)); new Point(rect.Right - space, middleY));
if (!isExpanded) { if (!isExpanded) {
drawingContext.DrawLine(blackPen, drawingContext.DrawLine(activePen,
new Point(middleX, rect.Top + space), new Point(middleX, rect.Top + space),
new Point(middleX, rect.Bottom - space)); new Point(middleX, rect.Bottom - space));
} }

Loading…
Cancel
Save