using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.ComponentModel;
using System.Text.RegularExpressions;
using Signum.Utilities;
using Signum.Utilities.ExpressionTrees;
using System.Windows.Data;
using Signum.Utilities.DataStructures;
using System.Reflection;
using System.Windows.Media;
using Signum.Entities.Reflection;
using Signum.Windows.Properties;
using System.Collections;
namespace Signum.Windows
{
public static class Common
{
public static double GetLabelWidth(DependencyObject obj)
{
return (double)obj.GetValue(LabelWidthProperty);
}
public static void SetLabelWidth(DependencyObject obj, double value)
{
obj.SetValue(LabelWidthProperty, value);
}
public static readonly DependencyProperty LabelWidthProperty =
DependencyProperty.RegisterAttached("LabelWidth", typeof(double), typeof(Common), new FrameworkPropertyMetadata(100.0, FrameworkPropertyMetadataOptions.Inherits));
public static bool GetLabelVisible(DependencyObject obj)
{
return (bool)obj.GetValue(LabelVisibleProperty);
}
public static void SetLabelVisible(DependencyObject obj, bool value)
{
obj.SetValue(LabelVisibleProperty, value);
}
public static readonly DependencyProperty LabelVisibleProperty =
DependencyProperty.RegisterAttached("LabelVisible", typeof(bool), typeof(Common), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits));
public static bool GetIsReadOnly(DependencyObject obj)
{
return (bool)obj.GetValue(IsReadOnlyProperty);
}
public static void SetIsReadOnly(DependencyObject obj, bool value)
{
obj.SetValue(IsReadOnlyProperty, value);
}
public static readonly DependencyProperty IsReadOnlyProperty =
DependencyProperty.RegisterAttached("IsReadOnly", typeof(bool), typeof(Common), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits));
public static TypeContext GetTypeContext(DependencyObject obj)
{
return (TypeContext)obj.GetValue(TypeContextProperty);
}
public static void SetTypeContext(DependencyObject obj, TypeContext value)
{
obj.SetValue(TypeContextProperty, value);
}
// Using a DependencyProperty as the backing store for TypeContext. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TypeContextProperty =
DependencyProperty.RegisterAttached("TypeContext", typeof(TypeContext), typeof(Common), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));
public static string GetRoute(DependencyObject obj)
{
return (string)obj.GetValue(RouteProperty);
}
public static void SetRoute(DependencyObject obj, string value)
{
obj.SetValue(RouteProperty, value);
}
public static readonly DependencyProperty RouteProperty =
DependencyProperty.RegisterAttached("Route", typeof(string), typeof(Common), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(RoutePropertyChanged)));
static readonly Regex validIdentifier = new Regex(@"^[_\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nl}][_\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nl}\p{Nd}]*$");
public static void RoutePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FrameworkElement fe = (FrameworkElement)d;
DependencyProperty labelText =
fe is ValueLine ? ValueLine.LabelTextProperty :
fe is EntityBase ? EntityBase.LabelTextProperty :
null;
if (DesignerProperties.GetIsInDesignMode(fe))
{
if (labelText != null && fe.NotSet(labelText))
{
fe.SetValue(labelText, e.NewValue);
}
return;
}
string route = (string)e.NewValue;
TypeContext context = GetTypeContext(fe.Parent);
if (context == null)
throw new ApplicationException(Properties.Resources.RoutePropertyCanNotBeAppliedWithNullTypeContext);
string nRoute = route.Replace("/", "./.");
string[] steps = nRoute.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var step in steps)
{
if (step == "/")
{
if(!typeof(IList).IsAssignableFrom(context.Type))
throw new InvalidOperationException(Resources.Type0IsNotAColection.Formato(context.Type.TypeName()));
context = new TypeSubContext(context.Type.GetProperty("Item"), context);
}
else if (validIdentifier.IsMatch(step))
{
PropertyInfo pi = context.Type.GetProperty(step).ThrowIfNullC(Resources.Property0DoNotExistOnType1.Formato(step, context.Type.TypeName()));
context = new TypeSubContext(pi, context);
}
}
SetTypeContext(fe, context);
DependencyProperty typeProperty =
fe is ValueLine ? ValueLine.ValueTypeProperty :
fe is EntityLine ? EntityLine.EntityTypeProperty :
fe is EntityList ? EntityList.EntitiesTypeProperty :
fe is EntityCombo ? EntityCombo.EntityTypeProperty :
fe is FileLine ? FileLine.EntityTypeProperty :
null;
if (typeProperty != null && fe.NotSet(typeProperty))
{
fe.SetValue(typeProperty, context.Type);
if (fe is EntityList)
fe.SetValue(EntityList.EntityTypeProperty, Reflector.CollectionType(context.Type));
}
if (labelText!= null && fe.NotSet(labelText))
{
fe.SetValue(labelText, steps.LastOrDefault());
}
DependencyProperty valueProp =
fe is ValueLine? ValueLine.ValueProperty:
fe is EntityLine? EntityLine.EntityProperty:
fe is EntityList? EntityList.EntitiesProperty:
fe is EntityCombo? EntityCombo.EntityProperty:
fe is FileLine ? FileLine.EntityProperty :
FrameworkElement.DataContextProperty;
bool isReadOnly = (context as TypeSubContext).TryCS(tsc => tsc.IsReadOnly) ?? true;
if (!BindingOperations.IsDataBound(fe, valueProp))
{
Binding b = new Binding(route);
b.Mode = isReadOnly? BindingMode.OneWay : BindingMode.TwoWay;
b.NotifyOnValidationError = true;
b.ValidatesOnExceptions = true;
b.ValidatesOnDataErrors = true;
fe.SetBinding(valueProp, b);
}
if (isReadOnly && (fe is ValueLine || fe is EntityLine || fe is EntityCombo || fe is FileLine))
{
Common.SetIsReadOnly(fe, true);
}
if (fe is EntityBase)
{
var contextList = context.FollowC(a => (a as TypeSubContext).TryCC(t => t.Parent)).ToList();
if (contextList.Count > 1)
{
var list = contextList.OfType<TypeSubContext>().Select(a => a.PropertyInfo).Reverse().ToList();
if(fe is EntityList)
list.Add( list.Last().PropertyType.GetProperty("Item"));
((EntityBase)fe).Implementations = Server.ServerProxy.FindImplementations(contextList.Last().Type, list.Cast<MemberInfo>().ToArray());
}
}
}
public static Window GetCurrentWindow(DependencyObject obj)
{
return (Window)obj.GetValue(CurrentWindowProperty);
}
public static void SetCurrentWindow(DependencyObject obj, Window value)
{
obj.SetValue(CurrentWindowProperty, value);
}
// Using a DependencyProperty as the backing store for CurrentWindow. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CurrentWindowProperty =
DependencyProperty.RegisterAttached("CurrentWindow", typeof(Window), typeof(Common), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));
public static Window FindCurrentWindow(this FrameworkElement fe)
{
return fe.FollowC(a => (FrameworkElement)(a.Parent ?? a.TemplatedParent))
.Select(a => GetCurrentWindow(a) ?? a as Window).NotNull().First(Properties.Resources.ParentWindowNotFound);
}
public static bool NotSet(this DependencyObject depObj, DependencyProperty prop)
{
return DependencyPropertyHelper.GetValueSource(depObj, prop).BaseValueSource != BaseValueSource.Local;
}
public static IEnumerable<DependencyObject> Parents(this DependencyObject child)
{
return child.FollowC(VisualTreeHelper.GetParent);
}
public static Visibility ToVisibility(this bool val)
{
return val ? Visibility.Visible : Visibility.Collapsed;
}
public static bool FromVisibility(this Visibility val)
{
return val == Visibility.Visible;
}
public static DependencyObject FindChildrenBreadthFirst(DependencyObject parent, Predicate<DependencyObject> predicate)
{
//http://en.wikipedia.org/wiki/Breadth-first_search
Queue<DependencyObject> st = new Queue<DependencyObject>();
st.Enqueue(parent);
while (st.Count > 0)
{
DependencyObject dp = st.Dequeue();
if (predicate(dp))
return dp;
int count = VisualTreeHelper.GetChildrenCount(dp);
for (int i = 0; i < count; i++)
{
st.Enqueue(VisualTreeHelper.GetChild(dp, i));
}
}
return null;
}
}
}