--HG--
branch : InputShapes
This commit is contained in:
Louis DeJardin
2011-06-28 17:47:36 -07:00
12 changed files with 123 additions and 37 deletions

Binary file not shown.

View File

@@ -101,6 +101,31 @@ namespace Orchard.Core.Shapes {
//object ActionLinkValue,
//object Description,
string EnabledBy) {
/*
* #id #type #name #title #title_display #field_prefix #field_suffix #description #required
* #title_display=={before,after,invisible,attribute,none}
*
* {form_element}
* <div attributes id="#id" class="form-type-#type form-item-#name">
* {form_element_label}
* <label class="option?#title_display==after element-invisible?#title_display==invisible" for="#id">
* #title
* {form_required_marker}
* <span class='form-required'>This field is required.</span>
* {/form_required_marker}?#required
* </label>
* {/form_element_label}?#title
* <span class="field-prefix">#field_prefix</span>?#field_prefix
* #child_content
* <span class="field-suffix">#field_suffix</span>?#field_suffix
* {form_element_label/}?#title_display==after
* <div class="description">#description</div>?
* </div>
* {/form_element}
*/
// Wraps an input with metadata as follows (most of it is optional and won't render if not present):
/*
<div data-controllerid="{EnabledByInputId}">
@@ -173,6 +198,33 @@ namespace Orchard.Core.Shapes {
Output.WriteLine(div.ToString(TagRenderMode.EndTag));
}
[Shape]
public void Form(Action<object> Output, dynamic Display, dynamic Shape) {
OrchardTagBuilder tag = _tagBuilderFactory.Create(Shape, "form");
Output(tag.ToString(TagRenderMode.StartTag));
foreach(var item in Shape) {
Output(Display(item));
}
Output(tag.ToString(TagRenderMode.EndTag));
}
[Shape]
public void Fieldset(Action<object> Output, dynamic Display, dynamic Shape) {
OrchardTagBuilder tag = _tagBuilderFactory.Create(Shape, "fieldset");
Output(tag.ToString(TagRenderMode.StartTag));
foreach(var item in Shape) {
Output(Display(item));
}
Output(tag.ToString(TagRenderMode.EndTag));
}
[Shape]
public IHtmlString Textbox(dynamic Display, dynamic Shape) {
Shape.Metadata.Type = "Input";
Shape.Type = "textbox";
return Display(Shape);
}
[Shape]
public IHtmlString Input(HtmlHelper Html, dynamic Shape, dynamic Display, string Type, string Name, dynamic Value) {
var tag = (TagBuilder)_tagBuilderFactory.Create(Shape, "input");

View File

@@ -5,6 +5,7 @@ using System.Xml.Linq;
using Orchard.Experimental.Models;
using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.Mvc;
using Orchard.Themes;
using Orchard.UI.Notify;
using Orchard.UI.Admin;
@@ -39,6 +40,19 @@ namespace Orchard.Experimental.Controllers {
public ActionResult Simple() {
return View(new Simple { Title = "This is a simple text", Quantity = 5 });
}
public ActionResult Forms() {
var form = Shape.Form();
form.Captcha = Shape.Fieldset(Title: T("Captcha"), Response: Shape.Textbox());
form.Actions = Shape.Fieldset(Ok: Shape.Button(T("OK")), Cancel: Shape.Button(T("Cancel")));
form.Add(form.Captcha);
form.Add(form.Actions);
form.Actions.Add(form.Actions.Ok);
form.Actions.Add(form.Actions.Cancel);
return new ShapeResult(this, form);
}
public ActionResult _RenderableAction() {
return PartialView("_RenderableAction", "This is render action");

View File

@@ -81,6 +81,8 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeAttributeStrategy {
if (parameter.Name == "Output" && parameter.ParameterType == typeof(TextWriter))
return output;
if (parameter.Name == "Output" && parameter.ParameterType == typeof(Action<object>))
return new Action<object>(output.Write);
// meh--
if (parameter.Name == "Html") {
@@ -95,7 +97,7 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeAttributeStrategy {
}
var getter = _getters.GetOrAdd(parameter.Name, n =>
CallSite<Func<CallSite, object, object>>.Create(
CallSite<Func<CallSite, object, dynamic>>.Create(
Microsoft.CSharp.RuntimeBinder.Binder.GetMember(
CSharpBinderFlags.None, n, null, new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })));
@@ -110,13 +112,13 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeAttributeStrategy {
}
static readonly ConcurrentDictionary<string, CallSite<Func<CallSite, object, object>>> _getters =
new ConcurrentDictionary<string, CallSite<Func<CallSite, object, object>>>();
static readonly ConcurrentDictionary<string, CallSite<Func<CallSite, object, dynamic>>> _getters =
new ConcurrentDictionary<string, CallSite<Func<CallSite, object, dynamic>>>();
static readonly ConcurrentDictionary<Type, Func<object, object>> _converters =
new ConcurrentDictionary<Type, Func<object, object>>();
static readonly ConcurrentDictionary<Type, Func<dynamic, object>> _converters =
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");
return Expression.Lambda<Func<object, object>>(

View File

@@ -51,7 +51,6 @@ namespace Orchard.DisplayManagement.Implementation {
positional = positional.Skip(1);
}
var shapeBehavior = new Shape.ShapeBehavior();
if (creatingContext.BaseType == typeof(Array)) {
// array is a hint - not an intended base class
creatingContext.BaseType = typeof(Shape);
@@ -67,7 +66,7 @@ namespace Orchard.DisplayManagement.Implementation {
new ClaySharp.Behaviors.InterfaceProxyBehavior(),
new ClaySharp.Behaviors.PropBehavior(),
new ClaySharp.Behaviors.NilResultBehavior(),
shapeBehavior,
new Shape.ShapeBehavior(),
};
}
@@ -92,7 +91,6 @@ namespace Orchard.DisplayManagement.Implementation {
ShapeType = creatingContext.ShapeType,
Shape = ClayActivator.CreateInstance(creatingContext.BaseType, creatingContext.Behaviors)
};
shapeBehavior._shape = createdContext.Shape;
var shapeMetadata = new ShapeMetadata { Type = shapeType };
createdContext.Shape.Metadata = shapeMetadata;

View File

@@ -23,7 +23,7 @@ namespace Orchard.DisplayManagement.Shapes {
public virtual IDictionary<string, string> Attributes { get { return _attributes; } }
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
if (item == null) {
return this;
@@ -35,7 +35,7 @@ namespace Orchard.DisplayManagement.Shapes {
item is String ) {
// need to implement positioned wrapper for non-shape objects
}
else {
else if (item is IShape) {
((dynamic) item).Metadata.Position = position;
}
}
@@ -58,14 +58,12 @@ namespace Orchard.DisplayManagement.Shapes {
}
public class ShapeBehavior : ClayBehavior {
public dynamic _shape;
// This can't really be done without a hack until indexer methods offer a self parameter
public override object SetIndex(Func<object> proceed, IEnumerable<object> keys, object value) {
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 = _shape as Shape;
var s = self as Shape;
if (s != null) {
s.Id = System.Convert.ToString(value);
}
@@ -73,21 +71,21 @@ namespace Orchard.DisplayManagement.Shapes {
}
if (name.Equals("Classes")) {
var args = Arguments.From(new[] { value }, Enumerable.Empty<string>());
MergeClasses(args, _shape.Classes);
MergeClasses(args, self.Classes);
return value;
}
if (name.Equals("Attributes")) {
var args = Arguments.From(new[] { value }, Enumerable.Empty<string>());
MergeAttributes(args, _shape.Attributes);
MergeAttributes(args, self.Attributes);
return value;
}
if (name.Equals("Items")) {
var args = Arguments.From(new[] { value }, Enumerable.Empty<string>());
MergeItems(args, _shape.Items);
MergeItems(args, self);
return value;
}
}
return base.SetIndex(proceed, keys, value);
return proceed();
}
public override object InvokeMember(Func<object> proceed, dynamic self, string name, INamedEnumerable<object> args) {

View File

@@ -19,7 +19,4 @@ namespace Orchard.Localization.Services {
return new CultureSelectorResult { Priority = -5, CultureName = currentCultureName };
}
}
public class CultureSettings {
}
}

View File

@@ -260,6 +260,7 @@
<Compile Include="Settings\ResourceDebugMode.cs" />
<Compile Include="Themes\ThemeManager.cs" />
<Compile Include="Time\CurrentTimeZoneWorkContext.cs" />
<Compile Include="Time\FallbackTimeZoneSelector.cs" />
<Compile Include="Time\SiteTimeZoneSelector.cs" />
<Compile Include="Time\IClock.cs" />
<Compile Include="Time\ITimeZoneSelector.cs" />

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Orchard.Time {
public class CurrentTimeZoneWorkContext : IWorkContextStateProvider {
@@ -12,21 +13,23 @@ namespace Orchard.Time {
public Func<WorkContext, T> Get<T>(string name) {
if (name == "CurrentTimeZone") {
return ctx => {
var timeZone = _timeZoneSelectors
.Select(x => x.GetTimeZone(ctx.HttpContext))
.Where(x => x != null)
.OrderByDescending(x => x.Priority)
.FirstOrDefault();
if (timeZone == null || timeZone.TimeZone == null) {
return (T)(object)TimeZoneInfo.Utc;
}
return (T)(object)timeZone.TimeZone;
};
return ctx => (T)(object)CurrentTimeZone(ctx.HttpContext);
}
return null;
}
TimeZoneInfo CurrentTimeZone(HttpContextBase httpContext) {
var timeZone = _timeZoneSelectors
.Select(x => x.GetTimeZone(httpContext))
.Where(x => x != null)
.OrderByDescending(x => x.Priority)
.FirstOrDefault();
if (timeZone == null) {
return null;
}
return timeZone.TimeZone;
}
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Web;
namespace Orchard.Time {
/// <summary>
/// Implements <see cref="ITimeZoneSelector"/> by providing the timezone defined in the machine's local settings.
/// </summary>
public class FallbackTimeZoneSelector : ITimeZoneSelector {
public TimeZoneSelectorResult GetTimeZone(HttpContextBase context) {
return new TimeZoneSelectorResult {
Priority = -100,
TimeZone = TimeZoneInfo.Local
};
}
}
}

View File

@@ -14,8 +14,13 @@ namespace Orchard.Time {
public TimeZoneSelectorResult GetTimeZone(HttpContextBase context) {
var siteTimeZoneId = _workContextAccessor.GetContext(context).CurrentSite.SiteTimeZone;
if (String.IsNullOrEmpty(siteTimeZoneId)) {
return null;
}
return new TimeZoneSelectorResult {
Priority = 0,
Priority = -5,
TimeZone = TimeZoneInfo.FindSystemTimeZoneById(siteTimeZoneId)
};
}

View File

@@ -67,7 +67,7 @@ namespace Orchard.UI.Zones {
}
return parentMember;
}
public override object GetIndex(Func<object> proceed, System.Collections.Generic.IEnumerable<object> keys) {
public override object GetIndex(Func<object> proceed, object self, System.Collections.Generic.IEnumerable<object> keys) {
if (keys.Count() == 1) {
return GetMember(proceed, null, System.Convert.ToString(keys.Single()));
}