DO NOT DOWNLOAD. DOWNLOAD LATEST STABLE FROM RELEASE TAB

Added Image Cropper datatype

[TFS Changeset #55169]
This commit is contained in:
kenny
2009-06-20 13:49:35 +00:00
parent 894664b41a
commit ec5c1b79c7
16 changed files with 3541 additions and 1 deletions

View File

@@ -0,0 +1,60 @@
using System;
using System.Collections;
namespace umbraco.editorControls.imagecropper
{
public class Config
{
public string UploadPropertyAlias { get; set; }
public bool GenerateImages { get; set; }
public int Quality { get; set; }
public bool ShowLabel { get; set; }
public ArrayList presets { get; set; }
public Config(string configuration)
{
presets = new ArrayList();
string[] configData = configuration.Split('|');
if (configData.Length != 2) return;
string[] generalSettings = configData[0].Split(',');
UploadPropertyAlias = generalSettings[0];
GenerateImages = generalSettings[1] == "1";
ShowLabel = generalSettings[2] == "1";
int _quality;
if(generalSettings.Length >= 4 && Int32.TryParse(generalSettings[3], out _quality))
{
Quality = _quality;
}
else
{
Quality = 90;
}
string[] presetData = configData[1].Split(';');
for (int i=0; i < presetData.Length; i++)
{
string[] p = presetData[i].Split(',');
int targetWidth, targetHeight;
if (p.Length >= 4 && Int32.TryParse(p[1], out targetWidth) && Int32.TryParse(p[2], out targetHeight))
{
char[] cropPosition = { 'C', 'M' };
if(p.Length >= 5)
{
cropPosition = p[4].ToCharArray();
}
presets.Add(new Preset(p[0], targetWidth, targetHeight, p[3] == "1" ? true : false, cropPosition[0].ToString(), cropPosition[1].ToString()));
}
}
}
}
}

View File

@@ -0,0 +1,119 @@
namespace umbraco.editorControls.imagecropper
{
struct Crop
{
public int X;
public int Y;
public int X2;
public int Y2;
public Crop(int x, int y, int x2, int y2)
{
X = x;
Y = y;
X2 = x2;
Y2 = y2;
}
}
enum DefaultCropPosition
{
CenterCenter = 0,
CenterTop,
CenterBottom,
LeftCenter,
LeftTop,
LeftBottom,
RightCenter,
RightTop,
RightBottom
}
struct Preset
{
public string Name;
public int TargetWidth;
public int TargetHeight;
public bool KeepAspect;
public string PositionH;
public string PositionV;
public float Aspect
{
get { return (float)TargetWidth / TargetHeight; }
}
public Crop Fit(ImageInfo imageInfo)
{
Crop crop;
if (Aspect >= imageInfo.Aspect)
{
// crop widest hor ver
// relevant positioning: center top, center center, center bottom
float h = ((float)imageInfo.Width / TargetWidth) * TargetHeight;
crop.X = 0;
crop.X2 = imageInfo.Width;
switch(PositionV)
{
case "T":
crop.Y = 0;
crop.Y2 = (int)h;
break;
case "B":
crop.Y = imageInfo.Height - (int)h;
crop.Y2 = imageInfo.Height;
break;
default: // CC
crop.Y = (int)(imageInfo.Height - h) / 2;
crop.Y2 = (int)(crop.Y + h);
break;
}
}
else
{
// image widest
// relevant positioning: left/right center, left/right top, left/right bottom
float w = ((float)imageInfo.Height / TargetHeight) * TargetWidth;
crop.Y = 0;
crop.Y2 = imageInfo.Height;
switch (PositionH)
{
case "L":
crop.X = 0;
crop.X2 = (int)w;
break;
case "R":
crop.X = imageInfo.Width - (int)w;
crop.X2 = imageInfo.Width;
break;
default: // CC
crop.X = (int) (imageInfo.Width - w)/2;
crop.X2 = (int) (crop.X + w);
break;
}
}
return crop;
}
public Preset(string name, int targetWidth, int targetHeight, bool keepAspect, string positionH, string positionV)
{
Name = name;
TargetWidth = targetWidth;
TargetHeight = targetHeight;
KeepAspect = keepAspect;
PositionH = positionH;
PositionV = positionV;
}
}
}

View File

@@ -0,0 +1,192 @@
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using umbraco.cms.businesslogic.property;
using umbraco.cms.businesslogic.web;
using System.Xml;
using System.Text;
using umbraco.editorControls.imagecropper;
namespace umbraco.editorControls.imagecropper
{
public class DataEditor : PlaceHolder, umbraco.interfaces.IDataEditor
{
private umbraco.interfaces.IData data;
private Config config;
private XmlDocument _xml;
public Image imgImage = new Image();
public HiddenField hdnJson = new HiddenField();
public HiddenField hdnRaw = new HiddenField();
public HiddenField hdnSer = new HiddenField();
public DataEditor(umbraco.interfaces.IData Data, string Configuration)
{
data = Data;
config = new Config(Configuration);
}
public virtual bool TreatAsRichTextEditor { get { return false; } }
public bool ShowLabel { get { return config.ShowLabel; } }
public Control Editor { get { return this; } }
protected override void OnInit(EventArgs e)
//protected override void OnLoad(EventArgs e)
{
this.ID = "ImageCropper";
//base.OnInit(e);
int propertyId = ((umbraco.cms.businesslogic.datatype.DefaultData) data).PropertyId;
int currentDocumentId = ((umbraco.cms.businesslogic.datatype.DefaultData)data).NodeId;
Document currentDocument = new Document(currentDocumentId);
Property uploadProperty = currentDocument.getProperty(config.UploadPropertyAlias);
if(uploadProperty == null) return;
string relativeImagePath = uploadProperty.Value.ToString();
ImageInfo imageInfo = new ImageInfo(relativeImagePath);
imgImage.ImageUrl = relativeImagePath;
imgImage.ID = String.Format("cropBox_{0}", propertyId);
StringBuilder sbJson = new StringBuilder();
StringBuilder sbRaw = new StringBuilder();
try
{
_xml = new XmlDocument();
_xml.LoadXml(data.Value.ToString());
}
catch
{
_xml = createBaseXmlDocument();
}
sbJson.Append("{ \"current\": 0, \"crops\": [");
for (int i = 0; i < config.presets.Count; i++)
{
Preset preset = (Preset) config.presets[i];
Crop crop;
sbJson.Append("{\"name\":'" + preset.Name + "'");
sbJson.Append(",\"config\":{" +
String.Format("\"targetWidth\":{0},\"targetHeight\":{1},\"keepAspect\":{2}",
preset.TargetWidth, preset.TargetHeight,
(preset.KeepAspect ? "true" : "false") + "}"));
if (imageInfo.Exists)
{
crop = preset.Fit(imageInfo);
}
else
{
crop.X = 0;
crop.Y = 0;
crop.X2 = preset.TargetWidth;
crop.Y2 = preset.TargetHeight;
}
// stored
if (_xml.DocumentElement != null && _xml.DocumentElement.ChildNodes.Count == config.presets.Count)
{
XmlNode xmlNode = _xml.DocumentElement.ChildNodes[i];
int xml_x = Convert.ToInt32(xmlNode.Attributes["x"].Value);
int xml_y = Convert.ToInt32(xmlNode.Attributes["y"].Value);
int xml_x2 = Convert.ToInt32(xmlNode.Attributes["x2"].Value);
int xml_y2 = Convert.ToInt32(xmlNode.Attributes["y2"].Value);
DateTime fileDate = Convert.ToDateTime(_xml.DocumentElement.Attributes["date"].Value);
// only use xml values if image is the same and different from defaults (document is stored inbetween image upload and cropping)
//if (xml_x2 - xml_x != preset.TargetWidth || xml_y2 - xml_y != preset.TargetHeight)
//fileDate == imageInfo.DateStamp && (
if(crop.X != xml_x || crop.X2 != xml_x2 || crop.Y != xml_y || crop.Y2 != xml_y2)
{
crop.X = xml_x;
crop.Y = xml_y;
crop.X2 = xml_x2;
crop.Y2 = xml_y2;
}
}
sbJson.Append(",\"value\":{" + String.Format("\"x\":{0},\"y\":{1},\"x2\":{2},\"y2\":{3}", crop.X, crop.Y, crop.X2, crop.Y2) + "}}");
sbRaw.Append(String.Format("{0},{1},{2},{3}", crop.X, crop.Y, crop.X2, crop.Y2));
if (i < config.presets.Count - 1)
{
sbJson.Append(",");
sbRaw.Append(";");
}
}
sbJson.Append("]}");
hdnJson.Value = sbJson.ToString();
//hdnJson.ID = String.Format("json_{0}", propertyId);
hdnRaw.Value = sbRaw.ToString();
//hdnRaw.ID = String.Format("raw_{0}", propertyId);
Controls.Add(imgImage);
Controls.Add(hdnJson);
Controls.Add(hdnRaw);
string imageCropperInitScript =
"initImageCropper('" +
imgImage.ClientID + "', '" +
hdnJson.ClientID + "', '" +
hdnRaw.ClientID +
"');";
Page.ClientScript.RegisterStartupScript(GetType(), ClientID + "_imageCropper", imageCropperInitScript, true);
Page.ClientScript.RegisterClientScriptBlock(Resources.json2Script.GetType(), "json2Script", Resources.json2Script, true);
Page.ClientScript.RegisterClientScriptBlock(Resources.jCropCSS.GetType(), "jCropCSS", Resources.jCropCSS);
Page.ClientScript.RegisterClientScriptBlock(Resources.jCropScript.GetType(), "jCropScript", Resources.jCropScript, true);
Page.ClientScript.RegisterClientScriptBlock(Resources.imageCropperScript.GetType(), "imageCropperScript", Resources.imageCropperScript, true);
base.OnInit(e);
}
/// <summary>
/// Store data as string XML (overridden by ToXMl to store "real" XML
/// XML format:
/// <crops dateStamp="">
/// <crop name="" x="" y="" x2="" y2="" url="" />
/// </crops>
/// </summary>
public void Save()
{
ImageInfo imageInfo = new ImageInfo(imgImage.ImageUrl);
if (!imageInfo.Exists)
{
data.Value = "";
}
else
{
SaveData saveData = new SaveData(hdnRaw.Value);
data.Value = saveData.Xml(config, imageInfo);
imageInfo.GenerateThumbnails(saveData, config);
}
}
private static XmlDocument createBaseXmlDocument()
{
XmlDocument doc = new XmlDocument();
XmlNode root = doc.CreateElement("crops");
doc.AppendChild(root);
return doc;
}
}
}

View File

@@ -0,0 +1,60 @@
using System;
using System.Reflection;
namespace umbraco.editorControls.imagecropper
{
public class DataType : umbraco.cms.businesslogic.datatype.BaseDataType, umbraco.interfaces.IDataType
{
private umbraco.interfaces.IDataEditor _editor;
private umbraco.interfaces.IData _baseData;
private PrevalueEditor _prevalueEditor;
public override umbraco.interfaces.IDataEditor DataEditor
{
get
{
if (_editor == null)
_editor = new DataEditor(Data, ((PrevalueEditor)PrevalueEditor).Configuration);
return _editor;
}
}
public override umbraco.interfaces.IData Data
{
get
{
if (_baseData == null)
_baseData = new DataTypeData(this);
return _baseData;
}
}
public override Guid Id
{
get { return new Guid("7A2D436C-34C2-410F-898F-4A23B3D79F54"); }
}
public override string DataTypeName
{
get { return "Image Cropper"; }
}
public override umbraco.interfaces.IDataPrevalue PrevalueEditor
{
get
{
if (_prevalueEditor == null)
_prevalueEditor = new PrevalueEditor(this);
return _prevalueEditor;
}
}
public static int Version
{
get
{
Version version = Assembly.GetExecutingAssembly().GetName().Version;
return version.Major*1000 + version.Minor*100;
}
}
}
}

View File

@@ -0,0 +1,21 @@
using System.Xml;
namespace umbraco.editorControls.imagecropper
{
public class DataTypeData : umbraco.cms.businesslogic.datatype.DefaultData
{
public DataTypeData(umbraco.cms.businesslogic.datatype.BaseDataType DataType) : base(DataType) { }
public override XmlNode ToXMl(XmlDocument data)
{
if (Value.ToString() != "") {
XmlDocument xd = new XmlDocument();
xd.LoadXml(Value.ToString());
return data.ImportNode(xd.DocumentElement, true);
} else {
return base.ToXMl(data);
}
}
}
}

View File

@@ -0,0 +1,22 @@
using System.IO;
using System.Xml.Serialization;
namespace umbraco.editorControls.imagecropper
{
class Helper
{
public static string SerializeToString(object obj)
{
XmlSerializer serializer = new XmlSerializer(obj.GetType());
using (StringWriter writer = new StringWriter())
{
serializer.Serialize(writer, obj);
return writer.ToString();
}
}
}
}

View File

@@ -0,0 +1,106 @@
using System;
using System.Drawing;
using System.IO;
using System.Web;
using umbraco.editorControls.imagecropper;
namespace umbraco.editorControls.imagecropper
{
public class ImageInfo
{
public Image image { get; set; }
public string Name { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public float Aspect { get; set; }
public DateTime DateStamp { get; set; }
public string Path { get; set; }
public string RelativePath { get; set; }
public ImageInfo(string relativePath)
{
RelativePath = relativePath;
Path = HttpContext.Current.Server.MapPath(relativePath);
if (File.Exists(Path))
{
string fileName = Path.Substring(Path.LastIndexOf('\\') + 1);
Name = fileName.Substring(0, fileName.LastIndexOf('.'));
byte[] buffer = null;
using (FileStream fs = new FileStream(Path, FileMode.Open, FileAccess.Read))
{
buffer = new byte[fs.Length];
fs.Read(buffer, 0, (int) fs.Length);
fs.Close();
}
try
{
image = Image.FromStream(new MemoryStream(buffer));
Width = image.Width;
Height = image.Height;
Aspect = (float) Width/Height;
DateStamp = File.GetLastWriteTime(Path);
}
catch (Exception)
{
Width = 0;
Height = 0;
Aspect = 0;
}
}
else
{
Width = 0;
Height = 0;
Aspect = 0;
}
}
public bool Exists
{
get { return Width > 0 && Height > 0; }
}
public string Directory
{
get { return Path.Substring(0, Path.LastIndexOf('\\')); }
}
public void GenerateThumbnails(SaveData saveData, Config config)
{
if (config.GenerateImages)
{
for (int i = 0; i < config.presets.Count; i++)
{
Crop crop = (Crop) saveData.data[i];
Preset preset = (Preset) config.presets[i];
// Crop rectangle bigger than actual image
if(crop.X2 - crop.X > Width || crop.Y2 - crop.Y > Height)
{
crop = preset.Fit(this);
}
ImageTransform.Execute(
Path,
String.Format("{0}_{1}", Name, preset.Name),
crop.X,
crop.Y,
crop.X2 - crop.X,
crop.Y2 - crop.Y,
preset.TargetWidth,
preset.TargetHeight,
config.Quality
);
//BasePage bp = new BasePage();
//bp.speechBubble(BasePage.speechBubbleIcon.error, "Error",
// "One or more crops are out of bounds. Please correct and try again.");
}
}
}
}
}

View File

@@ -0,0 +1,212 @@
using System;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing;
using System.IO;
namespace umbraco.editorControls.imagecropper
{
public class ImageTransform
{
public static void Execute(string sourceFile, string name, int cropX, int cropY, int cropWidth, int cropHeight, int sizeWidth, int sizeHeight, long quality)
{
if (!File.Exists(sourceFile)) return;
string path = sourceFile.Substring(0, sourceFile.LastIndexOf('\\'));
// TODO: Make configurable and move to imageInfo
//if(File.Exists(String.Format(@"{0}\{1}.jpg", path, name))) return;
byte[] buffer = null;
using(FileStream fs = new FileStream(sourceFile, FileMode.Open, FileAccess.Read))
{
buffer = new byte[fs.Length];
fs.Read(buffer, 0, (int)fs.Length);
fs.Close();
}
Image image = Image.FromStream(new MemoryStream(buffer));
DirectoryInfo di = new DirectoryInfo(path);
if (!di.Exists) di.Create();
using(Image croppedImage = cropImage(image, new Rectangle(cropX, cropY, cropWidth, cropHeight)))
{
using(Image resizedImage = resizeImage(croppedImage, new Size(sizeWidth, sizeHeight)))
{
using (Bitmap b = new Bitmap(resizedImage))
{
saveJpeg(String.Format("{0}/{1}.jpg", path, name), b, quality);
}
}
}
//saveJpeg(
// String.Format("{0}/{1}.jpg", path, name),
// new Bitmap(
// resizeImage(cropImage(image, new Rectangle(cropX, cropY, cropWidth, cropHeight)), new Size(sizeWidth, sizeHeight))),
// quality
// );
//using (FileStream stm = new FileStream(sourceFile, FileMode.Open, FileAccess.Read))
//{
//using (Image image = Image.FromStream(stm))
//{
//}
//stm.Close();
//}
//using (Image image = Image.FromFile(sourceFile))
//{
// //image = cropImage(image, new Rectangle(cropX, cropY, cropWidth, cropHeight));
// //cropImage(image, new Rectangle(cropX, cropY, cropWidth, cropHeight));
// //image = resizeImage(image, new Size(sizeWidth, sizeHeight));
// //resizeImage(image, new Size(sizeWidth, sizeHeight));
// string path = sourceFile.Substring(0, sourceFile.LastIndexOf('\\') + 1) + "Crops";
// DirectoryInfo di = new DirectoryInfo(path);
// if (!di.Exists) di.Create();
// saveJpeg(
// String.Format("{0}/{1}.jpg", path, name),
// new Bitmap(
// resizeImage(cropImage(image, new Rectangle(cropX, cropY, cropWidth, cropHeight)), new Size(sizeWidth, sizeHeight))),
// quality
// );
// image.Dispose();
//}
}
private static void saveJpeg(string path, Bitmap img, long quality)
{
// Encoder parameter for image quality
EncoderParameter qualityParam = new EncoderParameter(Encoder.Quality, quality);
// Jpeg image codec
ImageCodecInfo jpegCodec = getEncoderInfo("image/jpeg");
if (jpegCodec == null)
return;
EncoderParameters encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = qualityParam;
img.Save(path, jpegCodec, encoderParams);
}
private static ImageCodecInfo getEncoderInfo(string mimeType)
{
// Get image codecs for all image formats
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
// Find the correct image codec
for (int i = 0; i < codecs.Length; i++)
if (codecs[i].MimeType == mimeType)
return codecs[i];
return null;
}
private static Image cropImage(Image img, Rectangle cropArea)
{
Bitmap bmpImage = new Bitmap(img);
Bitmap bmpCrop = bmpImage.Clone(cropArea, bmpImage.PixelFormat);
return (Image)(bmpCrop);
}
private static Image resizeImage(Image imgToResize, Size size)
{
//int sourceWidth = imgToResize.Width;
//int sourceHeight = imgToResize.Height;
//float nPercent = 0;
//float nPercentW = 0;
//float nPercentH = 0;
//nPercentW = ((float)size.Width / (float)sourceWidth);
//nPercentH = ((float)size.Height / (float)sourceHeight);
//if (nPercentH < nPercentW)
// nPercent = nPercentH;
//else
// nPercent = nPercentW;
//int destWidth = (int)(sourceWidth * nPercent);
//int destHeight = (int)(sourceHeight * nPercent);
int destWidth = size.Width;
int destHeight = size.Height;
Bitmap b = new Bitmap(destWidth, destHeight);
ImageAttributes ia = new ImageAttributes();
ia.SetWrapMode(WrapMode.TileFlipXY);
Graphics g = Graphics.FromImage(b);
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.Clear(Color.White);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;
g.DrawImage(imgToResize, new Rectangle(0, 0, destWidth, destHeight), 0, 0, imgToResize.Width,
imgToResize.Height, GraphicsUnit.Pixel, ia);
ia.Dispose();
g.Dispose();
return b;
#if false
int destWidth = size.Width;
int destHeight = size.Height;
using (Bitmap b = new Bitmap(destWidth, destHeight))
{
using (Graphics g = Graphics.FromImage(b))
{
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (ImageAttributes ia = new ImageAttributes())
{
ia.SetWrapMode(WrapMode.TileFlipXY);
g.Clear(Color.White);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;
g.DrawImage(imgToResize, new Rectangle(0, 0, destWidth, destHeight), 0, 0, imgToResize.Width,
imgToResize.Height, GraphicsUnit.Pixel, ia);
}
}
return b;
}
#endif
#if false
int destWidth = size.Width;
int destHeight = size.Height;
Bitmap b = new Bitmap(destWidth, destHeight);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return (Image)b;
#endif
}
}
}

View File

@@ -0,0 +1,413 @@
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using umbraco.BusinessLogic;
using umbraco.editorControls;
using umbraco.DataLayer;
using umbraco.interfaces;
namespace umbraco.editorControls.imagecropper
{
public class PrevalueEditor : PlaceHolder, IDataPrevalue
{
private readonly umbraco.cms.businesslogic.datatype.BaseDataType _dataType;
private TextBox txtPropertyAlias;
private CheckBox chkGenerateCrops;
private CheckBox chkShowLabel;
private Literal litQuality;
private TextBox txtQuality;
private SmartListBox slbPresets;
private TextBox txtCropName;
private TextBox txtTargetWidth;
private TextBox txtTargetHeight;
private CheckBox chkKeepAspect;
private DropDownList ddlDefaultPosH;
private DropDownList ddlDefaultPosV;
private Button btnUp;
private Button btnDown;
private Button btnAdd;
private Button btnRemove;
private Button btnGenerate;
//private RegularExpressionValidator revName;
//private RequiredFieldValidator rqfName;
//private ValidationSummary vsErrors;
public PrevalueEditor(umbraco.cms.businesslogic.datatype.BaseDataType dataType)
{
_dataType = dataType;
SetupChildControls();
}
public void SetupChildControls()
{
txtPropertyAlias = new TextBox {ID = "upload", Width = Unit.Pixel(100)};
chkGenerateCrops = new CheckBox {ID = "generateimg", AutoPostBack = true};
litQuality = new Literal {ID = "qualityLiteral", Text = " Quality ", Visible = false};
txtQuality = new TextBox {ID = "quality", Width = Unit.Pixel(30), Visible = false};
chkShowLabel = new CheckBox {ID = "label"};
slbPresets = new SmartListBox
{
ID = "presets",
SelectionMode = ListSelectionMode.Multiple,
Height = Unit.Pixel(123),
Width = Unit.Pixel(350)
};
txtCropName = new TextBox {ID = "presetname", Width = Unit.Pixel(100)};
txtTargetWidth = new TextBox {ID = "presetw", Width = Unit.Pixel(50)};
txtTargetHeight = new TextBox {ID = "preseth", Width = Unit.Pixel(50)};
chkKeepAspect = new CheckBox {ID = "aspect", Checked = true};
ddlDefaultPosH = new DropDownList {ID = "posh"};
ddlDefaultPosH.Items.Add(new ListItem("Left", "L"));
ddlDefaultPosH.Items.Add(new ListItem("Center", "C"));
ddlDefaultPosH.Items.Add(new ListItem("Right", "R"));
ddlDefaultPosV = new DropDownList {ID = "posv"};
ddlDefaultPosV.Items.Add(new ListItem("Top", "T"));
ddlDefaultPosV.Items.Add(new ListItem("Middle", "M"));
ddlDefaultPosV.Items.Add(new ListItem("Bottom", "B"));
btnUp = new Button {ID = "up", Text = "Up", Width = Unit.Pixel(60)};
btnDown = new Button {ID = "down", Text = "Down", Width = Unit.Pixel(60)};
btnAdd = new Button {ID = "add", Text = "Add", Width = Unit.Pixel(60)};
btnRemove = new Button {ID = "remove", Text = "Remove", Width = Unit.Pixel(60)};
btnGenerate = new Button {ID = "generate", Text = "Generate", Width = Unit.Pixel(60)};
//vsErrors = new ValidationSummary {ID = "summary", ValidationGroup = "cropper"};
//rqfName = new RequiredFieldValidator {ID = "namevalidator", ValidationGroup = "cropper", ControlToValidate = txtCropName.ClientID, ErrorMessage = "Crop name missing", Text="*" };
//revName = new RegularExpressionValidator
// {
// ID = "namevalidator",
// ValidationExpression = ".*[a-zA-Z0-9-_ ].*",
// ValidationGroup = "cropper",
// ErrorMessage = "Invalid name. Alphanumerical only please as this will be the filename",
// AssociatedControlID = txtCropName.ID
// };
Controls.Add(txtPropertyAlias);
Controls.Add(chkGenerateCrops);
Controls.Add(litQuality);
Controls.Add(txtQuality);
Controls.Add(chkShowLabel);
Controls.Add(slbPresets);
Controls.Add(txtCropName);
Controls.Add(txtTargetWidth);
Controls.Add(txtTargetHeight);
Controls.Add(chkKeepAspect);
Controls.Add(ddlDefaultPosH);
Controls.Add(ddlDefaultPosV);
Controls.Add(btnUp);
Controls.Add(btnDown);
Controls.Add(btnAdd);
Controls.Add(btnRemove);
Controls.Add(btnGenerate);
//Controls.Add(vsErrors);
//Controls.Add(rqfName);
//Controls.Add(revName);
btnUp.Click += _upButton_Click;
btnDown.Click += _downButton_Click;
btnAdd.Click += _addButton_Click;
btnRemove.Click += _removeButton_Click;
//btnGenerate.Click += _generateButton_Click;
chkGenerateCrops.CheckedChanged += _generateImagesCheckBox_CheckedChanged;
}
#if false
void _generateButton_Click(object sender, EventArgs e)
{
Config config = new Config(Configuration);
// get list of nodeids with this datatype
using (IRecordsReader rdr = SqlHelper.ExecuteReader(
"SELECT DISTINCT contentNodeId, " +
"(SELECT Alias FROM cmsPropertyType WHERE Id = pd.propertyTypeId) AS propertyAlias " +
"FROM cmsPropertyData pd " +
"WHERE PropertyTypeId IN (SELECT Id FROM cmsPropertyType WHERE DataTypeId = " + _dataType.DataTypeDefinitionId + ")"))
{
while (rdr.Read())
{
int documentId = rdr.GetInt("contentNodeId");
string propertyAlias = rdr.GetString("propertyAlias");
Document document = new Document(documentId);
Property cropProperty = document.getProperty(propertyAlias);
Property imageProperty = document.getProperty(config.UploadPropertyAlias);
if (cropProperty != null) // && cropProperty.Value.ToString() == ""
{
ImageInfo imageInfo = new ImageInfo(imageProperty.Value.ToString());
if (imageInfo.Exists)
{
SaveData saveData = new SaveData();
foreach (Preset preset in config.presets)
{
Crop crop = preset.Fit(imageInfo);
saveData.data.Add(crop);
}
//cropProperty.Value = saveData.Xml(config, imageInfo);
imageInfo.GenerateThumbnails(saveData, config);
if (document.Published)
{
//document.Publish(document.User);
//umbraco.library.UpdateDocumentCache(document.Id);
}
else
{
//document.Save();
}
}
}
}
}
}
#endif
void _generateImagesCheckBox_CheckedChanged(object sender, EventArgs e)
{
txtQuality.Visible = chkGenerateCrops.Checked;
litQuality.Visible = chkGenerateCrops.Checked;
}
void _upButton_Click(object sender, EventArgs e)
{
slbPresets.MoveUp();
}
void _downButton_Click(object sender, EventArgs e)
{
slbPresets.MoveDown();
}
void _removeButton_Click(object sender, EventArgs e)
{
for (int i = slbPresets.Items.Count - 1; i >= 0; i--)
{
if (slbPresets.Items[i].Selected)
slbPresets.Items.Remove(slbPresets.Items[i]);
}
}
void _addButton_Click(object sender, EventArgs e)
{
slbPresets.Items.Add(
new ListItem(
getListItemDisplayName(
txtCropName.Text,
txtTargetWidth.Text,
txtTargetHeight.Text,
chkKeepAspect.Checked ? "1" : "0",
String.Concat(ddlDefaultPosH.SelectedValue, ddlDefaultPosV.SelectedValue)),
String.Format("{0},{1},{2},{3},{4}",
txtCropName.Text,
txtTargetWidth.Text,
txtTargetHeight.Text,
chkKeepAspect.Checked ? "1" : "0",
String.Concat(ddlDefaultPosH.SelectedValue, ddlDefaultPosV.SelectedValue))
)
);
txtCropName.Text = "";
txtTargetWidth.Text = "";
txtTargetHeight.Text = "";
chkKeepAspect.Checked = true;
}
public Control Editor
{
get
{
return this;
}
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!Page.IsPostBack)
LoadData();
}
private void LoadData()
{
if (!string.IsNullOrEmpty(Configuration))
{
Config config = new Config(Configuration);
txtPropertyAlias.Text = config.UploadPropertyAlias;
chkGenerateCrops.Checked = config.GenerateImages;
chkShowLabel.Checked = config.ShowLabel;
txtQuality.Visible = chkShowLabel.Checked;
txtQuality.Text = config.Quality.ToString();
litQuality.Visible = chkShowLabel.Checked;
foreach (Preset preset in config.presets)
{
slbPresets.Items.Add(
new ListItem(
getListItemDisplayName(
preset.Name,
preset.TargetWidth.ToString(),
preset.TargetHeight.ToString(),
preset.KeepAspect ? "1" : "0",
String.Concat(preset.PositionH, preset.PositionV)),
String.Format("{0},{1},{2},{3},{4}{5}",
preset.Name,
preset.TargetWidth,
preset.TargetHeight,
preset.KeepAspect ? "1" : "0",
preset.PositionH, preset.PositionV)));
}
}
}
private static string getListItemDisplayName(string presetTemplateName, string width, string height, string keepAspect, string position)
{
return String.Format("{0}, width: {1}px, height: {2}px, keep aspect: {3}, {4}",
presetTemplateName,
width,
height,
keepAspect == "1" ? "yes" : "no",
position);
}
/// <summary>
/// Serialize configuration to:
/// uploadPropertyAlias,generateImages,showLabel|presetTemplateName,targetWidth,targetHeight,keepAspect;
/// </summary>
public void Save()
{
_dataType.DBType = (umbraco.cms.businesslogic.datatype.DBTypes)Enum.Parse(
typeof(umbraco.cms.businesslogic.datatype.DBTypes), DBTypes.Ntext.ToString(), true);
string generalData = String.Format("{0},{1},{2}",
txtPropertyAlias.Text,
chkGenerateCrops.Checked ? "1" : "0",
chkShowLabel.Checked ? "1" : "0"
);
string templateData = "";
for (int i = 0; i < slbPresets.Items.Count; i++)
{
templateData += slbPresets.Items[i].Value;
if (i < slbPresets.Items.Count - 1) templateData += ";";
}
string data = String.Format("{0}|{1}", generalData, templateData);
SqlHelper.ExecuteNonQuery("delete from cmsDataTypePreValues where datatypenodeid = @dtdefid",
SqlHelper.CreateParameter("@dtdefid", _dataType.DataTypeDefinitionId));
SqlHelper.ExecuteNonQuery("insert into cmsDataTypePreValues (datatypenodeid,[value],sortorder,alias) values (@dtdefid,@value,0,'')",
SqlHelper.CreateParameter("@dtdefid", _dataType.DataTypeDefinitionId), SqlHelper.CreateParameter("@value", data));
}
protected override void Render(HtmlTextWriter writer)
{
writer.Write("<p><strong>General</strong></p>");
writer.Write("<table>");
writer.Write(" <tr><td>Property alias: (eg. 'umbracoFile'):</td><td>");
txtPropertyAlias.RenderControl(writer);
writer.Write(" </td></tr>");
writer.Write(" <tr><td>Save crop images (/media/(imageid)/(filename)_(cropname).jpg):</td><td>");
chkGenerateCrops.RenderControl(writer);
litQuality.RenderControl(writer);
txtQuality.RenderControl(writer);
writer.Write(" </td></tr>");
writer.Write(" <tr><td>Show Label:</td><td>");
chkShowLabel.RenderControl(writer);
writer.Write(" </td></tr>");
writer.Write("</table>");
writer.Write("<p><strong>Crops</strong></p>");
writer.Write("<table>");
writer.Write(" <tr><td valign=\"top\">");
writer.Write(" <table>");
writer.Write(" <tr><td>Name</td><td>");
txtCropName.RenderControl(writer);
writer.Write(" </td></tr>");
writer.Write(" <tr><td>Target width</td><td>");
txtTargetWidth.RenderControl(writer);
writer.Write(" px</td></tr>");
writer.Write(" <tr><td>Target height</td><td>");
txtTargetHeight.RenderControl(writer);
writer.Write(" px</td></tr>");
writer.Write(" <tr><td>Default position&nbsp;</td><td>");
ddlDefaultPosH.RenderControl(writer);
writer.Write(" ");
ddlDefaultPosV.RenderControl(writer);
writer.Write(" </td></tr>");
writer.Write(" <tr><td>Keep aspect</td><td>");
chkKeepAspect.RenderControl(writer);
writer.Write(" </td></tr>");
writer.Write(" </table><br />");
btnAdd.RenderControl(writer);
writer.Write(" </td><td valign=\"top\">&nbsp;&nbsp;");
slbPresets.RenderControl(writer);
writer.Write(" </td><td valign=\"top\">");
btnUp.RenderControl(writer);
writer.Write(" <br />");
btnDown.RenderControl(writer);
writer.Write(" <br /><br /><br /><br /><br />");
btnRemove.RenderControl(writer);
writer.Write(" </td></tr>");
writer.Write("</table>");
//_generateButton.RenderControl(writer);
//_vsErrors.RenderControl(writer);
//_revName.RenderControl(writer);
}
public string Configuration
{
get
{
object conf =
SqlHelper.ExecuteScalar<object>("select value from cmsDataTypePreValues where datatypenodeid = @datatypenodeid",
SqlHelper.CreateParameter("@datatypenodeid", _dataType.DataTypeDefinitionId));
if (conf != null)
return conf.ToString();
return string.Empty;
}
}
public static ISqlHelper SqlHelper
{
get
{
return Application.SqlHelper;
}
}
}
}

View File

@@ -0,0 +1,156 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.3074
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace umbraco.editorControls.imagecropper
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("umbraco.editorControls.imagecropper.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to function initImageCropper(imageId, jsonId, rawId) {
/// $(function() {
/// $(&apos;.header a&apos;).click(function() {
/// initJcrop(imageId, jsonId, rawId); // if other tab
/// });
/// $(&apos;#&apos; + imageId).ready(function() {
/// setTimeout(&apos;initJcrop(&quot;&apos; + imageId + &apos;&quot;,&quot;&apos; + jsonId + &apos;&quot;,&quot;&apos; + rawId + &apos;&quot;)&apos;,100);
/// //initJcrop(imageId, jsonId, rawId); // if first tab
/// });
/// });
///}
///
///function initJcrop(imageId, jsonId, rawId) {
///
/// if ($(&apos;#&apos; + imageId).height() &gt; 0) {
/// if ($(&apos;.img&apos; + imageId + &apos;.ic-cr [rest of string was truncated]&quot;;.
/// </summary>
public static string imageCropperScript {
get {
return ResourceManager.GetString("imageCropperScript", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &lt;style type=&quot;text/css&quot;&gt;
////* Fixes issue here http://code.google.com/p/jcrop/issues/detail?id=1 */
///.jcrop-holder { text-align: left; }
///
///.jcrop-vline, .jcrop-hline
///{
/// font-size: 0;
/// position: absolute;
/// background: white url(&apos;/media/Jcrop.gif&apos;) top left repeat;
///}
///.jcrop-vline { height: 100%; width: 1px !important; }
///.jcrop-hline { width: 100%; height: 1px !important; }
///.jcrop-handle {
/// font-size: 1px;
/// width: 7px !important;
/// height: 7px !important;
/// border: 1px #eee solid;
/// background-color: [rest of string was truncated]&quot;;.
/// </summary>
public static string jCropCSS {
get {
return ResourceManager.GetString("jCropCSS", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to /**
/// * jquery.Jcrop.js v0.9.8
/// * jQuery Image Cropping Plugin
/// * @author Kelly Hallman &lt;khallman@gmail.com&gt;
/// * Copyright (c) 2008-2009 Kelly Hallman - released under MIT License {{{
/// *
/// * Permission is hereby granted, free of charge, to any person
/// * obtaining a copy of this software and associated documentation
/// * files (the &quot;Software&quot;), to deal in the Software without
/// * restriction, including without limitation the rights to use,
/// * copy, modify, merge, publish, distribute, sublicense, and/or s [rest of string was truncated]&quot;;.
/// </summary>
public static string jCropScript {
get {
return ResourceManager.GetString("jCropScript", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to /*
/// http://www.JSON.org/json2.js
/// 2008-11-19
///
/// Public Domain.
///
/// NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
///
/// See http://www.JSON.org/js.html
///
/// This file creates a global JSON object containing two methods: stringify
/// and parse.
///
/// JSON.stringify(value, replacer, space)
/// value any JavaScript value, usually an object or array.
///
/// replacer an optional parameter that determines how object
/// values are st [rest of string was truncated]&quot;;.
/// </summary>
public static string json2Script {
get {
return ResourceManager.GetString("json2Script", resourceCulture);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,104 @@
using System;
using System.Collections;
using System.Xml;
namespace umbraco.editorControls.imagecropper
{
public class SaveData
{
public ArrayList data { get; set; }
public string Xml(Config config, ImageInfo imageInfo)
{
XmlDocument doc = createBaseXmlDocument();
XmlNode root = doc.DocumentElement;
if (root == null) return null;
XmlNode dateStampNode = doc.CreateNode(XmlNodeType.Attribute, "date", null);
dateStampNode.Value = imageInfo.DateStamp.ToString();
root.Attributes.SetNamedItem(dateStampNode);
for (int i = 0; i < data.Count; i++)
{
Crop crop = (Crop) data[i];
Preset preset = (Preset) config.presets[i];
XmlNode newNode = doc.CreateElement("crop");
XmlNode nameNode = doc.CreateNode(XmlNodeType.Attribute, "name", null);
nameNode.Value = preset.Name;
newNode.Attributes.SetNamedItem(nameNode);
XmlNode xNode = doc.CreateNode(XmlNodeType.Attribute, "x", null);
xNode.Value = crop.X.ToString();
newNode.Attributes.SetNamedItem(xNode);
XmlNode yNode = doc.CreateNode(XmlNodeType.Attribute, "y", null);
yNode.Value = crop.Y.ToString();
newNode.Attributes.SetNamedItem(yNode);
XmlNode x2Node = doc.CreateNode(XmlNodeType.Attribute, "x2", null);
x2Node.Value = crop.X2.ToString();
newNode.Attributes.SetNamedItem(x2Node);
XmlNode y2Node = doc.CreateNode(XmlNodeType.Attribute, "y2", null);
y2Node.Value = crop.Y2.ToString();
newNode.Attributes.SetNamedItem(y2Node);
if (config.GenerateImages)
{
XmlNode urlNode = doc.CreateNode(XmlNodeType.Attribute, "url", null);
urlNode.Value = String.Format("{0}/{1}_{2}.jpg",
imageInfo.RelativePath.Substring(0,
imageInfo.RelativePath.LastIndexOf(
'/')),
imageInfo.Name,
preset.Name);
newNode.Attributes.SetNamedItem(urlNode);
}
root.AppendChild(newNode);
}
return doc.InnerXml;
}
public SaveData()
{
data = new ArrayList();
}
public SaveData(string raw)
{
data = new ArrayList();
string[] crops = raw.Split(';');
foreach (string crop in crops)
{
var val = crop.Split(',');
data.Add(
new Crop(
Convert.ToInt32(val[0]),
Convert.ToInt32(val[1]),
Convert.ToInt32(val[2]),
Convert.ToInt32(val[3])
)
);
}
}
private static XmlDocument createBaseXmlDocument()
{
XmlDocument doc = new XmlDocument();
XmlNode root = doc.CreateElement("crops");
doc.AppendChild(root);
return doc;
}
}
}

View File

@@ -0,0 +1,47 @@
using System.Web.UI.WebControls;
namespace umbraco.editorControls.imagecropper
{
public class SmartListBox : ListBox
{
//Moves the selected items up one level
public void MoveUp()
{
for (int i = 0; i < Items.Count; i++)
{
if (Items[i].Selected)//identify the selected item
{
//swap with the top item(move up)
if (i > 0 && !Items[i - 1].Selected)
{
ListItem bottom = Items[i];
Items.Remove(bottom);
Items.Insert(i - 1, bottom);
Items[i - 1].Selected = true;
}
}
}
}
//Moves the selected items one level down
public void MoveDown()
{
int startindex = Items.Count - 1;
for (int i = startindex; i > -1; i--)
{
if (Items[i].Selected)//identify the selected item
{
//swap with the lower item(move down)
if (i < startindex && !Items[i + 1].Selected)
{
ListItem bottom = Items[i];
Items.Remove(bottom);
Items.Insert(i + 1, bottom);
Items[i + 1].Selected = true;
}
}
}
}
}
}

View File

@@ -211,6 +211,18 @@
<Compile Include="folderbrowser\folderBrowser.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="imagecropper\Config.cs" />
<Compile Include="imagecropper\Data.cs" />
<Compile Include="imagecropper\DataEditor.cs" />
<Compile Include="imagecropper\DataType.cs" />
<Compile Include="imagecropper\DataTypeData.cs" />
<Compile Include="imagecropper\Helper.cs" />
<Compile Include="imagecropper\ImageInfo.cs" />
<Compile Include="imagecropper\ImageManipulation.cs" />
<Compile Include="imagecropper\PrevalueEditor.cs" />
<Compile Include="imagecropper\Resources.Designer.cs" />
<Compile Include="imagecropper\SaveData.cs" />
<Compile Include="imagecropper\SmartListBox.cs" />
<Compile Include="KeyValuePrevalueEditor.cs">
<SubType>Code</SubType>
</Compile>
@@ -343,6 +355,7 @@
<Compile Include="yesno\YesNoDataType.cs">
<SubType>Code</SubType>
</Compile>
<EmbeddedResource Include="imagecropper\Resources.resx" />
<EmbeddedResource Include="textfield\textFieldDataEditor.resx">
<DependentUpon>textFieldDataEditor.cs</DependentUpon>
<SubType>Designer</SubType>

View File

@@ -1,6 +1,6 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<ProductVersion>9.0.21022</ProductVersion>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{651E1350-91B6-44B7-BD60-7207006D7003}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
@@ -1539,6 +1539,7 @@
<Content Include="umbraco\css\permissionsEditor.css" />
<Content Include="umbraco\images\editor\spellchecker.gif" />
<Content Include="umbraco_client\Application\JQuery\jquery.cookie.js" />
<Content Include="umbraco_client\imagecropper\Jcrop.gif" />
<Content Include="umbraco_client\Tree\Themes\default\context.gif" />
<Content Include="umbraco_client\Tree\Themes\default\create.png" />
<Content Include="umbraco_client\Tree\Themes\default\dot.gif" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B