All the controls missing in WPF. Over 1 million downloads.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

107 lines
3.2 KiB

using System;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows;
namespace Microsoft.Windows.Controls.Formatting
{
internal class FormatToolbarManager
{
RichTextBox _richTextBox;
readonly UIElementAdorner<Control> _adorner;
FormatToolbar toolbar;
bool AdornerIsVisible
{
get { return _adorner.Visibility == Visibility.Visible; }
}
public FormatToolbarManager(RichTextBox richTextBox)
{
_richTextBox = richTextBox;
_adorner = new UIElementAdorner<Control>(richTextBox);
toolbar = new FormatToolbar(richTextBox);
AttachToRichtextBox();
}
private void AttachToRichtextBox()
{
_richTextBox.Selection.Changed += Selection_Changed;
}
void Selection_Changed(object sender, EventArgs e)
{
TextRange selectedText = new TextRange(_richTextBox.Selection.Start, _richTextBox.Selection.End);
if (selectedText.Text.Length > 0)
{
VerifyAdorner();
}
else
{
HideAdorner();
}
}
//TODO: refactor
void VerifyAdorner()
{
VerifyAdornerLayer();
Control adorningEditor = toolbar;
_adorner.Child = adorningEditor;
_adorner.Visibility = Visibility.Visible;
Rect wordBoundary = _richTextBox.Selection.End.GetPositionAtOffset(0, LogicalDirection.Backward).GetCharacterRect(LogicalDirection.Backward);
double left = wordBoundary.X;
double top = (wordBoundary.Y + wordBoundary.Height) - toolbar.ActualHeight;
//top boundary
if (top < 0)
{
top = wordBoundary.Y + wordBoundary.Height;
}
//right boundary
if (left + toolbar.ActualWidth > _richTextBox.ActualWidth - 20)
{
left = left - toolbar.ActualWidth;
top = wordBoundary.Y + wordBoundary.Height + 5;
}
//bottom boundary
if (top + toolbar.ActualHeight > _richTextBox.ActualHeight - 20)
{
top = wordBoundary.Y - (toolbar.ActualHeight + wordBoundary.Height);
}
_adorner.SetOffsets(left, top);
}
/// <summary>
/// Ensures that the adorner is in the adorner layer.
/// </summary>
/// <returns>True if the adorner is in the adorner layer, else false.</returns>
bool VerifyAdornerLayer()
{
if (_adorner.Parent != null)
return true;
AdornerLayer layer = AdornerLayer.GetAdornerLayer(_richTextBox);
if (layer == null)
return false;
layer.Add(_adorner);
return true;
}
void HideAdorner()
{
if (this.AdornerIsVisible)
{
_adorner.Visibility = Visibility.Collapsed;
_adorner.Child = null;
}
}
}
}