// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993] for details.
// All other rights reserved.
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Windows.Automation.Peers;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
namespace System.Windows.Controls
{
///
/// An item used in a rating control.
///
/// Preview
[TemplateVisualState(Name = VisualStates.StateNormal, GroupName = VisualStates.GroupCommon)]
[TemplateVisualState(Name = VisualStates.StateMouseOver, GroupName = VisualStates.GroupCommon)]
[TemplateVisualState(Name = VisualStates.StatePressed, GroupName = VisualStates.GroupCommon)]
[TemplateVisualState(Name = VisualStates.StateDisabled, GroupName = VisualStates.GroupCommon)]
[TemplateVisualState(Name = VisualStates.StateReadOnly, GroupName = VisualStates.GroupCommon)]
[TemplateVisualState(Name = VisualStates.StateFocused, GroupName = VisualStates.GroupFocus)]
[TemplateVisualState(Name = VisualStates.StateUnfocused, GroupName = VisualStates.GroupFocus)]
[TemplateVisualState(Name = StateFilled, GroupName = GroupFill)]
[TemplateVisualState(Name = StateEmpty, GroupName = GroupFill)]
[TemplateVisualState(Name = StatePartial, GroupName = GroupFill)]
public class RatingItem : ButtonBase, IUpdateVisualState
{
///
/// The state in which the item is filled.
///
private const string StateFilled = "Filled";
///
/// The state in which the item is empty.
///
private const string StateEmpty = "Empty";
///
/// The group that contains fill states.
///
private const string GroupFill = "FillStates";
///
/// The state in which the item is partially filled.
///
private const string StatePartial = "Partial";
///
/// The interaction helper used to get the common states working.
///
private InteractionHelper _interactionHelper;
#region public double DisplayValue
///
/// A value indicating whether the actual value is being set.
///
private bool _settingDisplayValue;
///
/// Gets the actual value.
///
public double DisplayValue
{
get { return (double)GetValue(DisplayValueProperty); }
internal set
{
_settingDisplayValue = true;
try
{
SetValue(DisplayValueProperty, value);
}
finally
{
_settingDisplayValue = false;
}
}
}
///
/// Identifies the DisplayValue dependency property.
///
public static readonly DependencyProperty DisplayValueProperty =
DependencyProperty.Register(
"DisplayValue",
typeof(double),
typeof(RatingItem),
new PropertyMetadata(0.0, OnDisplayValueChanged));
///
/// DisplayValueProperty property changed handler.
///
/// RatingItem that changed its DisplayValue.
/// Event arguments.
private static void OnDisplayValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
RatingItem source = (RatingItem)d;
source.OnDisplayValueChanged((double)e.OldValue, (double)e.NewValue);
}
///
/// DisplayValueProperty property changed handler.
///
/// The old value.
/// The new value.
private void OnDisplayValueChanged(double oldValue, double newValue)
{
if (!_settingDisplayValue)
{
_settingDisplayValue = true;
this.DisplayValue = oldValue;
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, Muchinfo.WPF.Controls.Properties.Resources.InvalidAttemptToChangeReadOnlyProperty, "DisplayValue"));
}
else
{
if (newValue <= 0.0)
{
VisualStates.GoToState(this, true, StateEmpty);
}
else if (newValue >= 1.0)
{
VisualStates.GoToState(this, true, StateFilled);
}
else
{
VisualStates.GoToState(this, true, StatePartial);
}
}
}
#endregion public double DisplayValue
#region public bool IsReadOnly
///
/// A value indicating whether the read only value is being set.
///
private bool _settingIsReadOnly;
///
/// Gets a value indicating whether the control is read-only.
///
public bool IsReadOnly
{
get { return (bool)GetValue(IsReadOnlyProperty); }
internal set
{
_settingIsReadOnly = true;
try
{
SetValue(IsReadOnlyProperty, value);
}
finally
{
_settingIsReadOnly = false;
}
}
}
///
/// Identifies the IsReadOnly dependency property.
///
public static readonly DependencyProperty IsReadOnlyProperty =
DependencyProperty.Register(
"IsReadOnly",
typeof(bool),
typeof(RatingItem),
new PropertyMetadata(false, OnIsReadOnlyChanged));
///
/// IsReadOnlyProperty property changed handler.
///
/// RatingItem that changed its IsReadOnly.
/// Event arguments.
private static void OnIsReadOnlyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
RatingItem source = (RatingItem)d;
bool oldValue = (bool)e.OldValue;
bool newValue = (bool)e.NewValue;
source.OnIsReadOnlyChanged(oldValue, newValue);
}
///
/// IsReadOnlyProperty property changed handler.
///
/// Old value.
/// New value.
protected virtual void OnIsReadOnlyChanged(bool oldValue, bool newValue)
{
if (!_settingIsReadOnly)
{
_settingIsReadOnly = true;
this.IsReadOnly = oldValue;
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, Muchinfo.WPF.Controls.Properties.Resources.InvalidAttemptToChangeReadOnlyProperty, "IsReadOnly"));
}
else
{
_interactionHelper.OnIsReadOnlyChanged(newValue);
}
}
#endregion public bool IsReadOnly
///
/// Gets or sets the parent rating of this rating item.
///
internal Rating ParentRating { get; set; }
#region public double Value
///
/// Gets or sets the value property.
///
[SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "Value is the logical name for this property.")]
internal double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
///
/// Identifies the Value dependency property.
///
internal static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(
"Value",
typeof(double),
typeof(RatingItem),
new PropertyMetadata(0.0));
///
/// Selects a value and raises the value selected event.
///
internal void SelectValue()
{
if (!this.IsReadOnly)
{
this.Value = 1.0;
OnClick();
}
}
#endregion public double Value
#if !SILVERLIGHT
///
/// Initializes the static members of the ColumnDataPoint class.
///
static RatingItem()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(RatingItem), new FrameworkPropertyMetadata(typeof(RatingItem)));
}
#endif
///
/// Initializes a new instance of the RatingItem class.
///
public RatingItem()
{
#if SILVERLIGHT
this.DefaultStyleKey = typeof(RatingItem);
#endif
_interactionHelper = new InteractionHelper(this);
}
///
/// Provides handling for the RatingItem's MouseLeftButtonDown event.
///
/// Event arguments.
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
if (_interactionHelper.AllowMouseLeftButtonDown(e))
{
_interactionHelper.OnMouseLeftButtonDownBase();
}
base.OnMouseLeftButtonDown(e);
}
///
/// Provides handling for the RatingItem's MouseLeftButtonUp event.
///
/// Event arguments.
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
if (_interactionHelper.AllowMouseLeftButtonUp(e))
{
_interactionHelper.OnMouseLeftButtonUpBase();
}
base.OnMouseLeftButtonUp(e);
}
///
/// This method is invoked when the mouse enters the rating item.
///
/// Information about the event.
protected override void OnMouseEnter(MouseEventArgs e)
{
if (_interactionHelper.AllowMouseEnter(e))
{
_interactionHelper.UpdateVisualStateBase(true);
}
base.OnMouseEnter(e);
}
///
/// This method is invoked when the mouse leaves the rating item.
///
/// Information about the event.
protected override void OnMouseLeave(MouseEventArgs e)
{
if (_interactionHelper.AllowMouseLeave(e))
{
_interactionHelper.UpdateVisualStateBase(true);
}
base.OnMouseLeave(e);
}
///
/// Sets the value to 1.0 when clicked.
///
protected override void OnClick()
{
base.OnClick();
}
///
/// Updates the visual state.
///
/// A value indicating whether to use
/// transitions.
void IUpdateVisualState.UpdateVisualState(bool useTransitions)
{
_interactionHelper.UpdateVisualStateBase(useTransitions);
}
///
/// Returns a AccordionItemAutomationPeer for use by the Silverlight
/// automation infrastructure.
///
/// A AccordionItemAutomationPeer object for the AccordionItem.
protected override AutomationPeer OnCreateAutomationPeer()
{
return new RatingItemAutomationPeer(this);
}
}
}