@qooxdoo/framework
Version:
The JS Framework for Coders
303 lines (256 loc) • 8.34 kB
JavaScript
/* ************************************************************************
qooxdoo - the new era of web development
http://qooxdoo.org
Copyright:
2013 1&1 Internet AG, Germany, http://www.1und1.de
License:
MIT: https://opensource.org/licenses/MIT
See the LICENSE file in the project's top-level directory for details.
Authors:
* Martin Wittemann (martinwittemann)
* Daniel Wagner (danielwagner)
************************************************************************ */
/**
* Decorator which uses the CSS3 border image properties.
*/
qx.Mixin.define("qx.ui.decoration.MBorderImage", {
properties :
{
/**
* Base image URL.
*/
borderImage :
{
check : "String",
nullable : true,
apply : "_applyBorderImage"
},
/**
* The top slice line of the base image. The slice properties divide the
* image into nine regions, which define the corner, edge and the center
* images.
*/
sliceTop :
{
check : "Integer",
nullable : true,
init : null,
apply : "_applyBorderImage"
},
/**
* The right slice line of the base image. The slice properties divide the
* image into nine regions, which define the corner, edge and the center
* images.
*/
sliceRight :
{
check : "Integer",
nullable : true,
init : null,
apply : "_applyBorderImage"
},
/**
* The bottom slice line of the base image. The slice properties divide the
* image into nine regions, which define the corner, edge and the center
* images.
*/
sliceBottom :
{
check : "Integer",
nullable : true,
init : null,
apply : "_applyBorderImage"
},
/**
* The left slice line of the base image. The slice properties divide the
* image into nine regions, which define the corner, edge and the center
* images.
*/
sliceLeft :
{
check : "Integer",
nullable : true,
init : null,
apply : "_applyBorderImage"
},
/**
* The slice properties divide the image into nine regions, which define the
* corner, edge and the center images.
*/
slice :
{
group : [ "sliceTop", "sliceRight", "sliceBottom", "sliceLeft" ],
mode : "shorthand"
},
/**
* This property specifies how the images for the sides and the middle part
* of the border image are scaled and tiled horizontally.
*
* Values have the following meanings:
* <ul>
* <li><strong>stretch</strong>: The image is stretched to fill the area.</li>
* <li><strong>repeat</strong>: The image is tiled (repeated) to fill the area.</li>
* <li><strong>round</strong>: The image is tiled (repeated) to fill the area. If it does not
* fill the area with a whole number of tiles, the image is rescaled so
* that it does.</li>
* </ul>
*/
repeatX :
{
check : ["stretch", "repeat", "round"],
init : "stretch",
apply : "_applyBorderImage"
},
/**
* This property specifies how the images for the sides and the middle part
* of the border image are scaled and tiled vertically.
*
* Values have the following meanings:
* <ul>
* <li><strong>stretch</strong>: The image is stretched to fill the area.</li>
* <li><strong>repeat</strong>: The image is tiled (repeated) to fill the area.</li>
* <li><strong>round</strong>: The image is tiled (repeated) to fill the area. If it does not
* fill the area with a whole number of tiles, the image is rescaled so
* that it does.</li>
* </ul>
*/
repeatY :
{
check : ["stretch", "repeat", "round"],
init : "stretch",
apply : "_applyBorderImage"
},
/**
* This property specifies how the images for the sides and the middle part
* of the border image are scaled and tiled.
*/
repeat :
{
group : ["repeatX", "repeatY"],
mode : "shorthand"
},
/**
* If set to <code>false</code>, the center image will be omitted and only
* the border will be drawn.
*/
fill :
{
check : "Boolean",
init : true,
apply : "_applyBorderImage"
},
/**
* Configures the border image mode. Supported values:
* <ul>
* <li>horizontal: left and right border images</li>
* <li>vertical: top and bottom border images</li>
* <li>grid: border images for all edges</li>
* </ul>
*/
borderImageMode :
{
check : ["horizontal", "vertical", "grid"],
init : "grid"
}
},
members :
{
/**
* Adds the border-image styles to the given map
* @param styles {Map} CSS style map
*/
_styleBorderImage : function(styles)
{
if (!this.getBorderImage()) {
return;
}
var resolvedImage = qx.util.AliasManager.getInstance().resolve(this.getBorderImage());
var source = qx.util.ResourceManager.getInstance().toUri(resolvedImage);
var computedSlices = this._getDefaultInsetsForBorderImage();
var slice = [
computedSlices.top,
computedSlices.right,
computedSlices.bottom,
computedSlices.left
];
var repeat = [
this.getRepeatX(),
this.getRepeatY()
].join(" ");
var fill = this.getFill() &&
qx.core.Environment.get("css.borderimage.standardsyntax") ? " fill" : "";
var styleName = qx.bom.Style.getPropertyName("borderImage");
if (styleName) {
var cssName = qx.bom.Style.getCssName(styleName);
styles[cssName] = 'url("' + source + '") ' + slice.join(" ") + fill + " " + repeat;
}
// Apply border styles even if we couldn't determine the borderImage property name
// (e.g. because the browser doesn't support it). This is needed to keep
// the layout intact.
styles["border-style"] = "solid";
styles["border-color"] = "transparent";
styles["border-width"] = slice.join("px ") + "px";
},
/**
* Computes the inset values based on the border image slices (defined in the
* decoration theme or computed from the fallback image sizes).
*
* @return {Map} Map with the top, right, bottom and left insets
*/
_getDefaultInsetsForBorderImage : function()
{
if (!this.getBorderImage()) {
return {
top: 0,
right: 0,
bottom: 0,
left: 0
};
}
var resolvedImage = qx.util.AliasManager.getInstance().resolve(this.getBorderImage());
var computedSlices = this.__getSlices(resolvedImage);
return {
top : this.getSliceTop() || computedSlices[0],
right: this.getSliceRight() || computedSlices[1],
bottom: this.getSliceBottom() || computedSlices[2],
left: this.getSliceLeft() || computedSlices[3]
};
},
_applyBorderImage : function()
{
if (qx.core.Environment.get("qx.debug"))
{
if (this._isInitialized()) {
throw new Error("This decorator is already in-use. Modification is not possible anymore!");
}
}
},
/**
* Gets the slice sizes from the fallback border images.
*
* @param baseImage {String} Resource Id of the base border image
* @return {Integer[]} Array with the top, right, bottom and left slice widths
*/
__getSlices : function(baseImage)
{
var mode = this.getBorderImageMode();
var topSlice = 0;
var rightSlice = 0;
var bottomSlice = 0;
var leftSlice = 0;
var split = /(.*)(\.[a-z]+)$/.exec(baseImage);
var prefix = split[1];
var ext = split[2];
var ResourceManager = qx.util.ResourceManager.getInstance();
if (mode == "grid" || mode == "vertical") {
topSlice = ResourceManager.getImageHeight(prefix + "-t" + ext);
bottomSlice = ResourceManager.getImageHeight(prefix + "-b" + ext);
}
if (mode == "grid" || mode == "horizontal") {
rightSlice = ResourceManager.getImageWidth(prefix + "-r" + ext);
leftSlice = ResourceManager.getImageWidth(prefix + "-l" + ext);
}
return [topSlice, rightSlice, bottomSlice, leftSlice];
}
}
});