<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE bindings SYSTEM "chrome://status4evar/locale/prefs.dtd">

<!-- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
     If a copy of the MPL was not distributed with this file, 
     You can obtain one at http://mozilla.org/MPL/2.0/. -->

<bindings id="status4evar-prefs-bindings"
          xmlns="http://www.mozilla.org/xbl"
          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
          xmlns:xbl="http://www.mozilla.org/xbl">

	<binding id="css-bg-editor">
		<content sizetopopup="pref">
			<xul:vbox flex="1">
				<xul:deck anonid="css-bg-editor-deck" flex="1">
					<xul:vbox>
						<xul:hbox align="center">
							<xul:label xbl:inherits="disabled">&status4evar.editor.css.color.label;</xul:label>
							<xul:colorpicker anonid="css-bg-editor-color" type="button" onchange="this._editor._buildCSS();" xbl:inherits="disabled" />
						</xul:hbox>

						<xul:hbox align="center">
							<xul:label xbl:inherits="disabled">&status4evar.editor.css.image.label;</xul:label>
							<xul:textbox anonid="css-bg-editor-image" readonly="true" flex="1" xbl:inherits="disabled" />
							<xul:button anonid="css-bg-editor-image-browse" label="&status4evar.option.browse;" oncommand="this._editor._imageBrowse();" xbl:inherits="disabled" />
						</xul:hbox>
						<xul:hbox align="center" pack="end">
							<xul:button anonid="css-bg-editor-image-clear" label="&status4evar.option.clear;" oncommand="this._editor._imageClear();" xbl:inherits="disabled=no-image" />
						</xul:hbox>

						<xul:hbox>
							<xul:groupbox pack="center">
								<xul:caption label="" />
								<xul:hbox flex="1" align="center">
									<xul:label>X</xul:label>
								</xul:hbox>
								<xul:separator class="groove" orient="horizontal" />
								<xul:hbox flex="1" align="center">
									<xul:label>Y</xul:label>
								</xul:hbox>
							</xul:groupbox>

							<xul:groupbox>
								<xul:caption label="&status4evar.editor.css.image.repeat;" xbl:inherits="disabled=no-image" />
								<xul:menulist anonid="css-bg-editor-image-repeat-x" sizetopopup="always" onselect="this._editor._buildCSS();" xbl:inherits="disabled=no-image">
									<xul:menupopup>
										<xul:menuitem label="&status4evar.option.no-repeat;" value="no-repeat" />
										<xul:menuitem label="&status4evar.option.repeat;"    value="repeat" />
<!--
										<xul:menuitem label="&status4evar.option.space;"     value="space" />
										<xul:menuitem label="&status4evar.option.round;"     value="round" />
-->
									</xul:menupopup>
								</xul:menulist>
								<xul:separator class="groove" orient="horizontal" />
								<xul:menulist anonid="css-bg-editor-image-repeat-y" sizetopopup="always" onselect="this._editor._buildCSS();" xbl:inherits="disabled=no-image">
									<xul:menupopup>
										<xul:menuitem label="&status4evar.option.no-repeat;" value="no-repeat" />
										<xul:menuitem label="&status4evar.option.repeat;"    value="repeat" />
<!--
										<xul:menuitem label="&status4evar.option.space;"     value="space" />
										<xul:menuitem label="&status4evar.option.round;"     value="round" />
