+qx.Class.define("org.argeo.jcr.ria.views.XmlNodeEditor", {\r
+ extend : qx.ui.container.Composite,\r
+ implement : [org.argeo.ria.components.IView], \r
+\r
+ properties : {\r
+ /**\r
+ * The commands definition Map that will be automatically added and wired to the menubar and toolbar.\r
+ * See {@link org.argeo.ria.event.CommandsManager#definitions} for the keys to use for defining commands.\r
+ */\r
+ commands : {\r
+ init : {}\r
+ },\r
+ viewSelection : {\r
+ nullable:false, \r
+ check:"org.argeo.ria.components.ViewSelection"\r
+ },\r
+ instanceId : {\r
+ init:"XmlEditor",\r
+ event : "changeInstanceId"\r
+ },\r
+ instanceLabel : {\r
+ init:"Xml Editor",\r
+ event : "changeInstanceLabel"\r
+ },\r
+ dataModel : {\r
+ \r
+ }\r
+ },\r
+ \r
+ construct : function(){\r
+ this.base(arguments);\r
+ },\r
+ \r
+ members : {\r
+ /**\r
+ * The implementation should contain the GUI initialisation.\r
+ * This is the role of the manager to actually add the graphical component to the pane, \r
+ * so it's not necessary to do it here. \r
+ * @param viewPane {org.argeo.ria.components.ViewPane} The pane manager\r
+ * @param data {Mixed} Any object or data passed by the initiator of the view\r
+ * @return {Boolean}\r
+ */\r
+ init : function(viewPane, dataModel){\r
+ this.setViewSelection(new org.argeo.ria.components.ViewSelection(viewPane.getViewId())); \r
+ this.setLayout(new qx.ui.layout.VBox());\r
+ this.setDataModel(dataModel);\r
+ \r
+ this.input = new qx.ui.form.TextField();\r
+ this.add(this.input);\r
+ \r
+ this._attachInputToDM();\r
+ \r
+ this.htmlPane = new qx.ui.embed.Html();\r
+ this.htmlPane.setOverflow("auto", "auto");\r
+ this.add(this.htmlPane, {flex:1});\r
+ \r
+ },\r
+ /**\r
+ * The implementation should contain the real data loading (i.o. query...)\r
+ * @return {Boolean}\r
+ */\r
+ load : function(){\r
+ var dataModel = this.getDataModel();\r
+ dataModel.addListener("changeContextNode", function(event){\r
+ var xmlString = event.getData().toXmlString(true);\r
+ var TAG_START_PATTERN = new RegExp("<([0-9a-zA-Z\.]+)([^>]*)>", "gi");\r
+ var TAG_END_PATTERN = new RegExp("</([0-9a-zA-Z\.]+)>", "gi");\r
+ var TAG_CLOSE_PATTERN = new RegExp("(/?>)", "gi");\r
+ var TAG_ATTRIBUTE = new RegExp("\\s([0-9a-zA-Z:]+)\\=\"([^\"]*)\"", "gi");\r
+ // Not implemented yet\r
+ var TAG_COMMENT = new RegExp("(<!--.*-->)", "gi");\r
+ var TAG_CDATA_START = new RegExp("(\\<!\\[CDATA\\[).*", "gi");\r
+ var TAG_CDATA_END = new RegExp(".*(]]>)", "gi");\r
+ \r
+ xmlString = xmlString.replace(TAG_START_PATTERN, 'xml_div_begin<xml_tagname_begin$1xml_tagname_end$2>');\r
+ xmlString = xmlString.replace(TAG_END_PATTERN, '</xml_tagname_begin$1xml_tagname_end>xml_div_end');\r
+ xmlString = xmlString.replace(TAG_CLOSE_PATTERN, '>');\r
+ \r
+ xmlString = xmlString.replace(TAG_ATTRIBUTE, ' xml_attname_begin$1xml_attname_end="xml_attvalue_begin$2xml_attvalue_end"');\r
+ \r
+ //xmlString = qx.xml.String.escape(xmlString);\r
+ xmlString = xmlString.replace(new RegExp("(xml_div_begin)", "g"), '<div style="padding:1px;line-height:17px;padding-left:15px;">');\r
+ xmlString = xmlString.replace(new RegExp("(xml_div_end)", "g"), '</div>');\r
+ xmlString = xmlString.replace(new RegExp("(xml_tagname_begin)", "g"), '<b style="color:rgb(63,127,127);">');\r
+ xmlString = xmlString.replace(new RegExp("(xml_tagname_end)", "g"), '</b>');\r
+ xmlString = xmlString.replace(new RegExp("(xml_attname_begin)", "g"), '<b>');\r
+ xmlString = xmlString.replace(new RegExp("(xml_attname_end)", "g"), '</b>');\r
+ xmlString = xmlString.replace(new RegExp("(xml_attvalue_begin)", "g"), '<span style="color:rgb(0,0,255)">');\r
+ xmlString = xmlString.replace(new RegExp("(xml_attvalue_end)", "g"), '</span>');\r
+ xmlString = '<div style="margin-left:-10px;">' + xmlString + '</div>';\r
+ this.htmlPane.setHtml(xmlString);\r
+ /*\r
+ var call = new qx.util.DeferredCall(function(){\r
+ var htmlDom = this.htmlPane.getContentElement().getDomElement();\r
+ var spans = qx.bom.Selector.query("span", htmlDom);\r
+ for(var i=0;i<spans.length;i++){\r
+ var oThis = this;\r
+ spans[i].onclick = function(){oThis._setAttributesSpanEditable(this)};\r
+ }\r
+ }, this);\r
+ call.schedule();\r
+ */\r
+ }, this);\r
+ dataModel.requireContextChange(); \r
+ },\r
+ \r
+ _setAttributesSpanEditable : function(span){\r
+ var width = qx.bom.element.Dimension.getWidth(span);\r
+ var value = span.innerHTML;\r
+ qx.bom.element.Style.set(span, "display", "none");\r
+ var input = qx.bom.Element.create("input", {value:value, style:'width:'+width+'px;'});\r
+ qx.dom.Element.insertAfter(input, span); \r
+ },\r
+ \r
+ _attachInputToDM : function(){\r
+ var dm = this.getDataModel();\r
+ this.input.addListener("keypress", function(event){\r
+ if(event.getKeyIdentifier() != "Enter") return;\r
+ var path = this.input.getValue();\r
+ dm.requireContextChange(path);\r
+ }, this);\r
+ dm.addListener("changeContextNode", function(event){\r
+ var ctxtNode = event.getData();\r
+ this.input.setValue(ctxtNode.getPath());\r
+ }, this);\r
+ \r
+ },\r
+ \r
+ /**\r
+ * Whether this component is already contained in a scroller (return false) or not (return true).\r
+ * @return {Boolean}\r
+ */\r
+ addScroll : function(){\r
+ return false;\r
+ },\r
+ /**\r
+ * Called at destruction time\r
+ * Perform all the clean operations (stopping polling queries, etc.) \r
+ */\r
+ close : function(){\r
+ \r
+ } \r
+ }\r
+ \r
+ \r
+});
\ No newline at end of file