public static void editXPath(Word.ContentControl cc) { Word.Document document = Globals.ThisAddIn.Application.ActiveDocument; // First, work out whether this is a condition or a repeat or a plain bind bool isCondition = false; bool isRepeat = false; bool isBind = false; if ( (cc.Title!=null && cc.Title.StartsWith("Condition") ) || (cc.Tag!=null && cc.Tag.Contains("od:condition") )) { isCondition = true; } else if ( (cc.Title!=null && cc.Title.StartsWith("Repeat")) || (cc.Tag!=null && cc.Tag.Contains("od:repeat") )) { isRepeat = true; } else if ((cc.Title != null && cc.Title.StartsWith("Data")) || (cc.Tag != null && cc.Tag.Contains("od:xpath")) || cc.XMLMapping.IsMapped ) { isBind = true; } else { // Ask user using (Forms.ConditionOrRepeat cor = new Forms.ConditionOrRepeat()) { if (cor.ShowDialog() == DialogResult.OK) { isCondition = cor.radioButtonCondition.Checked; isRepeat = cor.radioButtonRepeat.Checked; isBind = cor.radioButtonBind.Checked; } else { // They cancelled return; } } } // OK, now we know whether its a condition or a repeat or a bind // Is it already mapped to something? TagData td = new TagData(cc.Tag); Model model = Model.ModelFactory(document); string strXPath = ""; // In order to get Id and prefix mappings for current part CustomTaskPane ctpPaneForThisWindow = Utilities.FindTaskPaneForCurrentWindow(); Controls.ControlMain ccm = (Controls.ControlMain)ctpPaneForThisWindow.Control; string cxpId = ccm.CurrentPart.Id; string prefixMappings = ""; // TODO GetPrefixMappings(ccm.CurrentPart.NamespaceManager); log.Debug("default prefixMappings: " + prefixMappings); XPathsPartEntry xppe = null; ConditionsPartEntry cpe = null; if (isCondition && td.get("od:condition") != null) { string conditionId = td.get("od:condition"); cpe = new ConditionsPartEntry(model); condition c = cpe.getConditionByID(conditionId); string xpathid = null; if (c!=null && c.Item is xpathref) { xpathref ex = (xpathref)c.Item; xpathid = ex.id; // Now fetch the XPath xppe = new XPathsPartEntry(model); xpathsXpath xx = xppe.getXPathByID(xpathid); if (xx != null) { strXPath = xx.dataBinding.xpath; cxpId = xx.dataBinding.storeItemID; prefixMappings = xx.dataBinding.prefixMappings; } } } else if (isRepeat && td.get("od:repeat") != null) { string repeatId = td.get("od:repeat"); // Now fetch the XPath xppe = new XPathsPartEntry(model); xpathsXpath xx = xppe.getXPathByID(repeatId); if (xx != null) { strXPath = xx.dataBinding.xpath; cxpId = xx.dataBinding.storeItemID; prefixMappings = xx.dataBinding.prefixMappings; } } else if (isBind) { if (cc.XMLMapping.IsMapped) { // Prefer this, if for some reason it contradicts od:xpath strXPath = cc.XMLMapping.XPath; cxpId = cc.XMLMapping.CustomXMLPart.Id; prefixMappings = cc.XMLMapping.PrefixMappings; } else if( td.get("od:xpath") != null) { string xpathId = td.get("od:xpath"); // Now fetch the XPath xppe = new XPathsPartEntry(model); xpathsXpath xx = xppe.getXPathByID(xpathId); if (xx != null) { strXPath = xx.dataBinding.xpath; cxpId = xx.dataBinding.storeItemID; prefixMappings = xx.dataBinding.prefixMappings; } } } // Now we can present the form using (Forms.XPathEditor xpe = new Forms.XPathEditor()) { xpe.textBox1.Text = strXPath; if (xpe.ShowDialog() == DialogResult.OK) { strXPath = xpe.textBox1.Text; } else { // They cancelled return; } } // Now give effect to it td = new TagData(""); if (isCondition) { // Create the new condition. Doesn't attempt to delete // the old one (if any) if (cpe == null) { cpe = new ConditionsPartEntry(model); } cpe.setup(cxpId, strXPath, prefixMappings, true); cpe.save(); cc.Title = "Conditional: " + cpe.conditionId; // Write tag td.set("od:condition", cpe.conditionId); cc.Tag = td.asQueryString(); } else if (isRepeat) { // Create the new repeat. Doesn't attempt to delete // the old one (if any) if (xppe == null) { xppe = new XPathsPartEntry(model); } xppe.setup("rpt", cxpId, strXPath, prefixMappings, false); xppe.save(); cc.Title = "Repeat: " + xppe.xpathId; // Write tag td.set("od:repeat", xppe.xpathId); cc.Tag = td.asQueryString(); } else if (isBind) { // Create the new bind. Doesn't attempt to delete // the old one (if any) if (xppe == null) { xppe = new XPathsPartEntry(model); } Word.XMLMapping bind = cc.XMLMapping; bool mappable = bind.SetMapping(strXPath, prefixMappings, CustomXmlUtilities.getPartById(document, cxpId) ); if (mappable) { // What does the XPath point to? string val = cc.XMLMapping.CustomXMLNode.Text; cc.Title = "Data value: " + xppe.xpathId; if (ContentDetection.IsBase64Encoded(val)) { // Force picture content control ... // cc.Type = Word.WdContentControlType.wdContentControlPicture; // from wdContentControlText (or wdContentControlRichText for that matter) // doesn't work (you get "inappropriate range for applying this // content control type"). cc.Delete(true); // Now add a new cc object missing = System.Type.Missing; Globals.ThisAddIn.Application.Selection.Collapse(ref missing); cc = document.ContentControls.Add( Word.WdContentControlType.wdContentControlPicture, ref missing); cc.XMLMapping.SetMapping(strXPath, prefixMappings, CustomXmlUtilities.getPartById(document, cxpId)); } else if (ContentDetection.IsXHTMLContent(val) ) { td.set("od:ContentType", "application/xhtml+xml"); cc.Tag = td.asQueryString(); cc.XMLMapping.Delete(); cc.Type = Word.WdContentControlType.wdContentControlRichText; cc.Title = "XHTML: " + xppe.xpathId; if (Inline2Block.containsBlockLevelContent(val)) { Inline2Block i2b = new Inline2Block(); cc = i2b.convertToBlockLevel(cc, true); if (cc == null) { MessageBox.Show("Problems inserting block level XHTML at this location."); return; } } } xppe.setup(null, cxpId, strXPath, prefixMappings, true); xppe.save(); td.set("od:xpath", xppe.xpathId); cc.Tag = td.asQueryString(); } else { xppe.setup(null, cxpId, strXPath, prefixMappings, true); xppe.save(); td.set("od:xpath", xppe.xpathId); cc.Title = "Data value: " + xppe.xpathId; cc.Tag = td.asQueryString(); log.Warn(" XPath \n\r " + strXPath + "\n\r does not return an element. The OpenDoPE pre-processor will attempt to evaluate it, but Word will never update the result. "); bind.Delete(); MessageBox.Show(" XPath \n\r " + strXPath + "\n\r does not return an element. Check this is what you want? "); } } }
private void buttonOK_Click(object sender, EventArgs e) { // First, check validity // .. controlQuestionCommon1 if (!controlQuestionCommon1.isValid()) { if (!this.controlQuestionCommon1.isValid()) { Mbox.ShowSimpleMsgBoxError("You need to enter the text of the question!"); DialogResult = DialogResult.None; // or use on closing event; see http://stackoverflow.com/questions/2499644/preventing-a-dialog-from-closing-in-the-buttons-click-event-handler return; } } // .. controlQuestionVaryWhichRepeat1 // TODO? // .. responses if (q.response.Item is responseFixed) { if (!this.controlQuestionResponsesFixed1.isValid()) { DialogResult = DialogResult.None; return; } } else { if (!this.controlDataTypeMAIN1.controlDataType1.isValid()) // TODO implement { Mbox.ShowSimpleMsgBoxError("Data invalid"); DialogResult = DialogResult.None; return; } } // OK, write changes string questionTextOriginal = q.text; controlQuestionCommon1.populateQuestion(q); Office.CustomXMLNode node = answersPart.SelectSingleNode(xpathObj.dataBinding.xpath); bool dataTypeDateChange = false; if (q.response.Item is responseFixed) { this.controlQuestionResponsesFixed1.updateQuestionFromForm(xpathObj, q, node); // If a response value was changed, need to check condition integrity // TODO } else { string typeExisting = xpathObj.type; this.controlDataTypeMAIN1.controlDataType1.updateQuestionFromForm(xpathObj, q, node); dataTypeDateChange = !(typeExisting.Equals(xpathObj.type)); } // Save changes // .. questionsPart string result = questionnaire.Serialize(); log.Info(result); CustomXmlUtilities.replaceXmlDoc(questionsPart, result); // .. xpaths xppe.save(); if (!q.text.Equals(questionTextOriginal) || dataTypeDateChange) { // If we changed the question text, need to update this in CC titles ConditionsPartEntry cpe = new ConditionsPartEntry(model); foreach (Word.ContentControl ccx in Globals.ThisAddIn.Application.ActiveDocument.ContentControls) { if (ccx.Tag.Contains("od:xpath")) { string thisID = (new TagData(ccx.Tag)).getXPathID(); if (thisID.Equals(xpathObj.id)) { // Update CC title ccx.Title = q.text; if (dataTypeDateChange) { if (xpathObj.type.Equals("date")) { // it is now a date ccx.Type = Word.WdContentControlType.wdContentControlDate; log.Info("converted plain text cc to date"); } else { // no longer a date ccx.Type = Word.WdContentControlType.wdContentControlText; log.Info("converted date cc to plain text"); } } } } else if (ccx.Tag.Contains("od:condition")) { string thisID = (new TagData(ccx.Tag)).getConditionID(); condition c = cpe.getConditionByID(thisID); if (ConditionHelper.doesConditionUseQuestion(xppe, cpe.conditions, c, q.id)) { log.Info("condition uses question " + q.id); // Update CC title // TODO } } } } // Vary with which? if (this.controlQuestionVaryWhichRepeat1.changed()) { this.controlQuestionVaryWhichRepeat1.moveIfNecessary(q.id, xpathObj, answersPart); } }
public void buttonConditionEdit_Click(Office.IRibbonControl control) { FabDocxState fabDocxState = getState(); if (currentCC.Tag != null) { String conditionID = (new TagData(currentCC.Tag)).getConditionID(); if (conditionID != null) { ConditionsPartEntry cpe = new ConditionsPartEntry(fabDocxState.model); condition c = cpe.getConditionByID(conditionID); FormCondition formCondition = new FormCondition(currentCC, cpe, c); formCondition.ShowDialog(); formCondition.Dispose(); } } if (fabDocxState.TaskPane.Visible) { Controls.LogicTaskPaneUserControl ltp = (Controls.LogicTaskPaneUserControl)fabDocxState.TaskPane.Control; ltp.populateLogicInUse(); } }