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.

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
}
}