Adding Shape editors infrastructure

--HG--
branch : 1.x
This commit is contained in:
Sebastien Ros
2011-09-01 14:08:04 -07:00
parent bf5dad4a1f
commit 7b13fb310e
3 changed files with 139 additions and 10 deletions

View File

@@ -82,6 +82,9 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeAttributeStrategy {
if (parameter.Name == "Output" && parameter.ParameterType == typeof(TextWriter)) if (parameter.Name == "Output" && parameter.ParameterType == typeof(TextWriter))
return output; return output;
if (parameter.Name == "Output" && parameter.ParameterType == typeof(Action<object>))
return new Action<object>(output.Write);
// meh-- // meh--
if (parameter.Name == "Html") { if (parameter.Name == "Html") {
return new HtmlHelper( return new HtmlHelper(
@@ -90,8 +93,12 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeAttributeStrategy {
_routeCollection); _routeCollection);
} }
if (parameter.Name == "Url" && parameter.ParameterType.IsAssignableFrom(typeof(UrlHelper))) {
return new UrlHelper(displayContext.ViewContext.RequestContext, _routeCollection);
}
var getter = _getters.GetOrAdd(parameter.Name, n => var getter = _getters.GetOrAdd(parameter.Name, n =>
CallSite<Func<CallSite, object, object>>.Create( CallSite<Func<CallSite, object, dynamic>>.Create(
Microsoft.CSharp.RuntimeBinder.Binder.GetMember( Microsoft.CSharp.RuntimeBinder.Binder.GetMember(
CSharpBinderFlags.None, n, null, new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }))); CSharpBinderFlags.None, n, null, new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })));
@@ -106,13 +113,13 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeAttributeStrategy {
} }
static readonly ConcurrentDictionary<string, CallSite<Func<CallSite, object, object>>> _getters = static readonly ConcurrentDictionary<string, CallSite<Func<CallSite, object, dynamic>>> _getters =
new ConcurrentDictionary<string, CallSite<Func<CallSite, object, object>>>(); new ConcurrentDictionary<string, CallSite<Func<CallSite, object, dynamic>>>();
static readonly ConcurrentDictionary<Type, Func<object, object>> _converters = static readonly ConcurrentDictionary<Type, Func<dynamic, object>> _converters =
new ConcurrentDictionary<Type, Func<object, object>>(); new ConcurrentDictionary<Type, Func<dynamic, object>>();
static Func<object, object> CompileConverter(Type targetType) { static Func<dynamic, object> CompileConverter(Type targetType) {
var valueParameter = Expression.Parameter(typeof(object), "value"); var valueParameter = Expression.Parameter(typeof(object), "value");
return Expression.Lambda<Func<object, object>>( return Expression.Lambda<Func<object, object>>(

View File

@@ -58,14 +58,15 @@ namespace Orchard.DisplayManagement.Implementation {
new ClaySharp.Behaviors.InterfaceProxyBehavior(), new ClaySharp.Behaviors.InterfaceProxyBehavior(),
new ClaySharp.Behaviors.PropBehavior(), new ClaySharp.Behaviors.PropBehavior(),
new ClaySharp.Behaviors.ArrayBehavior(), new ClaySharp.Behaviors.ArrayBehavior(),
new ClaySharp.Behaviors.NilResultBehavior() new ClaySharp.Behaviors.NilResultBehavior(),
}; };
} }
else { else {
creatingContext.Behaviors = new List<IClayBehavior> { creatingContext.Behaviors = new List<IClayBehavior> {
new ClaySharp.Behaviors.InterfaceProxyBehavior(), new ClaySharp.Behaviors.InterfaceProxyBehavior(),
new ClaySharp.Behaviors.PropBehavior(), new ClaySharp.Behaviors.PropBehavior(),
new ClaySharp.Behaviors.NilResultBehavior() new ClaySharp.Behaviors.NilResultBehavior(),
new Shape.ShapeBehavior(),
}; };
} }

View File

@@ -1,8 +1,11 @@
using System; using System;
using System.Linq;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Web.Mvc; using System.Web.Mvc;
using ClaySharp;
using ClaySharp.Implementation;
namespace Orchard.DisplayManagement.Shapes { namespace Orchard.DisplayManagement.Shapes {
[DebuggerTypeProxy(typeof(ShapeDebugView))] [DebuggerTypeProxy(typeof(ShapeDebugView))]
@@ -20,7 +23,7 @@ namespace Orchard.DisplayManagement.Shapes {
public virtual IDictionary<string, string> Attributes { get { return _attributes; } } public virtual IDictionary<string, string> Attributes { get { return _attributes; } }
public virtual IEnumerable<dynamic> Items { get { return _items; } } public virtual IEnumerable<dynamic> Items { get { return _items; } }
public virtual Shape Add(object item, string position = DefaultPosition) { public virtual Shape Add(object item, string position = null) {
// pszmyd: Ignoring null shapes // pszmyd: Ignoring null shapes
if (item == null) { if (item == null) {
return this; return this;
@@ -32,7 +35,7 @@ namespace Orchard.DisplayManagement.Shapes {
item is String ) { item is String ) {
// need to implement positioned wrapper for non-shape objects // need to implement positioned wrapper for non-shape objects
} }
else { else if (item is IShape) {
((dynamic) item).Metadata.Position = position; ((dynamic) item).Metadata.Position = position;
} }
} }
@@ -53,5 +56,123 @@ namespace Orchard.DisplayManagement.Shapes {
public virtual IEnumerator GetEnumerator() { public virtual IEnumerator GetEnumerator() {
return _items.GetEnumerator(); return _items.GetEnumerator();
} }
public class ShapeBehavior : ClayBehavior {
public override object SetIndex(Func<object> proceed, dynamic self, IEnumerable<object> keys, object value) {
if (keys.Count() == 1) {
var name = keys.Single().ToString();
if (name.Equals("Id")) {
// need to mutate the actual type
var s = self as Shape;
if (s != null) {
s.Id = System.Convert.ToString(value);
}
return value;
}
if (name.Equals("Classes")) {
var args = Arguments.From(new[] { value }, Enumerable.Empty<string>());
MergeClasses(args, self.Classes);
return value;
}
if (name.Equals("Attributes")) {
var args = Arguments.From(new[] { value }, Enumerable.Empty<string>());
MergeAttributes(args, self.Attributes);
return value;
}
if (name.Equals("Items")) {
var args = Arguments.From(new[] { value }, Enumerable.Empty<string>());
MergeItems(args, self);
return value;
}
}
return proceed();
}
public override object InvokeMember(Func<object> proceed, dynamic self, string name, INamedEnumerable<object> args) {
if (name.Equals("Id")) {
// need to mutate the actual type
var s = self as Shape;
if (s != null) {
s.Id = System.Convert.ToString(args.FirstOrDefault());
}
return self;
}
if (name.Equals("Classes") && !args.Named.Any()) {
MergeClasses(args, self.Classes);
return self;
}
if (name.Equals("Attributes") && args.Positional.Count() <= 1) {
MergeAttributes(args, self.Attributes);
return self;
}
if (name.Equals("Items")) {
MergeItems(args, self);
return self;
}
return proceed();
}
private static void MergeAttributes(INamedEnumerable<object> args, IDictionary<string, string> attributes) {
var arg = args.Positional.SingleOrDefault();
if (arg != null) {
if (arg is IDictionary) {
var dictionary = arg as IDictionary;
foreach (var key in dictionary.Keys) {
attributes[System.Convert.ToString(key)] = System.Convert.ToString(dictionary[key]);
}
}
else {
foreach (var prop in arg.GetType().GetProperties()) {
attributes[TranslateIdentifier(prop.Name)] = System.Convert.ToString(prop.GetValue(arg, null));
}
}
}
foreach (var named in args.Named) {
attributes[named.Key] = System.Convert.ToString(named.Value);
}
}
private static string TranslateIdentifier(string name) {
// Allows for certain characters in an identifier to represent different
// characters in an HTML attribute (mimics MVC behavior):
// data_foo ==> data-foo
// @keyword ==> keyword
return name.Replace("_", "-").Replace("@", "");
}
private static void MergeClasses(INamedEnumerable<object> args, IList<string> classes) {
foreach (var arg in args) {
// look for string first, because the "string" type is also an IEnumerable of char
if (arg is string) {
classes.Add(arg as string);
}
else if (arg is IEnumerable) {
foreach (var item in arg as IEnumerable) {
classes.Add(System.Convert.ToString(item));
}
}
else {
classes.Add(System.Convert.ToString(arg));
}
}
}
private static void MergeItems(INamedEnumerable<object> args, dynamic shape) {
foreach (var arg in args) {
// look for string first, because the "string" type is also an IEnumerable of char
if (arg is string) {
shape.Add(arg as string);
}
else if (arg is IEnumerable) {
foreach (var item in arg as IEnumerable) {
shape.Add(item);
}
}
else {
shape.Add(System.Convert.ToString(arg));
}
}
}
}
} }
} }