-->
									</xul:menupopup>
								</xul:menulist>
							</xul:groupbox>

							<xul:groupbox>
								<xul:caption label="&status4evar.editor.css.image.position;" xbl:inherits="disabled=no-image" />
								<xul:menulist anonid="css-bg-editor-image-position-x" sizetopopup="always" onselect="this._editor._updatePositionX();" xbl:inherits="disabled=no-image">
									<xul:menupopup>
											<xul:menuitem label="&status4evar.option.left;"   value="left" />
											<xul:menuitem label="&status4evar.option.center;" value="center" />
											<xul:menuitem label="&status4evar.option.right;"  value="right" />
											<xul:menuitem label="&status4evar.option.offset;" value="offset" />
									</xul:menupopup>
								</xul:menulist>
								<xul:separator class="groove" orient="horizontal" />
								<xul:menulist anonid="css-bg-editor-image-position-y" sizetopopup="always" onselect="this._editor._updatePositionY();" xbl:inherits="disabled=no-image">
									<xul:menupopup>
											<xul:menuitem label="&status4evar.option.top;"    value="top" />
											<xul:menuitem label="&status4evar.option.center;" value="center" />
											<xul:menuitem label="&status4evar.option.bottom;" value="bottom" />
											<xul:menuitem label="&status4evar.option.offset;" value="offset" />
									</xul:menupopup>
								</xul:menulist>
							</xul:groupbox>

							<xul:groupbox>
								<xul:caption label="&status4evar.editor.css.image.offset;" xbl:inherits="disabled=no-image" />
								<xul:hbox>
									<xul:textbox anonid="css-bg-editor-image-offset-x" type="number" size="4" min="-65535" onchange="this._editor._buildCSS();" />
									<xul:menulist anonid="css-bg-editor-image-offset-unit-x" sizetopopup="always" onselect="this._editor._buildCSS();">
										<xul:menupopup>
												<xul:menuitem label="%" value="%" />
												<xul:menuitem label="px" value="px" />
												<xul:menuitem label="em" value="em" />
												<xul:menuitem label="in" value="in" />
												<xul:menuitem label="cm" value="cm" />
												<xul:menuitem label="mm" value="mm" />
												<xul:menuitem label="pt" value="pt" />
												<xul:menuitem label="pc" value="pc" />
										</xul:menupopup>
									</xul:menulist>
								</xul:hbox>
								<xul:separator class="groove" orient="horizontal" />
								<xul:hbox>
									<xul:textbox anonid="css-bg-editor-image-offset-y" type="number" size="4" min="-65535" onchange="this._editor._buildCSS();" />
									<xul:menulist anonid="css-bg-editor-image-offset-unit-y" sizetopopup="always" onselect="this._editor._buildCSS();">
										<xul:menupopup>
												<xul:menuitem label="%" value="%" />
												<xul:menuitem label="px" value="px" />
												<xul:menuitem label="em" value="em" />
												<xul:menuitem label="in" value="in" />
												<xul:menuitem label="cm" value="cm" />
												<xul:menuitem label="mm" value="mm" />
												<xul:menuitem label="pt" value="pt" />
												<xul:menuitem label="pc" value="pc" />
										</xul:menupopup>
									</xul:menulist>
								</xul:hbox>
							</xul:groupbox>
						</xul:hbox>
					</xul:vbox>

					<xul:textbox anonid="css-bg-editor-css-text" multiline="true" rows="6" xbl:inherits="disabled" />
				</xul:deck>
			</xul:vbox>

			<xul:hbox align="center" pack="end">
				<children includes="progressmeter|toolbox" />
				<xul:label xbl:inherits="disabled">&status4evar.editor.label;</xul:label>
				<xul:menulist anonid="css-bg-editor-mode-menu" sizetopopup="always" onselect="this._editor._updateMode();" xbl:inherits="disabled">
					<xul:menupopup>
						<xul:menuitem label="&status4evar.option.simple;" />
						<xul:menuitem label="&status4evar.option.advanced;" />
					</xul:menupopup>
				</xul:menulist>
			</xul:hbox>
		</content>

		<implementation>
			<constructor><![CDATA[
				[
					"_editorColor",
					"_editorImageBrowse",
					"_editorImageClear",
					"_editorImageRepeatX",
					"_editorImageRepeatY",
					"_editorImagePositionX",
					"_editorImagePositionY",
					"_editorImageOffsetX",
					"_editorImageOffsetY",
					"_editorImageOffsetUnitX",
					"_editorImageOffsetUnitY",
					"_editorMode"
				].forEach(function(prop)
				{
					this[prop]._editor = this;
				}, this);

				this.setAdvanced(true, false);
			]]></constructor>

			<destructor><![CDATA[
			]]></destructor>

			<field name="_disableBuildCSS"><![CDATA[
				true
			]]></field>

			<field name="_editorColor" readonly="true"><![CDATA[
				document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-color");
			]]></field>

			<field name="_editorCSS" readonly="true"><![CDATA[
				document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-css-text");
			]]></field>

			<field name="_editorDeck" readonly="true"><![CDATA[
				document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-deck");
			]]></field>

			<field name="_editorImage" readonly="true"><![CDATA[
				document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image");
			]]></field>

			<field name="_editorImageBrowse" readonly="true"><![CDATA[
				document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-browse");
			]]></field>

			<field name="_editorImageClear" readonly="true"><![CDATA[
				document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-clear");
			]]></field>

			<field name="_editorImageRepeatX" readonly="true"><![CDATA[
				document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-repeat-x");
			]]></field>

			<field name="_editorImageRepeatY" readonly="true"><![CDATA[
				document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-repeat-y");
			]]></field>

			<field name="_editorImagePositionX" readonly="true"><![CDATA[
				document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-position-x");
			]]></field>

			<field name="_editorImagePositionY" readonly="true"><![CDATA[
				document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-position-y");
			]]></field>

			<field name="_editorImageOffsetX" readonly="true"><![CDATA[
				document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-offset-x");
			]]></field>

			<field name="_editorImageOffsetY" readonly="true"><![CDATA[
				document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-offset-y");
			]]></field>

			<field name="_editorImageOffsetUnitX" readonly="true"><![CDATA[
				document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-offset-unit-x");
			]]></field>

			<field name="_editorImageOffsetUnitY" readonly="true"><![CDATA[
				document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-image-offset-unit-y");
			]]></field>

			<field name="_editorMode" readonly="true"><![CDATA[
				document.getAnonymousElementByAttribute(this, "anonid", "css-bg-editor-mode-menu");
			]]></field>

			<field name="_initialized"><![CDATA[
				false
			]]></field>

			<field name="_reRGB" readonly="true"><![CDATA[
				/^rgb\((\d+), (\d+), (\d+)\)$/
			]]></field>

			<field name="_reURL" readonly="true"><![CDATA[
				/^url\(\s*['"]?(.+?)['"]?\s*\)$/
			]]></field>

			<field name="_reBgPosition" readonly="true"><![CDATA[
				/^(left|center|right)? ?(-?\d+[^\s\d]+)? ?(top|center|bottom)? ?(-?\d+[^\s\d]+)?$/
			]]></field>

			<field name="_reCSSUnit" readonly="true"><![CDATA[
				/^(-?\d+)([^\s\d]+)$/
			]]></field>

			<field name="_strings" readonly="true"><![CDATA[
				document.getElementById("bundle_status4evar");
			]]></field>

			<property name="value">
				<getter><![CDATA[
					return this._editorCSS.value;
				]]></getter>
				<setter><![CDATA[
					this._editorCSS.value = val;

					if(!this._initialized)
					{
						this.setAdvanced(false, false);
						this._initialized = true;
					}

					return val;
				]]></setter>
			</property>

			<property name="disabled">
				<getter><![CDATA[
					return this.getAttribute("disabled") == "true";
				]]></getter>
				<setter><![CDATA[
					if(val)
					{ 
						this.setAttribute("disabled", "true");
					}
					else
					{
						this.removeAttribute("disabled");
					}

					this._updateImageControllDisable();

					return val;
				]]></setter>
			</property>

			<method name="setAdvanced">
				<parameter name="aVal"/>
				<parameter name="aPrompt"/>
				<body><![CDATA[
					if(!aVal)
					{
						let success = this._parseCSS();
						if(!success)
						{
							let result = aPrompt && Services.prompt.confirm(window,
							                                                this._strings.getString("simpleEditorTitle"),
							                                                this._strings.getString("simpleEditorMessage"));
							if(result)
							{	// Continue to simple mode
								this._buildCSS();
							}
							else
							{	// Stay on advanced mode
								aVal = true;
							}
						}
					}

					this._disableBuildCSS = aVal;
					this._editorDeck.selectedIndex = ((aVal) ? 1 : 0);
					this._editorMode.selectedIndex = ((aVal) ? 1 : 0);
				]]></body>
			</method>

			<method name="_buildCSS">
				<body><![CDATA[
					if(this._disableBuildCSS)
					{
						return;
					}

					let cssVal = this._editorColor.color;
					let imgVal = this._editorImage.value;
					if(imgVal)
					{
						cssVal += " url(\"" + imgVal + "\")";

						//
						// Print the background repeat
						//
						let bgRX = this._editorImageRepeatX.value;
						let bgRY = this._editorImageRepeatY.value;
						if(bgRX == "repeat" && bgRY == "no-repeat")
						{
							cssVal += " repeat-x";
						}
						else if(bgRX == "no-repeat" && bgRY == "repeat")
						{
							cssVal += " repeat-y";
						}
						else
						{
							cssVal += " " + bgRX;
							if(bgRX != bgRY)
							{
								cssVal += " " + bgRY;
							}
						}

						//
						// Print the background position
						//
						let bgPX = this._editorImagePositionX.value;
						let bgPOX = this._editorImageOffsetX.value;
						if(bgPX != "offset")
						{
							cssVal += " " + bgPX;
						}
						else
						{
							cssVal += " " + bgPOX + this._editorImageOffsetUnitX.value;
						}

						let bgPY = this._editorImagePositionY.value;
						let bgPOY = this._editorImageOffsetY.value;
						if(bgPY != "offset")
						{
							cssVal += " " + bgPY;
						}
						else
						{
							cssVal += " " + bgPOY + this._editorImageOffsetUnitY.value;
						}
					}

					this._editorCSS.value = cssVal;

					let event = document.createEvent("Event");
					event.initEvent("change", true, true);
					this._editorCSS.dispatchEvent(event);
				]]></body>
			</method>

			<method name="_parseCSS">
				<body><![CDATA[
					let retVal = true;

					let cssParser = document.createElement("div");
					cssParser.style.background = this._editorCSS.value;
					if(!cssParser.style.background)
					{
						Components.utils.reportError("Error parsing background CSS rule: " + this._editorCSS.value);
						cssParser.style.background = "#33FF33";
						retVal = false;
					}

					//
					// Parse the background color
					//
					let bgC = cssParser.style.backgroundColor;
					if(this._reRGB.test(bgC))
					{
						let digits = this._reRGB.exec(bgC);

						let red = parseInt(digits[1]);
						let green = parseInt(digits[2]);
						let blue = parseInt(digits[3]);

						let rgb = blue | (green << 8) | (red << 16);
						bgC =  "#" + rgb.toString(16);
					}
					else
					{
						Components.utils.reportError("Error parsing background-color value: " + bgC);
						bgC = "#33FF33";
						retVal = false;
					}

					//
					// Parse the background image
					//
					let bgI = cssParser.style.backgroundImage;
					if(bgI != "none" && !this._reURL.test(bgI))
					{
						Components.utils.reportError("Error parsing background-image value: " + bgI);
						bgI = "none";
						retVal = false;
					}
					bgI = ((bgI != "none") ? this._reURL.exec(bgI)[1].trim() : "");

					//
					// Parse the background repeat
					//
					let bgR = cssParser.style.backgroundRepeat.split(" ");
					let bgRX = bgR[0];
					if(bgRX == "repeat-x")
					{
						bgRX = "repeat";
					}
					else if(bgRX == "repeat-y")
					{
						bgRX = "no-repeat";
					}

					let bgRY = bgR[bgR.length - 1];
					if(bgRY == "repeat-x")
					{
						bgRY = "no-repeat";
					}
					else if(bgRY == "repeat-y")
					{
						bgRY = "repeat";
					}

					//
					// Parse the background position
					//
					let bgP = cssParser.style.backgroundPosition;
					let bgPParts = this._reBgPosition.exec(bgP);
					let bgPValues = new Array();
					for(let i = 1; i <= 4; i++)
					{
						if(bgPParts[i])
						{
							bgPValues.push({
								"value": bgPParts[i],
								"group": i
							});
						}
					}

					if(bgPValues.length == 1)
					{
						bgPValues.splice(((bgPValues[0].group == 2) ? 0 : 1), 0, {
							"value": "center",
							"group": ((bgPValues[0].group == 2) ? 0 : 2)
						});
					}

					if(bgPValues.length == 2 && bgPValues[1].group == 2)
					{
						bgPValues[1].group = 4;
					}

					for(let i = 0; i < 4; i++)
					{
						let group = (i + 1);
						if(bgPValues[i] != undefined && bgPValues[i].group == group)
						{
							continue;
						}

						let tmp = "0px";
						switch(i)
						{
							case 0:
								tmp = "offset";
								break;
							case 2:
								tmp = "offset";
								break;
						}

						bgPValues.splice(i, 0, {
							"value": tmp,
							"group": group
						});
					}

					let bgPOXParts = this._reCSSUnit.exec(bgPValues[1].value);
					let bgPOYParts = this._reCSSUnit.exec(bgPValues[3].value);

					//
					// Parse the background size
					//

					//
					// Initialize the UI
					//
					let disableBuildCSS = this._disableBuildCSS;
					this._disableBuildCSS = true;

					this._editorColor.color = bgC;
					this._editorImage.value = bgI;
					this._editorImageOffsetX.value = bgPOXParts[1];
					this._editorImageOffsetY.value = bgPOYParts[1];

					[
						[this._editorImageRepeatX,	bgRX,			"repeat",	"repeat X"],
						[this._editorImageRepeatY,	bgRY,			"repeat",	"repeat Y"],
						[this._editorImagePositionX,	bgPValues[0].value,	"left",		"position X"],
						[this._editorImagePositionY,	bgPValues[2].value,	"top",		"position Y"],
						[this._editorImageOffsetUnitX,	bgPOXParts[2],		"px",		"offset X unit"],
						[this._editorImageOffsetUnitY,	bgPOYParts[2],		"px",		"offset Y unit"]
					].forEach(function(info)
					{
						if(!this._setSelectedItemSafe(info[0], info[1], info[2]))
						{
							Components.utils.reportError("Error setting " + info[3] + " to " + info[1]);
							retVal = false;
						}
					}, this);

					this._updateImageControllDisable();

					this._disableBuildCSS = disableBuildCSS;

					return retVal;
				]]></body>
			</method>

			<method name="_imageBrowse">
				<body><![CDATA[
					let nsIFilePicker = Components.interfaces.nsIFilePicker;
					let filePicker = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
					filePicker.init(window, this._strings.getString("imageSelectTitle"), nsIFilePicker.modeOpen);
					filePicker.appendFilters(nsIFilePicker.filterImages);

					let res = filePicker.show();
					if(res == nsIFilePicker.returnOK)
					{
						this._editorImage.value =  Services.io.newFileURI(filePicker.file).spec;
						this._updateImageControllDisable();
						this._buildCSS();
					}
				]]></body>
			</method>

			<method name="_imageClear">
				<body><![CDATA[
					this._editorImage.value =  "";
					this._editorImageRepeatX.value = "repeat";
					this._editorImageRepeatY.value = "repeat";
					this._editorImagePositionX.value = "left";
					this._editorImagePositionY.value = "top";
					this._editorImageOffsetX.value = 0;
					this._editorImageOffsetY.value = 0;
					this._editorImageOffsetUnitX.value = "px";
					this._editorImageOffsetUnitY.value = "px";
					this._updateImageControllDisable();
					this._buildCSS();
				]]></body>
			</method>

			<method name="_processEvent">
				<parameter name="event"/>
				<body><![CDATA[
					if(!("css-bg-editor-css-text" == event.originalTarget.getAttribute("anonid")
					|| "css-bg-editor-css-text" == document.getBindingParent(event.originalTarget).getAttribute("anonid")))
					{
						event.stopPropagation();
					}

					//Components.utils.reportError("Editor event " + event.type + " on " + event.originalTarget.tagName + "::" + event.originalTarget.getAttribute("anonid"));
				]]></body>
			</method>

			<method name="_setSelectedItemSafe">
				<parameter name="aElement"/>
				<parameter name="aValue"/>
				<parameter name="aDefault"/>
				<body><![CDATA[
					aElement.value = aValue;
					if(!aElement.selectedItem || aElement.selectedItem.value != aValue)
					{
						aElement.value = aDefault;
						return false;
					}
					return true;
				]]></body>
			</method>

			<method name="_updateImageControllDisable">
				<body><![CDATA[
					if(this.disabled || !this._editorImage.value)
					{
						this.setAttribute("no-image", "true");
						this._updatePositionOffsetXDisabled(true);
						this._updatePositionOffsetYDisabled(true);
					}
					else
					{
						this.removeAttribute("no-image");
						this._updatePositionOffsetXDisabled(false);
						this._updatePositionOffsetYDisabled(false);
					}
				]]></body>
			</method>

			<method name="_updateMode">
				<body><![CDATA[
					if(this._editorMode.selectedIndex == this._editorDeck.selectedIndex)
					{
						return;
					}

					this.setAdvanced(((this._editorMode.selectedIndex == 1) ? true : false), true);
				]]></body>
			</method>

			<method name="_updatePositionOffsetXDisabled">
				<parameter name="aVal"/>
				<body><![CDATA[
					let bgPX = this._editorImagePositionX.value;
					let disableOffsetX = aVal || (bgPX != "offset");// || bgPX == "center");
					this._editorImageOffsetX.disabled = disableOffsetX;
					this._editorImageOffsetUnitX.disabled = disableOffsetX;
				]]></body>
			</method>

			<method name="_updatePositionOffsetYDisabled">
				<parameter name="aVal"/>
				<body><![CDATA[
					let bgPY = this._editorImagePositionY.value;
					var disableOffsetY = aVal || (bgPY != "offset");// || bgPY == "center");
					this._editorImageOffsetY.disabled = disableOffsetY;
					this._editorImageOffsetUnitY.disabled = disableOffsetY;
				]]></body>
			</method>

			<method name="_updatePositionX">
				<body><![CDATA[
					this._updatePositionOffsetXDisabled(false);
					this._buildCSS();
				]]></body>
			</method>

			<method name="_updatePositionY">
				<body><![CDATA[
					this._updatePositionOffsetYDisabled(false);
					this._buildCSS();
				]]></body>
			</method>
		</implementation>

		<handlers>
			<handler event="command"><![CDATA[
				this._processEvent(event);
			]]></handler>

			<handler event="change"><![CDATA[
				this._processEvent(event);
			]]></handler>

			<handler event="input"><![CDATA[
				this._processEvent(event);
			]]></handler>

			<handler event="select"><![CDATA[
				this._processEvent(event);
			]]></handler>
		</handlers>
	</binding>
</bindings>

