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.
447 lines
15 KiB
447 lines
15 KiB
/*************************************************************************************
|
|
|
|
Extended WPF Toolkit
|
|
|
|
Copyright (C) 2007-2013 Xceed Software Inc.
|
|
|
|
This program is provided to you under the terms of the Microsoft Public
|
|
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
|
|
|
|
For more features, controls, and fast professional support,
|
|
pick up the Plus Edition at http://xceed.com/wpf_toolkit
|
|
|
|
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
|
|
|
|
***********************************************************************************/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Windows.Controls;
|
|
using System.Windows;
|
|
using Xceed.Wpf.Toolkit.Core.Utilities;
|
|
using System.Windows.Media;
|
|
using System.Windows.Documents;
|
|
using System.Windows.Controls.Primitives;
|
|
using Xceed.Wpf.Toolkit.Core;
|
|
|
|
namespace Xceed.Wpf.Toolkit
|
|
{
|
|
public class RichTextBoxFormatBar : Control, IRichTextBoxFormatBar
|
|
{
|
|
#region Members
|
|
private ComboBox _cmbFontFamilies;
|
|
private ComboBox _cmbFontSizes;
|
|
private ColorPicker _cmbFontBackgroundColor;
|
|
private ColorPicker _cmbFontColor;
|
|
|
|
private ToggleButton _btnNumbers;
|
|
private ToggleButton _btnBullets;
|
|
private ToggleButton _btnBold;
|
|
private ToggleButton _btnItalic;
|
|
private ToggleButton _btnUnderline;
|
|
private ToggleButton _btnAlignLeft;
|
|
private ToggleButton _btnAlignCenter;
|
|
private ToggleButton _btnAlignRight;
|
|
|
|
private Thumb _dragWidget;
|
|
private bool _waitingForMouseOver;
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
public static double[] FontSizes
|
|
{
|
|
get
|
|
{
|
|
return new double[] {
|
|
3.0, 4.0, 5.0, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5,
|
|
10.0, 10.5, 11.0, 11.5, 12.0, 12.5, 13.0, 13.5, 14.0, 15.0,
|
|
16.0, 17.0, 18.0, 19.0, 20.0, 22.0, 24.0, 26.0, 28.0, 30.0,
|
|
32.0, 34.0, 36.0, 38.0, 40.0, 44.0, 48.0, 52.0, 56.0, 60.0, 64.0, 68.0, 72.0, 76.0,
|
|
80.0, 88.0, 96.0, 104.0, 112.0, 120.0, 128.0, 136.0, 144.0
|
|
};
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Constructors
|
|
|
|
static RichTextBoxFormatBar()
|
|
{
|
|
DefaultStyleKeyProperty.OverrideMetadata( typeof( RichTextBoxFormatBar ), new FrameworkPropertyMetadata( typeof( RichTextBoxFormatBar ) ) );
|
|
}
|
|
|
|
#endregion //Constructors
|
|
|
|
#region Event Hanlders
|
|
|
|
private void FontFamily_SelectionChanged( object sender, SelectionChangedEventArgs e )
|
|
{
|
|
if( e.AddedItems.Count == 0 )
|
|
return;
|
|
|
|
FontFamily editValue = ( FontFamily )e.AddedItems[ 0 ];
|
|
ApplyPropertyValueToSelectedText( TextElement.FontFamilyProperty, editValue );
|
|
_waitingForMouseOver = true;
|
|
}
|
|
|
|
private void FontSize_SelectionChanged( object sender, SelectionChangedEventArgs e )
|
|
{
|
|
if( e.AddedItems.Count == 0 )
|
|
return;
|
|
|
|
ApplyPropertyValueToSelectedText( TextElement.FontSizeProperty, e.AddedItems[ 0 ] );
|
|
_waitingForMouseOver = true;
|
|
}
|
|
|
|
void FontColor_SelectedColorChanged( object sender, RoutedPropertyChangedEventArgs<Color?> e )
|
|
{
|
|
Color? selectedColor = ( Color? )e.NewValue;
|
|
ApplyPropertyValueToSelectedText( TextElement.ForegroundProperty, selectedColor.HasValue ? new SolidColorBrush( selectedColor.Value ) : null );
|
|
_waitingForMouseOver = true;
|
|
}
|
|
|
|
private void FontBackgroundColor_SelectedColorChanged( object sender, RoutedPropertyChangedEventArgs<Color?> e )
|
|
{
|
|
Color? selectedColor = ( Color? )e.NewValue;
|
|
ApplyPropertyValueToSelectedText( TextElement.BackgroundProperty, selectedColor.HasValue ? new SolidColorBrush( selectedColor.Value ) : null );
|
|
_waitingForMouseOver = true;
|
|
}
|
|
|
|
private void Bullets_Clicked( object sender, RoutedEventArgs e )
|
|
{
|
|
if( BothSelectionListsAreChecked() )
|
|
{
|
|
_btnNumbers.IsChecked = false;
|
|
}
|
|
}
|
|
|
|
private void Numbers_Clicked( object sender, RoutedEventArgs e )
|
|
{
|
|
if( BothSelectionListsAreChecked() )
|
|
{
|
|
_btnBullets.IsChecked = false;
|
|
}
|
|
}
|
|
|
|
private void DragWidget_DragDelta( object sender, DragDeltaEventArgs e )
|
|
{
|
|
ProcessMove( e );
|
|
}
|
|
|
|
protected override void OnMouseEnter( System.Windows.Input.MouseEventArgs e )
|
|
{
|
|
base.OnMouseEnter( e );
|
|
_waitingForMouseOver = false;
|
|
}
|
|
|
|
#endregion //Event Hanlders
|
|
|
|
#region Methods
|
|
|
|
public override void OnApplyTemplate()
|
|
{
|
|
base.OnApplyTemplate();
|
|
|
|
if( _dragWidget != null )
|
|
{
|
|
_dragWidget.DragDelta -= new DragDeltaEventHandler( DragWidget_DragDelta );
|
|
}
|
|
|
|
if( _cmbFontFamilies != null )
|
|
{
|
|
_cmbFontFamilies.SelectionChanged -= new SelectionChangedEventHandler( FontFamily_SelectionChanged );
|
|
}
|
|
|
|
if( _cmbFontSizes != null )
|
|
{
|
|
_cmbFontSizes.SelectionChanged -= new SelectionChangedEventHandler( FontSize_SelectionChanged );
|
|
}
|
|
|
|
if( _btnBullets != null )
|
|
{
|
|
_btnBullets.Click -= new RoutedEventHandler( Bullets_Clicked );
|
|
}
|
|
|
|
if( _btnNumbers != null )
|
|
{
|
|
_btnNumbers.Click -= new RoutedEventHandler( Numbers_Clicked );
|
|
}
|
|
|
|
if( _cmbFontBackgroundColor != null )
|
|
{
|
|
_cmbFontBackgroundColor.SelectedColorChanged -= new RoutedPropertyChangedEventHandler<Color?>( FontBackgroundColor_SelectedColorChanged );
|
|
}
|
|
|
|
if( _cmbFontColor != null )
|
|
{
|
|
_cmbFontColor.SelectedColorChanged -= new RoutedPropertyChangedEventHandler<Color?>( FontColor_SelectedColorChanged );
|
|
}
|
|
|
|
this.GetTemplateComponent( ref _cmbFontFamilies, "_cmbFontFamilies" );
|
|
this.GetTemplateComponent( ref _cmbFontSizes, "_cmbFontSizes" );
|
|
this.GetTemplateComponent( ref _cmbFontBackgroundColor, "_cmbFontBackgroundColor" );
|
|
this.GetTemplateComponent( ref _cmbFontColor, "_cmbFontColor" );
|
|
this.GetTemplateComponent( ref _btnNumbers, "_btnNumbers" );
|
|
this.GetTemplateComponent( ref _btnBullets, "_btnBullets" );
|
|
this.GetTemplateComponent( ref _btnBold, "_btnBold" );
|
|
this.GetTemplateComponent( ref _btnItalic, "_btnItalic" );
|
|
this.GetTemplateComponent( ref _btnUnderline, "_btnUnderline" );
|
|
this.GetTemplateComponent( ref _btnAlignLeft, "_btnAlignLeft" );
|
|
this.GetTemplateComponent( ref _btnAlignCenter, "_btnAlignCenter" );
|
|
this.GetTemplateComponent( ref _btnAlignRight, "_btnAlignRight" );
|
|
this.GetTemplateComponent( ref _dragWidget, "_dragWidget" );
|
|
|
|
if( _dragWidget != null )
|
|
{
|
|
_dragWidget.DragDelta += new DragDeltaEventHandler( DragWidget_DragDelta );
|
|
}
|
|
|
|
if( _cmbFontFamilies != null )
|
|
{
|
|
_cmbFontFamilies.ItemsSource = FontUtilities.Families.OrderBy( fontFamily => fontFamily.Source );
|
|
_cmbFontFamilies.SelectionChanged += new SelectionChangedEventHandler( FontFamily_SelectionChanged );
|
|
}
|
|
|
|
if( _cmbFontSizes != null )
|
|
{
|
|
_cmbFontSizes.ItemsSource = FontSizes;
|
|
_cmbFontSizes.SelectionChanged += new SelectionChangedEventHandler( FontSize_SelectionChanged );
|
|
}
|
|
|
|
if( _btnBullets != null )
|
|
{
|
|
_btnBullets.Click += new RoutedEventHandler( Bullets_Clicked );
|
|
}
|
|
|
|
if( _btnNumbers != null )
|
|
{
|
|
_btnNumbers.Click += new RoutedEventHandler( Numbers_Clicked );
|
|
}
|
|
|
|
if( _cmbFontBackgroundColor != null )
|
|
{
|
|
_cmbFontBackgroundColor.SelectedColorChanged += new RoutedPropertyChangedEventHandler<Color?>( FontBackgroundColor_SelectedColorChanged );
|
|
}
|
|
|
|
if( _cmbFontColor != null )
|
|
{
|
|
_cmbFontColor.SelectedColorChanged += new RoutedPropertyChangedEventHandler<Color?>( FontColor_SelectedColorChanged );
|
|
}
|
|
|
|
// Update the ComboBoxes when changing themes.
|
|
this.Update();
|
|
}
|
|
|
|
private void GetTemplateComponent<T>( ref T partMember, string partName ) where T : class
|
|
{
|
|
partMember = ( this.Template != null )
|
|
? this.Template.FindName( partName, this ) as T
|
|
: null;
|
|
}
|
|
|
|
private void UpdateToggleButtonState()
|
|
{
|
|
UpdateItemCheckedState( _btnBold, TextElement.FontWeightProperty, FontWeights.Bold );
|
|
UpdateItemCheckedState( _btnItalic, TextElement.FontStyleProperty, FontStyles.Italic );
|
|
UpdateItemCheckedState( _btnUnderline, Inline.TextDecorationsProperty, TextDecorations.Underline );
|
|
|
|
UpdateItemCheckedState( _btnAlignLeft, Paragraph.TextAlignmentProperty, TextAlignment.Left );
|
|
UpdateItemCheckedState( _btnAlignCenter, Paragraph.TextAlignmentProperty, TextAlignment.Center );
|
|
UpdateItemCheckedState( _btnAlignRight, Paragraph.TextAlignmentProperty, TextAlignment.Right );
|
|
}
|
|
|
|
void UpdateItemCheckedState( ToggleButton button, DependencyProperty formattingProperty, object expectedValue )
|
|
{
|
|
object currentValue = DependencyProperty.UnsetValue;
|
|
if( ( Target != null ) && ( Target.Selection != null ) )
|
|
{
|
|
currentValue = Target.Selection.GetPropertyValue( formattingProperty );
|
|
}
|
|
|
|
if( currentValue == DependencyProperty.UnsetValue )
|
|
return;
|
|
|
|
button.IsChecked = ( currentValue == null )
|
|
? false
|
|
: currentValue != null && currentValue.Equals( expectedValue );
|
|
}
|
|
|
|
private void UpdateSelectedFontFamily()
|
|
{
|
|
object value = DependencyProperty.UnsetValue;
|
|
if( ( Target != null ) && ( Target.Selection != null ) )
|
|
{
|
|
value = Target.Selection.GetPropertyValue( TextElement.FontFamilyProperty );
|
|
}
|
|
|
|
if( value == DependencyProperty.UnsetValue )
|
|
return;
|
|
|
|
FontFamily currentFontFamily = ( FontFamily )value;
|
|
if( currentFontFamily != null )
|
|
{
|
|
_cmbFontFamilies.SelectedItem = currentFontFamily;
|
|
}
|
|
}
|
|
|
|
private void UpdateSelectedFontSize()
|
|
{
|
|
object value = DependencyProperty.UnsetValue;
|
|
if( ( Target != null ) && ( Target.Selection != null ) )
|
|
{
|
|
value = Target.Selection.GetPropertyValue( TextElement.FontSizeProperty );
|
|
}
|
|
|
|
if( value == DependencyProperty.UnsetValue )
|
|
return;
|
|
|
|
_cmbFontSizes.SelectedValue = value;
|
|
}
|
|
|
|
private void UpdateFontColor()
|
|
{
|
|
object value = DependencyProperty.UnsetValue;
|
|
if( ( Target != null ) && ( Target.Selection != null ) )
|
|
{
|
|
value = Target.Selection.GetPropertyValue( TextElement.ForegroundProperty );
|
|
}
|
|
|
|
if( value == DependencyProperty.UnsetValue )
|
|
return;
|
|
|
|
Color? currentColor = ( ( value == null )
|
|
? null
|
|
: ( Color? )( ( SolidColorBrush )value ).Color );
|
|
_cmbFontColor.SelectedColor = currentColor;
|
|
}
|
|
|
|
private void UpdateFontBackgroundColor()
|
|
{
|
|
object value = DependencyProperty.UnsetValue;
|
|
if( ( Target != null ) && ( Target.Selection != null ) )
|
|
{
|
|
value = Target.Selection.GetPropertyValue( TextElement.BackgroundProperty );
|
|
}
|
|
|
|
if( value == DependencyProperty.UnsetValue )
|
|
return;
|
|
|
|
Color? currentColor = ( ( value == null )
|
|
? null
|
|
: ( Color? )( ( SolidColorBrush )value ).Color );
|
|
_cmbFontBackgroundColor.SelectedColor = currentColor;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the visual state of the List styles, such as Numbers and Bullets.
|
|
/// </summary>
|
|
private void UpdateSelectionListType()
|
|
{
|
|
//uncheck both
|
|
_btnBullets.IsChecked = false;
|
|
_btnNumbers.IsChecked = false;
|
|
|
|
Paragraph startParagraph = ( ( Target != null ) && ( Target.Selection != null ) )
|
|
? Target.Selection.Start.Paragraph
|
|
: null;
|
|
Paragraph endParagraph = ( ( Target != null ) && ( Target.Selection != null ) )
|
|
? Target.Selection.End.Paragraph
|
|
: null;
|
|
if( startParagraph != null && endParagraph != null && ( startParagraph.Parent is ListItem ) && ( endParagraph.Parent is ListItem ) && object.ReferenceEquals( ( ( ListItem )startParagraph.Parent ).List, ( ( ListItem )endParagraph.Parent ).List ) )
|
|
{
|
|
TextMarkerStyle markerStyle = ( ( ListItem )startParagraph.Parent ).List.MarkerStyle;
|
|
if( markerStyle == TextMarkerStyle.Disc ) //bullets
|
|
{
|
|
_btnBullets.IsChecked = true;
|
|
}
|
|
else if( markerStyle == TextMarkerStyle.Decimal ) //numbers
|
|
{
|
|
_btnNumbers.IsChecked = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks to see if both selection lists are checked. (Bullets and Numbers)
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private bool BothSelectionListsAreChecked()
|
|
{
|
|
return _btnBullets.IsChecked == true && _btnNumbers.IsChecked == true;
|
|
}
|
|
|
|
void ApplyPropertyValueToSelectedText( DependencyProperty formattingProperty, object value )
|
|
{
|
|
if( ( Target == null ) || ( Target.Selection == null ) )
|
|
return;
|
|
|
|
SolidColorBrush solidColorBrush = value as SolidColorBrush;
|
|
if( ( solidColorBrush != null ) && solidColorBrush.Color.Equals( Colors.Transparent ) )
|
|
{
|
|
Target.Selection.ApplyPropertyValue( formattingProperty, null );
|
|
}
|
|
else
|
|
{
|
|
Target.Selection.ApplyPropertyValue( formattingProperty, value );
|
|
}
|
|
}
|
|
|
|
private void ProcessMove( DragDeltaEventArgs e )
|
|
{
|
|
AdornerLayer layer = AdornerLayer.GetAdornerLayer( Target );
|
|
UIElementAdorner<Control> adorner = layer.GetAdorners( Target ).OfType<UIElementAdorner<Control>>().First();
|
|
adorner.SetOffsets( adorner.OffsetLeft + e.HorizontalChange, adorner.OffsetTop + e.VerticalChange );
|
|
}
|
|
|
|
#endregion //Methods
|
|
|
|
#region IRichTextBoxFormatBar Interface
|
|
|
|
#region Target
|
|
|
|
public static readonly DependencyProperty TargetProperty = DependencyProperty.Register( "Target", typeof( global::System.Windows.Controls.RichTextBox ), typeof( RichTextBoxFormatBar ), new PropertyMetadata( null, OnRichTextBoxPropertyChanged ) );
|
|
public global::System.Windows.Controls.RichTextBox Target
|
|
{
|
|
get
|
|
{
|
|
return ( global::System.Windows.Controls.RichTextBox )GetValue( TargetProperty );
|
|
}
|
|
set
|
|
{
|
|
SetValue( TargetProperty, value );
|
|
}
|
|
}
|
|
|
|
private static void OnRichTextBoxPropertyChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
|
|
{
|
|
RichTextBoxFormatBar formatBar = d as RichTextBoxFormatBar;
|
|
}
|
|
|
|
#endregion //Target
|
|
|
|
public bool PreventDisplayFadeOut
|
|
{
|
|
get
|
|
{
|
|
return ( _cmbFontFamilies.IsDropDownOpen || _cmbFontSizes.IsDropDownOpen ||
|
|
_cmbFontBackgroundColor.IsOpen || _cmbFontColor.IsOpen || _waitingForMouseOver );
|
|
}
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
UpdateToggleButtonState();
|
|
UpdateSelectedFontFamily();
|
|
UpdateSelectedFontSize();
|
|
UpdateFontColor();
|
|
UpdateFontBackgroundColor();
|
|
UpdateSelectionListType();
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|
|
|