using System;
using System.Configuration;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Text;
namespace YUI.Controls
{
public enum ColorPickerMode
{
/// <summary>
/// The color picker widget will be rendered into a movable virtual window within the document
/// </summary>
FloatingDialog,
/// <summary>
/// The color picker will be statically rendered into the control specified by the ContainerControl property
/// </summary>
Inline
}
public enum ColorPickerUpdateMode
{
/// <summary>
/// Whenever the user clicks on a color, the callback and client code will be called.
/// </summary>
Continuous,
/// <summary>
/// Used on dialogs only (FloatingDialog)
/// </summary>
OnConfirm
}
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
//[DefaultProperty("ContainerControl")]
[ToolboxData("<{0}:ColorPicker run=\"server\"> </{0}:ColorPicker>")]
//[ParseChildren(true, "Text")]
public class ColorPicker : WebControl, ICallbackEventHandler
{
private string ContainerClientID
{
get
{
return ClientID + "_container";
}
}
private string HiddenFieldClientID
{
get
{
return ClientID + "_value";
}
}
private string DialogContainerClientID
{
get
{
return ClientID + "_dialog";
}
}
#region Behavior properties
[Bindable(false)]
[Category("Behavior")]
[Description("Color picker mode. One of: FloatingDialog, Inline.")]
[DefaultValue("")]
[Localizable(false)]
public ColorPickerMode ColorPickerMode { get; set; }
[Bindable(true)]
[Category("Behavior")]
[Description("The update mode of the Color Picker. Either OnConfirm or Continuous.")]
[DefaultValue("")]
[Localizable(false)]
public ColorPickerUpdateMode UpdateMode { get; set; }
[Bindable(false)]
[Category("Behavior")]
[Description("Enables animation of the color picker thumb")]
[DefaultValue(false)]
[Localizable(false)]
public bool EnableAnimation { get; set; }
[Bindable(false)]
[Category("Behavior")]
[Description("Color picker modal behavior.")]
[DefaultValue("")]
[Localizable(false)]
public bool ModalBehavior { get; set; }
[Bindable(false)]
[Category("Behavior")]
[Description("Color picker modal behavior.")]
[DefaultValue("")]
[Localizable(false)]
public bool UseCallback { get; set; }
#endregion
#region Color Picker Properties
[Bindable(true)]
[Category("Color Picker")]
[Description("The Color picker RGB Value")]
[DefaultValue("")]
[Localizable(false)]
public string Color
{
get
{
return (string)ViewState["Color"];
}
set
{
if (Color != value)
{
ViewState["Color"] = value;
if (ColorChanged != null)
ColorChanged(this, EventArgs.Empty);
}
}
}
[Bindable(true)]
[Category("Color Picker")]
[Description("Controls whether the color picker should be rendered as visible or hidden")]
[DefaultValue(true)]
[Localizable(false)]
public bool IsHidden
{
get
{
var vsp = ViewState["IsHidden"];
if (vsp == null)
return false;
return (bool)vsp;
}
set
{
ViewState["IsHidden"] = value;
}
}
[Bindable(true)]
[Category("Color Picker")]
[Description("Hide/show the entire set of controls. Default: true.")]
[DefaultValue(true)]
[Localizable(false)]
public bool? ShowControls
{
get
{
var vsp = ViewState["ShowControls"];
if (vsp == null)
return null;
return (bool)vsp;
}
set
{
ViewState["ShowControls"] = value;
}
}
[Bindable(true)]
[Category("Color Picker")]
[Description("Hide/show the hex controls. Default: true.")]
[DefaultValue(true)]
[Localizable(false)]
public bool? ShowHexControls
{
get
{
var vsp = ViewState["ShowHexControls"];
if (vsp == null)
return null;
return (bool)vsp;
}
set
{
ViewState["ShowHexControls"] = value;
}
}
[Bindable(true)]
[Category("Color Picker")]
[Description("Hide/show the hex summary. Default: true.")]
[DefaultValue(true)]
[Localizable(false)]
public bool? ShowHexSummary
{
get
{
var vsp = ViewState["ShowHexSummary"];
if (vsp == null)
return null;
return (bool)vsp;
}
set
{
ViewState["ShowHexControls"] = value;
}
}
[Bindable(true)]
[Category("Color Picker")]
[Description("Hide/show the HSV controls. Default: false.")]
[DefaultValue(false)]
[Localizable(false)]
public bool? ShowHSVControls
{
get
{
var vsp = ViewState["ShowHSVControls"];
if (vsp == null)
return null;
return (bool)vsp;
}
set
{
ViewState["ShowHSVControls"] = value;
}
}
[Bindable(true)]
[Category("Color Picker")]
[Description("Hide/show the RGB controls. Default: true.")]
[DefaultValue(true)]
[Localizable(false)]
public bool? ShowRGBControls
{
get
{
var vsp = ViewState["ShowRGBControls"];
if (vsp == null)
return null;
return (bool)vsp;
}
set
{
ViewState["ShowRGBControls"] = value;
}
}
[Bindable(true)]
[Category("Color Picker")]
[Description("Hide/show the websafe-color swatch. Default: true.")]
[DefaultValue(true)]
[Localizable(false)]
public bool? ShowWebSafe
{
get
{
var vsp = ViewState["ShowWebSafe"];
if (vsp == null)
return null;
return (bool)vsp;
}
set
{
ViewState["ShowWebSafe"] = value;
}
}
#endregion
[DefaultValue(true)]
public bool LoadYui
{
get
{
var vsp = ViewState["LoadYui"];
if (vsp == null)
return true;
return (bool)vsp;
}
set
{
ViewState["LoadYui"] = value;
}
}
#region Color Picker events
[Category("Events")]
[Description("The Color picker server-side ColorChanged handler")]
[DefaultValue("")]
[Localizable(false)]
public event EventHandler ColorChanged;
[Bindable(true)]
[Category("Events")]
[Description("The Color picker client-side ColorChanged handler code")]
[DefaultValue("")]
[Localizable(false)]
public string OnClientColorChanged { get; set; }
#endregion
#region ASP.NET stuff
/// <summary>
/// Registers YUI and the initializer. On postbacks, loads the update value (which, in turn, will fire events)
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
NextControlInitializerFunctionId = ContainerClientID + "_loadyui";
NextControlUpdateFunctionId = ContainerClientID + "_updateyui";
if (ModalBehavior && ColorPickerMode == ColorPickerMode.Inline)
throw new Exception("ModalBehavior cannot be set on ColorPickerMode Fixed");
if (LoadYui)
{
Page.ClientScript.RegisterClientScriptInclude(GetType(), "YuiLoader", "http://yui.yahooapis.com/2.7.0/build/yuiloader/yuiloader-min.js");
}
if (!Page.IsPostBack)
{
}
else if (Page.IsPostBack && !Page.IsCallback)
{
var val = Page.Request[HiddenFieldClientID];
if (val.Length == 6)
Color = "#" + val; }
}
/// <summary>
/// Initializes the script that will create the color picker on the next postback
/// </summary>
private string GetNextControlUpdateFunction()
{
var sb = new StringBuilder();
sb.AppendLine("var picker = c.context;");
//Not implemented
return sb.ToString();
}
/// <summary>
/// Returns the YUI loader code that will load the color picker and its dependencies, and then call this color picker instance's initializer
/// </summary>
/// <returns></returns>
private string GetYuiLoaderCode()
{
string modules = "'colorpicker'";
if (EnableAnimation)
modules += ",'animation'";
if (ColorPickerMode == ColorPickerMode.FloatingDialog)
modules += ",'container','event'";
return @"
(function() {
var loader = new YAHOO.util.YUILoader({
base: '',
require: [" + modules + @"],
loadOptional: false,
combine: true,
filter: 'MIN',
allowRollup: true,
onSuccess: function() { " + NextControlInitializerFunctionId + @"();}
});
loader.insert();
})();
";
}
/// <summary>
/// The name of the function that will initialize this color picker instance
/// </summary>
string NextControlInitializerFunctionId;
/// <summary>
/// The name of the function that will update this color picker instance after the callback
/// </summary>
string NextControlUpdateFunctionId;
/// <summary>
/// Callback handler
/// </summary>
/// <param name="eventArg"></param>
public void RaiseCallbackEvent(string eventArg)
{
Color = "#" + eventArg;
}
/// <summary>
/// Callback handler
/// </summary>
/// <returns></returns>
public string GetCallbackResult()
{
return "";
}
protected override HtmlTextWriterTag TagKey
{
get
{
return HtmlTextWriterTag.Div;
}
}
/// <summary>
/// Writes the color picker instance's initialization script
/// </summary>
/// <param name="e"></param>
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
if (UseCallback)
Page.ClientScript.RegisterStartupScript(GetType(), NextControlUpdateFunctionId, "function " + NextControlUpdateFunctionId + "(c) {" + GetNextControlUpdateFunction() + "}", true);
Page.ClientScript.RegisterClientScriptBlock(GetType(), "YuiColorPickerJs", Code, true);
int[] colors = ParseColor(Color);
var script = new StringBuilder();
script.Append("ASPYUI.CreateColorPicker(");
script.AppendFormat("'{0}',", HiddenFieldClientID);
script.AppendFormat("'{0}',", ContainerClientID);
script.AppendFormat("function(){{{0}}},", (OnClientColorChanged ?? ""));
script.AppendFormat("\"{0}\",", UseCallback ? Page.ClientScript.GetCallbackEventReference(this, "hex", NextControlUpdateFunctionId, "picker") : "");
script.AppendFormat("'{0}',", ColorPickerMode.ToString());
script.AppendFormat("'{0}',", DialogContainerClientID);
script.AppendFormat("{0},", GetJsBool(ModalBehavior));
script.AppendFormat("{0},", GetJsBool(IsHidden));
script.AppendFormat("{0},", GetJsBool(ShowControls, true));
script.AppendFormat("{0},", GetJsBool(ShowHexControls, true));
script.AppendFormat("{0},", GetJsBool(ShowHexSummary, true));
script.AppendFormat("{0},", GetJsBool(ShowHSVControls, false));
script.AppendFormat("{0},", GetJsBool(ShowRGBControls, true));
script.AppendFormat("{0},", GetJsBool(ShowWebSafe, true));
script.AppendFormat("[{0},{1},{2}],", colors[0], colors[1], colors[2]);
script.AppendFormat("'{0}');", UpdateMode.ToString());
if (LoadYui)
{
script.Insert(0, "ASPYUI.Callbacks.push(function(){");
script.Append("});");
script.Append("ASPYUI.Modules.colorpicker = true;");
if (EnableAnimation)
script.Append("ASPYUI.Modules.animation = true;");
if (ColorPickerMode == ColorPickerMode.FloatingDialog)
{
script.Append("ASPYUI.Modules.container = true;");
script.Append("ASPYUI.Modules.event = true;");
}
}
else
{
script.Insert(0, "YAHOO.util.Event.onDOMReady(function(){");
script.Append("});");
}
Page.ClientScript.RegisterStartupScript(GetType(), NextControlInitializerFunctionId, script.ToString(), true);
if (LoadYui)
Page.ClientScript.RegisterStartupScript(GetType(), "LoadYUI", "ASPYUI.LoadYuiAsync();", true);
Page.ClientScript.RegisterHiddenField(HiddenFieldClientID, Color);
}
/// <summary>
/// Returns a javascript statement that hides the color picker
/// </summary>
/// <returns></returns>
public string GetClientHidePickerScript()
{
switch (ColorPickerMode)
{
case ColorPickerMode.Inline:
return "document.getElementById('" + ContainerClientID + "').style.display='none';";
case ColorPickerMode.FloatingDialog:
return "document.getElementById('" + DialogContainerClientID + "').dialog.cancel();";
default:
return "";
}
}
/// <summary>
/// Returns a javascript statement that shows the color picker
/// </summary>
/// <returns></returns>
public string GetClientShowPickerScript()
{
switch (ColorPickerMode)
{
case ColorPickerMode.Inline:
return "document.getElementById('" + ContainerClientID + "').style.display='';";
case ColorPickerMode.FloatingDialog:
return "document.getElementById('" + DialogContainerClientID + "').dialog.show();";
default:
return "";
}
}
/// <summary>
/// Return a javascript expression that evaluates to "#rrggbb"
/// </summary>
/// <returns></returns>
public string GetClientGetPickerColorScript()
{
return "document.getElementById('" + HiddenFieldClientID + "').value";
}
#endregion
#region Utils
/// <summary>
/// Used to parse an RGB color from value into the Color Picker widget
/// </summary>
/// <param name="RGB"></param>
/// <returns></returns>
private int[] ParseColor(string RGB)
{
int[] ret = new int[3];
if (String.IsNullOrEmpty(RGB))
RGB = "ffffff";
if (RGB.StartsWith("#") || RGB.Length == 6)
{
if (RGB.StartsWith("#"))
RGB = RGB.Substring(1);
if (RGB.Length == 3)
{
var r = RGB.Substring(0, 1);
ret[0] = int.Parse(r, System.Globalization.NumberStyles.HexNumber);
var g = RGB.Substring(1, 1);
ret[1] = int.Parse(g, System.Globalization.NumberStyles.HexNumber);
var b = RGB.Substring(2, 1);
ret[2] = int.Parse(b, System.Globalization.NumberStyles.HexNumber);
}
else if (RGB.Length == 6)
{
var r = RGB.Substring(0, 2);
ret[0] = int.Parse(r, System.Globalization.NumberStyles.HexNumber);
var g = RGB.Substring(2, 2);
ret[1] = int.Parse(g, System.Globalization.NumberStyles.HexNumber);
var b = RGB.Substring(4, 2);
ret[2] = int.Parse(b, System.Globalization.NumberStyles.HexNumber);
}
else throw new Exception("Invalid hex RGB value");
}
else if (RGB.Split(',').Length == 3)
{
var parts = RGB.Split(',');
var r = parts[0];
ret[0] = Int32.Parse(r);
var g = parts[0];
ret[1] = Int32.Parse(r);
var b = parts[0];
ret[2] = Int32.Parse(r);
}
else throw new Exception("Invalid color value");
if (ret[0] < 0 || ret[0] > 255)
throw new Exception("Invalid Red component value");
if (ret[1] < 0 || ret[1] > 255)
throw new Exception("Invalid Green component value");
if (ret[2] < 0 || ret[2] > 255)
throw new Exception("Invalid Blue component value");
return ret;
}
/// <summary>
/// Returns either true or false, with a default value.
/// </summary>
/// <param name="value"></param>
/// <param name="defaultValue"></param>
/// <returns></returns>
private string GetJsBool(bool? value, bool defaultValue)
{
return GetJsBool(value.GetValueOrDefault(defaultValue));
}
private string GetJsBool(bool v)
{
return v ? "true" : "false";
}
#endregion
protected override void RenderContents(HtmlTextWriter writer)
{
writer.WriteBeginTag("div");
writer.WriteAttribute("id", DialogContainerClientID);
if (ColorPickerMode == ColorPickerMode.FloatingDialog)
{
writer.WriteAttribute("class", "yui-picker-panel");
writer.WriteAttribute("visibility", "hidden");
writer.Write(HtmlTextWriter.TagRightChar);
writer.WriteBeginTag("div");
writer.WriteAttribute("class", "hd");
writer.Write(HtmlTextWriter.TagRightChar);
writer.WriteEncodedText("Please choose a color:");
writer.WriteEndTag("div");
writer.WriteBeginTag("div");
writer.WriteAttribute("class", "bd");
writer.Write(HtmlTextWriter.TagRightChar);
}
else
writer.Write(HtmlTextWriter.TagRightChar);
writer.WriteBeginTag("div");
writer.WriteAttribute("id", ContainerClientID);
writer.WriteAttribute("style", "position:relative;height:220px");//width:420px;
writer.Write(HtmlTextWriter.SelfClosingTagEnd);
if (ColorPickerMode == ColorPickerMode.FloatingDialog)
{
writer.WriteEndTag("div"); //close the body div
writer.WriteBeginTag("div");
writer.WriteAttribute("class", "ft");
writer.Write(HtmlTextWriter.TagRightChar);
//writer.WriteEncodedText("Footer text");
writer.WriteEndTag("div");
}
writer.WriteEndTag("div");
}
const string Code = @"
if (typeof(ASPYUI)=='undefined')
ASPYUI = {};
if (typeof(ASPYUI.Callbacks)=='undefined')
ASPYUI.Callbacks=[];
if (typeof(ASPYUI.Modules)=='undefined')
ASPYUI.Modules={};
if (typeof(ASPYUI.LoadYuiAsync)=='undefined')
ASPYUI.LoadYuiAsync = function()
{
window.setTimeout(ASPYUI.LoadYui,0);
}
if (typeof(ASPYUI.LoadYui)=='undefined')
ASPYUI.LoadYui = function()
{
var modules = [];
for (var i in ASPYUI.Modules)
modules.push(i);
var loader = new YAHOO.util.YUILoader(
{
base: '',
require: modules,
loadOptional: false,
combine: true,
filter: 'MIN',
allowRollup: true,
onSuccess: function()
{
for (var j=0;j<ASPYUI.Callbacks.length;j++)
try
{
ASPYUI.Callbacks[j]();
}
catch(e1)
{
}
}
});
loader.insert();
}
ASPYUI.CreateColorPicker = function( HiddenFieldClientID,
ContainerClientID,
OnClientValueChanged,
CallbackRef,
ColorPickerMode,
DialogContainerClientID,
ModalBehavior,
IsHidden,
ShowControls,
ShowHexControls,
ShowHexSummary,
ShowHSVControls,
ShowRGBControls,
ShowWebSafe,
RGB, //[int,int,int]
UpdateMode
)
{
var picker, dialog, container, hiddenField, valueChangeHandler, hex, revertValueHandler;
hiddenField = document.getElementById(HiddenFieldClientID);
container = new YAHOO.util.Element(ContainerClientID);
new YAHOO.util.Element(document.body).addClass('yui-skin-sam');
//Create value changed handler
function valueChangeHandler()
{
hex = picker.get('hex');
if (HiddenFieldClientID != null)
hiddenField.value = hex;
if (OnClientValueChanged != null)
{
try
{
OnClientValueChanged();
}
catch(e1)
{
}
}
if (CallbackRef!=null)
{
try
{
eval(CallbackRef+';');
}
catch(e2)
{
}
}
}
//Create revert handler
revertValueHandler = function() {picker.set('hex',dialog._initialPickerValue);}
function setupControl()
{
picker = new YAHOO.widget.ColorPicker(container,
{
showcontrols: ShowControls
,showhexcontrols: ShowHexControls
,showhexsummary: ShowHexSummary
,showhsvcontrols: ShowHSVControls
,showrgbcontrols: ShowRGBControls
,showwebsafe: ShowWebSafe
,images:
{
PICKER_THUMB: 'http://yui.yahooapis.com/2.7.0/build/colorpicker/assets/picker_thumb.png',
HUE_THUMB: 'http://yui.yahooapis.com/2.7.0/build/colorpicker/assets/hue_thumb.png'
}
,container: ((ColorPickerMode == ColorPickerMode.FloatingDialog) ? dialog : undefined)
});
container.get('element')._picker = picker;
if (RGB)
{
picker.skipAnim = true;
picker.setValue(RGB, true);
picker.skipAnim = false;
}
if (ColorPickerMode == 'FloatingDialog')
{
if (UpdateMode=='Continuous')
{
picker.on('rgbChange', valueChangeHandler);
}
}
else if (ColorPickerMode == 'Inline')
{
if (UpdateMode == 'Continuous')
picker.on('rgbChange', valueChangeHandler);
}
hiddenField.value = picker.get('hex');
}
if (ColorPickerMode == 'FloatingDialog')
{
dialog = new YAHOO.widget.Dialog(DialogContainerClientID,
{
width : '500px',
close: false,
fixedcenter : true,
visible : false,
modal : ModalBehavior,
zindex: 4,
constraintoviewport : true,
buttons : [
{ text:'OK',handler: function(){dialog.cancel(); valueChangeHandler(); }, isDefault:true },
{ text:'Cancel', handler: function(){revertValueHandler(); dialog.cancel(); } } ]
});
dialog.showEvent.subscribe(function() { dialog._initialPickerValue=picker.get('hex'); });
dialog.renderEvent.subscribe(function() {setupControl();});
dialog.render();
document.getElementById(DialogContainerClientID).dialog = dialog;
if (!IsHidden)
{
dialog.show();
}
}
else
{
container.addClass('yui-skin-sam');
if (IsHidden)
container.setStyle('display','none');
setupControl();
}
};";
}
}