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.

170 lines
5.9 KiB

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using Microsoft.Windows.Controls.Core;
using System.Windows.Input;
namespace Microsoft.Windows.Controls
{
public class RichTextBoxFormatBarManager : DependencyObject
{
#region Members
private global::System.Windows.Controls.RichTextBox _richTextBox;
private UIElementAdorner<Control> _adorner;
private IRichTextBoxFormatBar _toolbar;
#endregion //Members
#region Properties
#region FormatBar
public static readonly DependencyProperty FormatBarProperty = DependencyProperty.RegisterAttached("FormatBar", typeof(IRichTextBoxFormatBar), typeof(RichTextBox), new PropertyMetadata(null, OnFormatBarPropertyChanged));
public static void SetFormatBar(UIElement element, IRichTextBoxFormatBar value)
{
element.SetValue(FormatBarProperty, value);
}
public static IRichTextBoxFormatBar GetFormatBar(UIElement element)
{
return (IRichTextBoxFormatBar)element.GetValue(FormatBarProperty);
}
private static void OnFormatBarPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
global::System.Windows.Controls.RichTextBox rtb = d as global::System.Windows.Controls.RichTextBox;
if (rtb == null)
throw new Exception("A FormatBar can only be applied to a RichTextBox.");
RichTextBoxFormatBarManager manager = new RichTextBoxFormatBarManager();
manager.AttachFormatBarToRichtextBox(rtb, e.NewValue as IRichTextBoxFormatBar);
}
#endregion //FormatBar
bool AdornerIsVisible
{
get { return _adorner.Visibility == Visibility.Visible; }
}
#endregion //Properties
#region Event Handlers
void RichTextBox_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
TextRange selectedText = new TextRange(_richTextBox.Selection.Start, _richTextBox.Selection.End);
if (selectedText.Text.Length > 0 && !String.IsNullOrWhiteSpace(selectedText.Text))
{
ShowAdorner();
}
else
{
HideAdorner();
}
}
void RichTextBox_PreviewMouseMove(object sender, MouseEventArgs e)
{
//if the mouse moves outside the richtextbox bounds hide the adorner
//though this deosn't always work, especially if the user moves the mouse very quickly.
//need to find a better solution, but this will work for now.
Point p = e.GetPosition(_richTextBox);
if (p.X <= 5.0 || p.X >= _richTextBox.ActualWidth - 5 || p.Y <= 3.0 || p.Y >= _richTextBox.ActualHeight - 3)
HideAdorner();
}
#endregion //Event Handlers
#region Methods
/// <summary>
/// Attaches a FormatBar to a RichtextBox
/// </summary>
/// <param name="richTextBox">The RichtextBox to attach to.</param>
/// <param name="formatBar">The Formatbar to attach.</param>
private void AttachFormatBarToRichtextBox(global::System.Windows.Controls.RichTextBox richTextBox, IRichTextBoxFormatBar formatBar)
{
_richTextBox = richTextBox;
_richTextBox.PreviewMouseMove += RichTextBox_PreviewMouseMove;
_richTextBox.PreviewMouseLeftButtonUp += RichTextBox_PreviewMouseLeftButtonUp;
_adorner = new UIElementAdorner<Control>(_richTextBox);
formatBar.Target = _richTextBox;
_toolbar = formatBar;
}
/// <summary>
/// Shows the FormatBar
/// </summary>
void ShowAdorner()
{
VerifyAdornerLayer();
Control adorningEditor = _toolbar as Control;
_adorner.Child = adorningEditor;
_adorner.Visibility = Visibility.Visible;
PositionFormatBar(adorningEditor);
}
/// <summary>
/// Positions the FormatBar so that is does not go outside the bounds of the RichTextBox or covers the selected text
/// </summary>
/// <param name="adorningEditor"></param>
private void PositionFormatBar(Control adorningEditor)
{
Point mousePosition = Mouse.GetPosition(_richTextBox);
double left = mousePosition.X;
double top = (mousePosition.Y - 15) - adorningEditor.ActualHeight;
//top
if (top < 0)
{
top = mousePosition.Y + 10;
}
//right boundary
if (left + adorningEditor.ActualWidth > _richTextBox.ActualWidth - 20)
{
left = left - (adorningEditor.ActualWidth - (_richTextBox.ActualWidth - left));
}
_adorner.SetOffsets(left, top);
}
/// <summary>
/// Ensures that the IRichTextFormatBar is in the adorner layer.
/// </summary>
/// <returns>True if the IRichTextFormatBar 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;
}
/// <summary>
/// Hides the IRichTextFormatBar that is in the adornor layer.
/// </summary>
void HideAdorner()
{
if (AdornerIsVisible)
{
_adorner.Visibility = Visibility.Collapsed;
_adorner.Child = null;
}
}
#endregion //Methods
}
}