public static T GetCustomXmlByTagName <T>(Excel.Workbook workbook, string tagName) where T : class { if (null == workbook) { throw new ArgumentNullException("workbook"); } if (string.IsNullOrWhiteSpace(tagName)) { throw new ArgumentNullException("tagName"); } foreach (Office.CustomXMLPart part in workbook.CustomXMLParts) { if (part.DocumentElement.BaseName == tagName) { Office.CustomXMLNode node = part.DocumentElement.FirstChild; string json = node.NodeValue.Trim(); return(JsonConvert.DeserializeObject <T>(json)); } } return(default(T)); }
/// <summary> /// Refresh the property grid. /// </summary> /// <param name="cxn">A CustomXMLNode specifying the node whose properties we want to use.</param> internal void RefreshProperties(Office.CustomXMLNode cxn) { listViewProperties.Items.Clear(); if (cxn != null) { //refresh properties if (show("NodeProperties.Show.Namespace")) { listViewProperties.Items.Add(new ListViewItem(new string[] { Properties.Resources.Namespace, cxn.NamespaceURI })); } if (show("NodeProperties.Show.Type")) { listViewProperties.Items.Add(new ListViewItem(new string[] { Properties.Resources.Type, cxn.NodeType.ToString() })); } if (show("NodeProperties.Show.XPath")) { listViewProperties.Items.Add(new ListViewItem(new string[] { Properties.Resources.XPath, cxn.XPath })); } if (show("NodeProperties.Show.Prefixes")) { listViewProperties.Items.Add(new ListViewItem(new string[] { Properties.Resources.Prefixes, Utilities.GetPrefixMappingsMxn(cxn) })); } if (show("NodeProperties.Show.XML")) { listViewProperties.Items.Add(new ListViewItem(new string[] { Properties.Resources.XML, cxn.XML })); } } }
public static void replaceXmlDoc(Office.CustomXMLPart cxp, String newContent) { /* Office.CustomXMLNode node = cxp.SelectSingleNode("/"); * // gives you #document, * // but you can't get the root node from it? * * //node = cxp.SelectSingleNode("/mypart"); */ Office.CustomXMLNode node = cxp.SelectSingleNode("/node()"); //log.Debug(node.XML); //log.Debug(node.XPath); Office.CustomXMLNode parent = node.ParentNode; log.Debug(parent.BaseName); //parent.ReplaceChildNode(node, "mynewnode", "", Office.MsoCustomXMLNodeType.msoCustomXMLNodeElement, ""); parent.ReplaceChildSubtree(newContent, node); //parent.RemoveChild(node); //doesn't work //parent.AppendChildSubtree("<mynewpart><blagh/></mynewpart>"); node = cxp.SelectSingleNode("/"); log.Debug(node.XML); }
public void AddXMLNode(Office.CustomXMLPart TreeviewXMLPart, string id, string wordcount, string pgcount, string text, string bookmark, System.Windows.Media.Color CardColor)// this adds a node for the card in the custom XML file { string color = CardColor.R.ToString() + "," + CardColor.G.ToString() + "," + CardColor.B.ToString(); Office.CustomXMLNode node = TreeviewXMLPart.SelectSingleNode("//cardList[1]");//[@xmlns=CARDS] Office.CustomXMLNode childNode; if (node == null) { MessageBox.Show("Node = null"); } try { node.AppendChildNode("node", "", Office.MsoCustomXMLNodeType.msoCustomXMLNodeElement, text); childNode = node.LastChild; childNode.AppendChildNode("id", "", Office.MsoCustomXMLNodeType.msoCustomXMLNodeAttribute, id); childNode.AppendChildNode("words", "", Office.MsoCustomXMLNodeType.msoCustomXMLNodeAttribute, wordcount); childNode.AppendChildNode("Pages", "", Office.MsoCustomXMLNodeType.msoCustomXMLNodeAttribute, pgcount); childNode.AppendChildNode("bookmark", "", Office.MsoCustomXMLNodeType.msoCustomXMLNodeAttribute, bookmark); childNode.AppendChildNode("color", "", Office.MsoCustomXMLNodeType.msoCustomXMLNodeAttribute, color); } catch { MessageBox.Show("problem: " + TreeviewXMLPart.DocumentElement.XML + "\n---------\n" + TreeviewXMLPart.XML); } }
public static string ReadCustomXmlNode(Excel.Workbook workbook, string xNameSpace, string xPath) { Office.CustomXMLNode node = GetCustomXmlNode(workbook, xNameSpace, xPath); if (node != null) { return(node.XML); } return(string.Empty); }
public static string getAttribute(Office.CustomXMLNode node, string attributeName) { foreach (Office.CustomXMLNode attr in node.Attributes) { if (attr.BaseName.Equals(attributeName)) { return(attr.NodeValue); } } return(null); }
public static void UpdateCustomXmlNode(Excel.Workbook workbook, string namespaceName, string xmlString, string xPath) { Office.CustomXMLParts ps = workbook.CustomXMLParts.SelectByNamespace(namespaceName); foreach (Office.CustomXMLPart p in ps) { var nsmgr = p.NamespaceManager; nsmgr.AddNamespace("x", namespaceName); Office.CustomXMLNode oldNode = p.SelectSingleNode(xPath); oldNode.ParentNode.ReplaceChildSubtree(xmlString, oldNode); } }
/// <summary> /// Get the prefix mappings needed to evaluate the XPath to a specific custom XML node. /// </summary> /// <param name="cxn">The corresponding CustomXMLNode.</param> /// <returns>A string specifying the prefix mapping list.</returns> internal static string GetPrefixMappingsMxn(Office.CustomXMLNode cxn) { string s = ""; foreach (Office.CustomXMLPrefixMapping cxpm in cxn.OwnerPart.NamespaceManager) { //get the string if (!String.IsNullOrEmpty(cxpm.Prefix) && cxpm.Prefix != "xml" && cxpm.Prefix != "xmlns") { s += "xmlns:" + cxpm.Prefix + "='" + cxpm.NamespaceURI + "' "; } } return(s); }
// get DAX query from XML Data based on active rngCell public string GetCustomTableQuery(Excel.Range rngCell) { Excel.Worksheet sheet = (Excel.Worksheet)rngCell.Parent; Excel.Workbook workbook = (Excel.Workbook)sheet.Parent; TabularItems.Measure measure = GetMeasure(rngCell); #region measure // get referenced measure Office.CustomXMLNode node = ExcelHelper.GetCustomXmlNode(workbook, Constants.DaxDrillXmlSchemaSpace, string.Format("{0}[@id='{1}']", Constants.MeasureXpath, measure.Name)); string measureName = measure.Name; if (node != null) { foreach (Office.CustomXMLNode attr in node.Attributes) { if (attr.BaseName == "ref") { // get DAX query by measure id node = ExcelHelper.GetCustomXmlNode(workbook, Constants.DaxDrillXmlSchemaSpace, string.Format("{0}[@id='{1}']/x:query", Constants.MeasureXpath, attr.Text)); break; } } } #endregion #region table // get DAX query by table id (if measure not found in XML metadata) if (node == null) { node = ExcelHelper.GetCustomXmlNode(workbook, Constants.DaxDrillXmlSchemaSpace, string.Format("{0}[@id='{1}']/x:query", Constants.TableXpath, measure.TableName)); } #endregion if (node != null) { return(node.Text); } return(string.Empty); }
/// <summary> /// Create an XmlNode for a CustomXMLNode. /// </summary> /// <param name="mxnNewNode">The CustomXMLNode to convert.</param> /// <param name="xdoc">The XmlDocument for the corresponding XmlNode.</param> /// <returns>The newly created XmlNode.</returns> internal static XmlNode XnBuildFromMxn(Office.CustomXMLNode mxnNewNode, XmlDocument xdoc) { XmlNode xn = null; switch (mxnNewNode.NodeType) { case Office.MsoCustomXMLNodeType.msoCustomXMLNodeElement: //create a new temp XML document XmlDocument xdocElement = new XmlDocument(); xdocElement.LoadXml(mxnNewNode.XML); //import the element back into the main DOM xn = xdoc.ImportNode(xdocElement.DocumentElement, true); //clean up xdocElement = null; break; case Office.MsoCustomXMLNodeType.msoCustomXMLNodeAttribute: char[] cSplitter = { '=' }; string[] strAttribute = mxnNewNode.XML.Split(cSplitter); xn = xdoc.CreateAttribute(strAttribute[0], mxnNewNode.NamespaceURI); xn.InnerText = mxnNewNode.NodeValue; break; case Office.MsoCustomXMLNodeType.msoCustomXMLNodeText: xn = xdoc.CreateTextNode(mxnNewNode.Text); break; case Office.MsoCustomXMLNodeType.msoCustomXMLNodeProcessingInstruction: xn = xdoc.CreateProcessingInstruction(mxnNewNode.BaseName, mxnNewNode.Text); break; case Office.MsoCustomXMLNodeType.msoCustomXMLNodeCData: xn = xdoc.CreateCDataSection(mxnNewNode.Text); break; case Office.MsoCustomXMLNodeType.msoCustomXMLNodeComment: xn = xdoc.CreateComment(mxnNewNode.Text); break; } return(xn); }
/// <summary> /// Get an XmlNode in the local XML tree from the corresponding CustomXMLNode. /// </summary> /// <param name="xdoc">The XmlDocument for the local XML tree.</param> /// <param name="mxn">The CustomXMLNode to convert.</param> /// <param name="mxnNew">A new CustomXMLNode that's not in the local tree, and therefore should be ignored when trying to find the XmlNode.</param> /// <returns>The corresponding XmlNode.</returns> internal static XmlNode XnFromMxn(XmlDocument xdoc, Office.CustomXMLNode mxn, Office.CustomXMLNode mxnNew) { NameTable nt = new NameTable(); XmlNamespaceManager xmlnsMgr = new XmlNamespaceManager(nt); string strXPath = string.Empty; XmlNode xn = null; strXPath = XpathFromMxn(mxn, xmlnsMgr, mxnNew); Debug.Assert(!string.IsNullOrEmpty(strXPath)); if (xdoc != null) { xn = xdoc.SelectSingleNode(strXPath, xmlnsMgr); } Debug.Assert(xn != null); return(xn); }
public static Office.CustomXMLNode GetCustomXmlNode(Excel.Workbook workbook, string xNameSpace, string xPath) { Office.CustomXMLParts ps = workbook.CustomXMLParts; ps = ps.SelectByNamespace(xNameSpace); for (int i = 1; i <= ps.Count; i++) { Office.CustomXMLPart p = ps[i]; var nsmgr = p.NamespaceManager; nsmgr.AddNamespace("x", xNameSpace); Office.CustomXMLNode node = p.SelectSingleNode(xPath); if (node != null) { return(node); } } return(null); }
/// <summary> /// Get a CustomXMLNode from a TreeNode. /// </summary> /// <param name="tn">The TreeNode to convert.</param> /// <param name="cxp">The CustomXMLPart containing the corresponding CustomXMLNode.</param> /// <param name="fRemoveTextNode">True to get the parent XML node, False otherwise.</param> /// <returns>The corresponding CustomXMLNode.</returns> internal static Office.CustomXMLNode MxnFromTn(TreeNode tn, Office.CustomXMLPart cxp, bool fRemoveTextNode) { if (tn == null || tn.Text == "/") { throw new ArgumentNullException("tn"); } //if we hit a null node, bail if (((XmlNode)tn.Tag) == null) { throw new ArgumentNullException("tn"); } //get an nsmgr NameTable nt = new NameTable(); XmlNamespaceManager xmlnsMgr = new XmlNamespaceManager(nt); //check if we're editing the text node of an attribute, since then we'll want to get the XPath of the attribute string xpath; if (((XmlNode)tn.Tag).NodeType == XmlNodeType.Text && ((XmlNode)tn.Parent.Tag).NodeType == XmlNodeType.Attribute) { xpath = XpathFromTn(tn.Parent, fRemoveTextNode, cxp, xmlnsMgr); } else if (((XmlNode)tn.Tag).NodeType == XmlNodeType.Text) { xpath = XpathFromTn(tn, fRemoveTextNode, cxp, xmlnsMgr); } else { xpath = XpathFromTn(tn, false, cxp, xmlnsMgr); } Debug.Assert(!String.IsNullOrEmpty(xpath), "ASSERT: empty xpath", "xpathFromTn gave us back nothing!"); Office.CustomXMLNode selectedNode = cxp.SelectSingleNode(xpath); Debug.Assert(selectedNode != null, "ASSERT: null mxn from xpath", "This XPath: " + xpath + " gave us back no node!"); return(selectedNode); }
private String getCandidatePartsNames(List <Office.CustomXMLPart> cxp) { StringBuilder sb = new StringBuilder(); bool first = true; foreach (Office.CustomXMLPart cp in cxp) { Office.CustomXMLNode node = cp.SelectSingleNode("/node()"); if (first) { sb.Append(node.BaseName); first = false; } else { sb.Append(", " + node.BaseName); } } return(sb.ToString()); }
public static T GetCustomXmlByNamespace <T>(Excel.Workbook workbook, string namespaceStr) where T : class, new() { if (null == workbook) { throw new ArgumentNullException("workbook"); } if (string.IsNullOrWhiteSpace(namespaceStr)) { throw new ArgumentNullException("namespaceStr"); } Office.CustomXMLParts parts = workbook.CustomXMLParts.SelectByNamespace(namespaceStr); if (0 == parts.Count) { return(new T()); } Office.CustomXMLNode node = parts[1].DocumentElement.FirstChild; string json = node.NodeValue.Trim(); return(JsonConvert.DeserializeObject <T>(json)); }
private void part_NodeAfterDelete(Office.CustomXMLNode mxnDeletedNode, Office.CustomXMLNode mxnDeletedParent, Office.CustomXMLNode mxnDeletedNextSibling, bool bInUndoRedo) { Debug.WriteLine("Streams.NodeAfterDelete fired."); m_cmTaskPane.RefreshControls(Controls.ControlMain.ChangeReason.NodeDeleted, mxnDeletedNode, mxnDeletedParent, mxnDeletedNextSibling, null, null); }
/// <summary> /// Handle Word's OnEnter event for content controls, to set the selection in the pane (if the option is set). /// </summary> /// <param name="ccEntered">A ContentControl object specifying the control that was entered.</param> private void doc_ContentControlOnEnter(Word.ContentControl ccEntered) { log.Debug("Document.ContentControlOnEnter fired."); if (ccEntered.XMLMapping.IsMapped) { log.Debug("control mapped to " + ccEntered.XMLMapping.XPath); if (ccEntered.XMLMapping.CustomXMLNode != null) { m_cmTaskPane.RefreshControls(Controls.ControlMain.ChangeReason.OnEnter, null, null, null, ccEntered.XMLMapping.CustomXMLNode, null); } else { // Not mapped to anything; probably because the part was replaced? log.Debug(".. but XMLMapping.CustomXMLNode is null"); m_cmTaskPane.controlTreeView.DeselectNode(); m_cmTaskPane.WarnViaProperties(ccEntered.XMLMapping.XPath); } } else if (ccEntered.Tag != null) { TagData td = new TagData(ccEntered.Tag); string xpathid = td.getXPathID(); if (xpathid == null) { xpathid = td.getRepeatID(); } if (xpathid == null) { // Visually indicate in the task pane that we're no longer in a mapped control m_cmTaskPane.controlTreeView.DeselectNode(); m_cmTaskPane.PropertiesClear(); } else { log.Debug("control mapped via tag to " + xpathid); // Repeats, escaped XHTML; we don't show anything for conditions XPathsPartEntry xppe = new XPathsPartEntry(m_cmTaskPane.model); xpathsXpath xx = xppe.getXPathByID(xpathid); Office.CustomXMLNode customXMLNode = null; if (xx != null) { log.Debug(xx.dataBinding.xpath); customXMLNode = m_currentPart.SelectSingleNode(xx.dataBinding.xpath); } if (customXMLNode == null) { // Not mapped to anything; probably because the part was replaced? m_cmTaskPane.controlTreeView.DeselectNode(); if (xx == null) { log.Error("Couldn't find xpath for " + xpathid); m_cmTaskPane.WarnViaProperties("Missing"); } else { log.Warn("Couldn't find target node for " + xx.dataBinding.xpath); m_cmTaskPane.WarnViaProperties(xx.dataBinding.xpath); } } else { m_cmTaskPane.RefreshControls(Controls.ControlMain.ChangeReason.OnEnter, null, null, null, customXMLNode, null); } } } Ribbon.buttonEditEnabled = true; Ribbon.buttonDeleteEnabled = true; Ribbon.myInvalidate(); }
/// <summary> /// Refresh the dropdown list. /// </summary> /// <param name="bRebuildList">True if the list should be rebuilt from the data in the document, False otherwise.</param> /// <param name="bSelectFirstPart">True if the first part in the dropdown list should be selected after the refresh.</param> /// <param name="bSelectNewestPart">True if the last part in the dropdown list should be selected after the refresh.</param> /// <param name="strIdOfPartToSelect">A string specifying the ID of the part to be selected after the refresh.</param> /// <param name="strPartToIgnore">A string specifying the ID of a part to be ignored as part of the refresh (because it is being deleted).</param> /// <param name="mxnNodeToSelect">A CustomXMLNode specifying the node to be selected after the refresh.</param> internal void RefreshPartList(bool bRebuildList, bool bSelectFirstPart, bool bSelectNewestPart, string strIdOfPartToSelect, string strPartToIgnore, Office.CustomXMLNode mxnNodeToSelect) { this.SuspendLayout(); // store the location of the deleted item if we're losing one, since we need to reposition the selection afterwards int intPositionOfDeletedItem = -1; if (!string.IsNullOrEmpty(strPartToIgnore)) { intPositionOfDeletedItem = m_dicCurrentIndices[strPartToIgnore]; } // store the node to select m_mxnToSelect = mxnNodeToSelect; // only rebuild if we need to if (bRebuildList) { RebuildPartList(strPartToIgnore); } // get the right selection if (bSelectFirstPart) { comboBoxPartList.SelectedIndex = 0; } else if (bSelectNewestPart) { Debug.Assert(m_intLastSelected != comboBoxPartList.Items.Count - 2, "PERF: Double Refresh?", "Why are we refreshing on newest stream index?" + m_intLastSelected.ToString(CultureInfo.InvariantCulture) + " to " + comboBoxPartList.SelectedIndex.ToString(CultureInfo.InvariantCulture)); // move to the newest item // this will implicitly force a tree refresh, because we're switching the index Debug.WriteLine("Tree refresh in RefreshPartList w/ selectNewestPart."); comboBoxPartList.SelectedIndex = comboBoxPartList.Items.Count - 2; } else if (!string.IsNullOrEmpty(strIdOfPartToSelect)) { log.Debug("Selecting part by id: " + strIdOfPartToSelect); if (comboBoxPartList.SelectedIndex == m_dicCurrentIndices[strIdOfPartToSelect]) { log.Debug("SelectNodeFromTree"); controlMain.SelectNodeFromTree(m_mxnToSelect); } else { comboBoxPartList.SelectedIndex = m_dicCurrentIndices[strIdOfPartToSelect]; if (m_intLastSelected != m_dicCurrentIndices[strIdOfPartToSelect]) { // refresh the treeview Debug.WriteLine("Tree refresh in RefreshStreamSelect w/ specific stream"); log.Debug("Tree refresh in RefreshStreamSelect w/ specific stream"); controlMain.RefreshTreeControl(m_mxnToSelect); } } } else { //we want to keep on the same stream if (!string.IsNullOrEmpty(strPartToIgnore) && intPositionOfDeletedItem < m_intLastSelected) //deleting one above, so move the selection up one { comboBoxPartList.SelectedIndex = m_intLastSelected - 1; } else if (m_intLastSelected == intPositionOfDeletedItem) //deleting the one we're on, so go to the top { comboBoxPartList.SelectedIndex = 0; } else if (m_intLastSelected != comboBoxPartList.SelectedIndex) //deleting one below, so do nothing { comboBoxPartList.SelectedIndex = m_intLastSelected; } } //set the current selection m_intLastSelected = comboBoxPartList.SelectedIndex; //clear m_mxnToSelect = null; this.ResumeLayout(); this.PerformLayout(); }
/// <summary> /// Find the position of a node at its level in the XML part. /// </summary> /// <param name="xn">The XmlNode to convert.</param> /// <param name="mxnNew">A new CustomXMLNode that's not in the local tree, and therefore should be ignored when trying to find the position.</param> /// <returns>The position of the node, in XPath format (i.e. [1]).</returns> private static string XpathPosFromMxn(Office.CustomXMLNode xn, Office.CustomXMLNode mxnNew) { try { Debug.Assert(xn != null, "cannot create an xpath from a null node"); long lSib = 0; long lTotal = 0; Office.CustomXMLNode xnPrevSib = null; string name = xn.BaseName; string nsUri = xn.NamespaceURI; Office.MsoCustomXMLNodeType nt = xn.NodeType; if (xn == null) { Debug.Fail("null node"); throw new ArgumentNullException("xn"); } if (xn.ParentNode != null) { lTotal = xn.ParentNode.ChildNodes.Count; } //need to get the mxnNew down all the way to here and NOT increment the count //*if* the xnPrevSib == mxnNew, since then the new node is //*not* in my DOM, and I should not use it in the XPath(!) while ((xnPrevSib = xn.PreviousSibling) != null) { if (mxnNew != null) { if (xnPrevSib.NodeType == nt && xnPrevSib.BaseName.Equals(name) && xnPrevSib.NamespaceURI.Equals(nsUri) && xnPrevSib.XPath != mxnNew.XPath) { lSib++; } } else { if (xnPrevSib.NodeType == nt && xnPrevSib.BaseName.Equals(name) && xnPrevSib.NamespaceURI.Equals(nsUri)) { lSib++; } } xn = xnPrevSib; } return(lTotal > 0 ? "[" + (lSib + 1).ToString(CultureInfo.InvariantCulture) + "]" : ""); } catch (ArgumentNullException ex) { Debug.Fail(ex.Source, ex.Message); } return(string.Empty); }
/// <summary> /// Refresh the contents of the tree view control. /// </summary> /// <param name="mxnNodeToSelect">Optional. A CustomXMLNode specifying a node which should be selected after the refresh is completed.</param> internal void RefreshTreeControl(Office.CustomXMLNode mxnNodeToSelect) { controlTreeView.RefreshTree(mxnNodeToSelect); }
// We can't add a tag for a repeat or a condition, // unless we know the XPath. And we can't know that // if there is no suitable child to deduce it from. // But if they later press the edit button, we // would prefer not to have to ask them whether it // is a repeat or a condition. We could track the // content controls by their ID, but it seems // better to just use the Title. /// <summary> /// Wrap the selection in a Repeat. /// The XPath is deduced from plain binds in the contents. /// If there are none of these, just insert an empty content control. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public void buttonRepeat_Click(Office.IRibbonControl control) { Word.Document document = Globals.ThisAddIn.Application.ActiveDocument; // Workaround for reported Word crash. // Can't reproduce with Word 2010 sp1: 14.0.6129.500 Word.ContentControl currentCC = ContentControlMaker.getActiveContentControl(document, Globals.ThisAddIn.Application.Selection); if (currentCC != null && currentCC.Type != Word.WdContentControlType.wdContentControlRichText) { MessageBox.Show("You can't add a repeat here."); return; } OpenDoPEModel.DesignMode designMode = new OpenDoPEModel.DesignMode(document); designMode.Off(); // Find a content control within the selection List <Word.ContentControl> shallowChildren = ContentControlUtilities.getShallowestSelectedContentControls(document, Globals.ThisAddIn.Application.Selection); log.Debug(shallowChildren.Count + " shallowChildren found."); Word.ContentControl repeatCC = null; object missing = System.Type.Missing; try { repeatCC = document.ContentControls.Add(Word.WdContentControlType.wdContentControlRichText, ref missing); // Limitation here: you can't make your content control of eg type picture log.Debug("New content control added, with id: " + repeatCC.ID); designMode.On(); } catch (System.Exception) { MessageBox.Show("Selection must be either part of a single paragraph, or one or more whole paragraphs"); designMode.restoreState(); return; } repeatCC.Title = "Repeat [unbound]"; // This used if they later click edit if (shallowChildren.Count == 0) { log.Debug("No child control found. So Repeat not set on our new CC"); //MessageBox.Show("Unbound content control only added. Click the edit button to setup the repeat."); editXPath(repeatCC); return; } // For now, just use the tag on the first simple bind we find. // Later, we could try parsing a condition or repeat Word.ContentControl usableChild = null; foreach (Word.ContentControl child in shallowChildren) { //if (child.Tag.Contains("od:xpath")) if (child.XMLMapping.IsMapped) { usableChild = child; break; } } if (usableChild == null) { log.Debug("No usable child found. So Repeat not set on our new CC"); //MessageBox.Show("Naked content control only added. Click the edit button to setup the repeat."); editXPath(repeatCC); return; } string strXPath = null; // Need to work out what repeats. Could be this child, // the parent, etc. If its obvious from this exemplar xml doc, // we can do it automatically. Otherwise, we'll ask user. // Currently the logic supports repeating ., .., or grandparent. // See whether this child repeats in this exemplar. Office.CustomXMLNode thisNode = usableChild.XMLMapping.CustomXMLNode; Office.CustomXMLNode thisNodeSibling = usableChild.XMLMapping.CustomXMLNode.NextSibling; Office.CustomXMLNode parent = usableChild.XMLMapping.CustomXMLNode.ParentNode; Office.CustomXMLNode parentSibling = usableChild.XMLMapping.CustomXMLNode.ParentNode.NextSibling; if (thisNodeSibling != null && thisNodeSibling.BaseName.Equals(thisNode.BaseName)) { // Looks like this node repeats :-) strXPath = usableChild.XMLMapping.XPath; // Get XPath. Could use the od xpaths part, but // easier here to work with the binding log.Debug("Using . as repeat: " + strXPath); } // If it doesn't, test parent. else if (parentSibling != null && parentSibling.BaseName.Equals(parent.BaseName)) { strXPath = usableChild.XMLMapping.XPath; log.Debug("Using parent for repeat "); strXPath = strXPath.Substring(0, strXPath.LastIndexOf("/")); log.Debug("Using: " + strXPath); } else // If that doesn't either, ask user. { Office.CustomXMLNode grandparent = null; if (parent != null) { grandparent = parent.ParentNode; } using (Forms.FormSelectRepeatedElement sr = new Forms.FormSelectRepeatedElement()) { sr.labelXPath.Text = usableChild.XMLMapping.XPath; sr.listElementNames.Items.Add(thisNode.BaseName); sr.listElementNames.Items.Add(parent.BaseName); if (grandparent != null) { sr.listElementNames.Items.Add(grandparent.BaseName); } sr.listElementNames.SelectedIndex = 0; sr.ShowDialog(); if (sr.listElementNames.SelectedIndex == 0) { strXPath = usableChild.XMLMapping.XPath; } else if (sr.listElementNames.SelectedIndex == 1) { strXPath = parent.XPath; log.Debug("Using parent for repeat: " + strXPath); } else { // Grandparent strXPath = grandparent.XPath; log.Debug("Using grandparent for repeat: " + strXPath); } } } // Need to drop eg [1] (if any), so BetterForm-based interactive processing works if (strXPath.EndsWith("]")) { strXPath = strXPath.Substring(0, strXPath.LastIndexOf("[")); log.Debug("Having dropped '[]': " + strXPath); } XPathsPartEntry xppe = new XPathsPartEntry(Model.ModelFactory(document)); // TODO fix usableChild.XMLMapping.PrefixMappings xppe.setup("rpt", usableChild.XMLMapping.CustomXMLPart.Id, strXPath, "", false); // No Q for repeat xppe.save(); repeatCC.Title = "Repeat: " + xppe.xpathId; // Write tag TagData td = new TagData(""); td.set("od:repeat", xppe.xpathId); repeatCC.Tag = td.asQueryString(); }
/// <summary> /// Refresh the contents of the property grid. /// </summary> /// <param name="mxn">A CustomXMLNode specifying the node whose properties we want to display.</param> internal void RefreshProperties(Office.CustomXMLNode mxn) { controlProperties.RefreshProperties(mxn); }
public void treeView_ItemDrag(object sender, ItemDragEventArgs e, ControlTreeView controlTreeView, ControlMain controlMain, Word.Document CurrentDocument, Office.CustomXMLPart CurrentPart, XmlDocument OwnerDocument, bool _PictureContentControlsReplace) { object missing = System.Type.Missing; TreeNode tn = (TreeNode)e.Item; if (tn == null) { Debug.Fail("no tn"); return; } //check if this is something we can drag if (((XmlNode)tn.Tag).NodeType == XmlNodeType.ProcessingInstruction || ((XmlNode)tn.Tag).NodeType == XmlNodeType.Comment) { return; } if (controlMain.modeControlEnabled == false || // ie always mode bind controlMain.controlMode1.isModeBind()) { if (!ControlTreeView.IsLeafNode(tn) || ((XmlNode)tn.Tag).NodeType == XmlNodeType.Text && !ControlTreeView.IsLeafNode(tn.Parent)) { return; } } // repeats and conditions; let them drag any node //get an nsmgr NameTable nt = new NameTable(); //generate the xpath and the ns manager XmlNamespaceManager xmlnsMgr = new XmlNamespaceManager(nt); string strXPath = Utilities.XpathFromXn(CurrentPart.NamespaceManager, (XmlNode)tn.Tag, true, xmlnsMgr); log.Info("Dragging XPath: " + strXPath); string prefixMappings = Utilities.GetPrefixMappings(xmlnsMgr); // OpenDoPE TagData td = new TagData(""); String val = ((XmlNode)tn.Tag).InnerText; DesignMode designMode = new OpenDoPEModel.DesignMode(CurrentDocument); // Special case for pictures, since drag/drop does not seem // to work properly (the XHTML pasted doesn't do what it should?) bool isPicture = ContentDetection.IsBase64Encoded(val); if (isPicture && !_PictureContentControlsReplace) { designMode.Off(); log.Debug("Special case handling for pictures.."); // Selection can't be textual content, so ensure it isn't. // It is allowed to be a picture, so in the future we could // leave the selection alone if it is just a picture. Globals.ThisAddIn.Application.Selection.Collapse(ref missing); // Are they dragging to an existing picture content control Word.ContentControl picCC = ContentControlMaker.getActiveContentControl(CurrentDocument, Globals.ThisAddIn.Application.Selection); try { if (picCC == null || (picCC.Type != Word.WdContentControlType.wdContentControlPicture)) { picCC = CurrentDocument.ContentControls.Add( Word.WdContentControlType.wdContentControlPicture, ref missing); designMode.restoreState(); } } catch (COMException ce) { // Will happen if you try to drag a text node onto an existing image content control log.Debug("Ignoring " + ce.Message); return; } XPathsPartEntry xppe = new XPathsPartEntry(controlMain.model); xppe.setup(null, CurrentPart.Id, strXPath, prefixMappings, false); xppe.save(); td.set("od:xpath", xppe.xpathId); picCC.Tag = td.asQueryString(); picCC.Title = "Data value: " + xppe.xpathId; picCC.XMLMapping.SetMappingByNode(Utilities.MxnFromTn(tn, CurrentPart, true)); return; } log.Debug("\n\ntreeView_ItemDrag for WdSelectionType " + Globals.ThisAddIn.Application.Selection.Type.ToString()); bool isXHTML = false; bool isFlatOPC = ContentDetection.IsFlatOPCContent(val); if (!isFlatOPC) { isXHTML = ContentDetection.IsXHTMLContent(val); } if (Globals.ThisAddIn.Application.Selection.Type != Microsoft.Office.Interop.Word.WdSelectionType.wdSelectionIP) { // ie something is selected, since "inline paragraph selection" // just means the cursor is somewhere inside // a paragraph, but with nothing selected. designMode.Off(); // Selection types: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.wdselectiontype(v=office.11).aspx log.Debug("treeView_ItemDrag fired, but interpreted as gesture for WdSelectionType " + Globals.ThisAddIn.Application.Selection.Type.ToString()); Word.ContentControl parentCC = ContentControlMaker.getActiveContentControl(CurrentDocument, Globals.ThisAddIn.Application.Selection); // Insert bind | condition | repeat // depending on which mode button is pressed. if (controlMain.modeControlEnabled == false || // ie always mode bind controlMain.controlMode1.isModeBind()) { log.Debug("In bind mode"); Word.ContentControl cc = null; try { if (isFlatOPC || isXHTML || (isPicture && _PictureContentControlsReplace)) { // Rich text if (parentCC != null && ContentControlOpenDoPEType.isBound(parentCC)) { // Reuse existing cc cc = ContentControlMaker.MakeOrReuse(true, Word.WdContentControlType.wdContentControlRichText, CurrentDocument, Globals.ThisAddIn.Application.Selection); } else { // Make new cc cc = ContentControlMaker.MakeOrReuse(true, Word.WdContentControlType.wdContentControlRichText, CurrentDocument, Globals.ThisAddIn.Application.Selection); } if (isFlatOPC) { log.Debug(".. contains block content "); // Ensure block level Inline2Block i2b = new Inline2Block(); cc = i2b.convertToBlockLevel(cc, false, true); if (cc == null) { MessageBox.Show("Problems inserting block level WordML at this location."); return; } } else if (isXHTML && // and thus not picture Inline2Block.containsBlockLevelContent(val)) { log.Debug(".. contains block content "); // Ensure block level Inline2Block i2b = new Inline2Block(); cc = i2b.convertToBlockLevel(cc, false, true); if (cc == null) { MessageBox.Show("Problems inserting block level XHTML at this location."); return; } } } else { // Plain text if (parentCC != null && ContentControlOpenDoPEType.isBound(parentCC)) { // Reuse existing cc cc = ContentControlMaker.MakeOrReuse(true, Word.WdContentControlType.wdContentControlText, CurrentDocument, Globals.ThisAddIn.Application.Selection); } else { // Make new cc cc = ContentControlMaker.MakeOrReuse(false, Word.WdContentControlType.wdContentControlText, CurrentDocument, Globals.ThisAddIn.Application.Selection); } cc.MultiLine = true; // Is a text content control always run-level? // No, not if you have a single para selected and you do drag gesture // (or if you remap a rich text control) } } catch (Exception ex) { log.Error("Couldn't add content control: " + ex.Message); return; } XPathsPartEntry xppe = new XPathsPartEntry(controlMain.model); xppe.setup(null, CurrentPart.Id, strXPath, prefixMappings, true); xppe.save(); td.set("od:xpath", xppe.xpathId); if (isFlatOPC) { // <?mso-application progid="Word.Document"?> // <pkg:package xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage"> td.set("od:progid", "Word.Document"); cc.Title = "Word: " + xppe.xpathId; //cc.Range.Text = val; // don't escape it cc.Range.InsertXML(val, ref missing); } else if (isXHTML) { td.set("od:ContentType", "application/xhtml+xml"); cc.Title = "XHTML: " + xppe.xpathId; cc.Range.Text = val; // don't escape it } else if (isPicture) { PictureUtils.setPictureHandler(td); cc.Title = "Image: " + xppe.xpathId; string picContent = CurrentPart.SelectSingleNode(strXPath).Text; PictureUtils.pastePictureIntoCC(cc, Convert.FromBase64String(picContent)); } else { cc.XMLMapping.SetMappingByNode(Utilities.MxnFromTn(tn, CurrentPart, true)); string nodeXML = cc.XMLMapping.CustomXMLNode.XML; log.Info(nodeXML); cc.Title = "Data value: " + xppe.xpathId; } cc.Tag = td.asQueryString(); designMode.restoreState(); } else if (controlMain.controlMode1.isModeCondition()) { log.Debug("In condition mode"); Word.ContentControl cc = null; try { // always make new cc = ContentControlMaker.MakeOrReuse(false, Word.WdContentControlType.wdContentControlRichText, CurrentDocument, Globals.ThisAddIn.Application.Selection); } catch (Exception ex) { log.Error("Couldn't add content control: " + ex.Message); return; } ConditionsPartEntry cpe = new ConditionsPartEntry(controlMain.model); cpe.setup(CurrentPart.Id, strXPath, prefixMappings, true); cpe.save(); cc.Title = "Conditional: " + cpe.conditionId; // Write tag td.set("od:condition", cpe.conditionId); cc.Tag = td.asQueryString(); designMode.On(); } else if (controlMain.controlMode1.isModeRepeat()) { log.Debug("In repeat mode"); Word.ContentControl cc = null; try { // always make new cc = ContentControlMaker.MakeOrReuse(false, Word.WdContentControlType.wdContentControlRichText, CurrentDocument, Globals.ThisAddIn.Application.Selection); } catch (Exception ex) { log.Error("Couldn't add content control: " + ex.Message); return; } // Need to drop eg [1] (if any), so BetterForm-based interactive processing works if (strXPath.EndsWith("]")) { strXPath = strXPath.Substring(0, strXPath.LastIndexOf("[")); log.Debug("Having dropped '[]': " + strXPath); } XPathsPartEntry xppe = new XPathsPartEntry(controlMain.model); xppe.setup("rpt", CurrentPart.Id, strXPath, prefixMappings, false); // no Q for repeat xppe.save(); cc.Title = "Repeat: " + xppe.xpathId; // Write tag td.set("od:repeat", xppe.xpathId); cc.Tag = td.asQueryString(); designMode.On(); } return; } // end if (Globals.ThisAddIn.Application.Selection.Type != Microsoft.Office.Interop.Word.WdSelectionType.wdSelectionIP) // Selection.Type: Microsoft.Office.Interop.Word.WdSelectionType.wdSelectionIP // ie cursor is somewhere inside a paragraph, but with nothing selected. log.Info("In wdSelectionIP specific code."); // leave designMode alone here // Following processing uses clipboard HTML to implement drag/drop processing // Could avoid dealing with that (what's the problem anyway?) if they are dragging onto an existing content control, with: //Word.ContentControl existingCC = ContentControlMaker.getActiveContentControl(CurrentDocument, Globals.ThisAddIn.Application.Selection); //if (existingCC != null) return; // But that stops them from dragging any more content into a repeat. string title = ""; string tag = ""; bool needBind = false; log.Debug(strXPath); Office.CustomXMLNode targetNode = CurrentPart.SelectSingleNode(strXPath); string nodeContent = targetNode.Text; // or ((XmlNode)tn.Tag).InnerXml // Insert bind | condition | repeat // depending on which mode button is pressed. if (controlMain.modeControlEnabled == false || // ie always mode bind controlMain.controlMode1.isModeBind()) { log.Debug("In bind mode"); // OpenDoPE: create w:tag=od:xpath=x1 // and add XPath to xpaths part XPathsPartEntry xppe = new XPathsPartEntry(controlMain.model); xppe.setup(null, CurrentPart.Id, strXPath, prefixMappings, false); // Don't setup Q until after drop xppe.save(); // Write tag td.set("od:xpath", xppe.xpathId); // Does this node contain XHTML? // TODO: error handling log.Info(nodeContent); if (isFlatOPC) { // <?mso-application progid="Word.Document"?> // <pkg:package xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage"> td.set("od:progid", "Word.Document"); title = "Word: " + xppe.xpathId; needBind = false; // make it a rich text control } else if (isXHTML) { td.set("od:ContentType", "application/xhtml+xml"); // TODO since this is a run-level sdt, // the XHTML content will need to be run-level. // Help the user with this? // Or in a run-level context, docx4j could convert // p to soft-enter? But what to do about tables? title = "XHTML: " + xppe.xpathId; needBind = false; // make it a rich text control // Word will only replace our HTML-imported-to-docx with the raw HTML // if we have the bind. // Without this, giving the user visual feedback in Word is a TODO } else if (isPicture) { designMode.Off(); log.Debug("NEW Special case handling for pictures.."); //object missing = System.Type.Missing; Globals.ThisAddIn.Application.Selection.Collapse(ref missing); // Are they dragging to an existing picture content control Word.ContentControl picCC = ContentControlMaker.getActiveContentControl(CurrentDocument, Globals.ThisAddIn.Application.Selection); try { if (picCC == null || (picCC.Type != Word.WdContentControlType.wdContentControlPicture)) { picCC = CurrentDocument.ContentControls.Add( Word.WdContentControlType.wdContentControlRichText, ref missing); designMode.restoreState(); } } catch (COMException ce) { // Will happen if you try to drag a text node onto an existing image content control log.Debug("Ignoring " + ce.Message); return; } PictureUtils.setPictureHandler(td); picCC.Title = "Image: " + xppe.xpathId; picCC.Tag = td.asQueryString(); PictureUtils.pastePictureIntoCC(picCC, Convert.FromBase64String(nodeContent)); return; } else { title = "Data value: " + xppe.xpathId; needBind = true; } tag = td.asQueryString(); } else if (controlMain.controlMode1.isModeCondition()) { log.Debug("In condition mode"); ConditionsPartEntry cpe = new ConditionsPartEntry(controlMain.model); cpe.setup(CurrentPart.Id, strXPath, prefixMappings, false); cpe.save(); title = "Conditional: " + cpe.conditionId; // Write tag td.set("od:condition", cpe.conditionId); tag = td.asQueryString(); } else if (controlMain.controlMode1.isModeRepeat()) { log.Debug("In repeat mode"); // Need to drop eg [1] (if any), so BetterForm-based interactive processing works if (strXPath.EndsWith("]")) { strXPath = strXPath.Substring(0, strXPath.LastIndexOf("[")); log.Debug("Having dropped '[]': " + strXPath); } XPathsPartEntry xppe = new XPathsPartEntry(controlMain.model); xppe.setup("rpt", CurrentPart.Id, strXPath, prefixMappings, false); xppe.save(); title = "Data value: " + xppe.xpathId; // Write tag td.set("od:repeat", xppe.xpathId); tag = td.asQueryString(); } //create the HTML string strHTML = string.Empty; if (isFlatOPC) { // <?mso-application progid="Word.Document"?> // <pkg:package xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage"> nodeContent = ControlTreeView.EscapeXHTML(nodeContent); strHTML = ClipboardUtilities.GenerateClipboardHTML(needBind, strXPath, Utilities.GetPrefixMappings(xmlnsMgr), CurrentPart.Id, Utilities.MappingType.RichText, title, tag, nodeContent); } else if (isXHTML) { // need to escape eg <span> for it to get through the Clipboard nodeContent = ControlTreeView.EscapeXHTML(nodeContent); // use a RichText control, and set nodeContent strHTML = ClipboardUtilities.GenerateClipboardHTML(needBind, strXPath, Utilities.GetPrefixMappings(xmlnsMgr), CurrentPart.Id, Utilities.MappingType.RichText, title, tag, nodeContent); // alternatively, this could be done in DocumentEvents.doc_ContentControlAfterAdd // but to do it there, we'd need to manually resolve the XPath to // find the value of the CustomXMLNode it pointed to. } else if (!needBind) { // For conditions & repeats, we use a RichText control strHTML = ClipboardUtilities.GenerateClipboardHTML(needBind, strXPath, Utilities.GetPrefixMappings(xmlnsMgr), CurrentPart.Id, Utilities.MappingType.RichText, title, tag); } else { // Normal bind if (OwnerDocument.Schemas.Count > 0) { switch (Utilities.CheckNodeType((XmlNode)tn.Tag)) { case Utilities.MappingType.Date: strHTML = ClipboardUtilities.GenerateClipboardHTML(needBind, strXPath, prefixMappings, CurrentPart.Id, Utilities.MappingType.Date, title, tag); break; case Utilities.MappingType.DropDown: strHTML = ClipboardUtilities.GenerateClipboardHTML(needBind, strXPath, prefixMappings, CurrentPart.Id, Utilities.MappingType.DropDown, title, tag); break; case Utilities.MappingType.Picture: strHTML = ClipboardUtilities.GenerateClipboardHTML(needBind, strXPath, prefixMappings, CurrentPart.Id, Utilities.MappingType.Picture, title, tag); break; default: strHTML = ClipboardUtilities.GenerateClipboardHTML(needBind, strXPath, prefixMappings, CurrentPart.Id, Utilities.MappingType.Text, title, tag); break; } } else { //String val = ((XmlNode)tn.Tag).InnerText; if (ContentDetection.IsBase64Encoded(val)) { // Force picture content control strHTML = ClipboardUtilities.GenerateClipboardHTML(needBind, strXPath, Utilities.GetPrefixMappings(xmlnsMgr), CurrentPart.Id, Utilities.MappingType.Picture, title, tag); } else { strHTML = ClipboardUtilities.GenerateClipboardHTML(needBind, strXPath, Utilities.GetPrefixMappings(xmlnsMgr), CurrentPart.Id, Utilities.MappingType.Text, title, tag); } } } // All cases:- //notify ourselves of a pending drag/drop controlMain.NotifyDragDrop(true); //throw it on the clipboard to drag DataObject dobj = new DataObject(); dobj.SetData(DataFormats.Html, strHTML); dobj.SetData(DataFormats.Text, tn.Text); controlTreeView.DoDragDrop(dobj, DragDropEffects.Move); //notify ourselves of a completed drag/drop controlMain.NotifyDragDrop(false); Clipboard.SetData(DataFormats.Text, ((XmlNode)tn.Tag).InnerXml); }
public TreeViewElements(Office.CustomXMLPart cxpTreeView, Office.CustomXMLNode mxnNodeToSelect) { m_cxpTreeView = cxpTreeView; m_xdocTreeView = new XmlDocument(); m_mxnNodeToSelect = mxnNodeToSelect; }
private void part_NodeAfterInsert(Office.CustomXMLNode mxnNewNode, bool bInUndoRedo) { Debug.WriteLine("Streams.NodeAfterInsert fired."); m_cmTaskPane.RefreshControls(Controls.ControlMain.ChangeReason.NodeAdded, null, null, null, mxnNewNode, null); }
private void part_NodeAfterReplace(Office.CustomXMLNode mxnOldNode, Office.CustomXMLNode mxnNewNode, bool bInUndoRedo) { Debug.WriteLine("Streams.NodeAfterReplace fired."); m_cmTaskPane.RefreshControls(Controls.ControlMain.ChangeReason.NodeReplaced, mxnOldNode, mxnNewNode.ParentNode, mxnNewNode.NextSibling, mxnNewNode, null); }
/// <summary> /// Get an XPath for a CustomXMLNode. /// </summary> /// <param name="xn">The CustomXMLNode to convert.</param> /// <param name="xnsmgr">The XmlNamespaceManager for the local XML tree.</param> /// <param name="mxnNew">A new CustomXMLNode that's not in the local tree, and therefore should be ignored when trying to find the XPath.</param> /// <returns>The corresponding XPath.</returns> private static string XpathFromMxn(Office.CustomXMLNode xn, XmlNamespaceManager xnsmgr, Office.CustomXMLNode mxnNew) { try { Debug.Assert(xn != null, "cannot create an xpath from a null node"); string strThis = null; string strThisName = null; string ns = ""; bool fCheckParent = true; Office.CustomXMLNode xnParent = xn.ParentNode; Office.CustomXMLPrefixMappings mnsmgr = xn.OwnerPart.NamespaceManager; switch (xn.NodeType) { case Office.MsoCustomXMLNodeType.msoCustomXMLNodeElement: strThisName = xn.BaseName; if (!string.IsNullOrEmpty(xn.NamespaceURI)) { ns = mnsmgr.LookupPrefix(xn.NamespaceURI) + ":"; xnsmgr.AddNamespace(mnsmgr.LookupPrefix(xn.NamespaceURI), xn.NamespaceURI); } strThis = "/" + ns + strThisName + XpathPosFromMxn(xn, mxnNew); break; case Office.MsoCustomXMLNodeType.msoCustomXMLNodeAttribute: strThisName = xn.BaseName; if (!string.IsNullOrEmpty(xn.NamespaceURI)) { ns = mnsmgr.LookupPrefix(xn.NamespaceURI) + ":"; xnsmgr.AddNamespace(mnsmgr.LookupPrefix(xn.NamespaceURI), xn.NamespaceURI); } strThis = "/@" + ns + strThisName; xnParent = xn.SelectSingleNode(".."); break; case Office.MsoCustomXMLNodeType.msoCustomXMLNodeProcessingInstruction: { strThis = "/processing-instruction("; strThis = strThis + ")" + XpathPosFromMxn(xn, mxnNew); break; } case Office.MsoCustomXMLNodeType.msoCustomXMLNodeText: strThis = "/text()" + XpathPosFromMxn(xn, mxnNew); break; case Office.MsoCustomXMLNodeType.msoCustomXMLNodeComment: strThis = "/comment()" + XpathPosFromMxn(xn, mxnNew); break; case Office.MsoCustomXMLNodeType.msoCustomXMLNodeDocument: strThis = ""; fCheckParent = false; break; case Office.MsoCustomXMLNodeType.msoCustomXMLNodeCData: strThis = "/text()" + XpathPosFromMxn(xn, mxnNew); break; } return(strThis.Insert(0, fCheckParent ? XpathFromMxn(xnParent, xnsmgr, mxnNew) : "")); } catch (COMException ex) { Debug.Fail(ex.Source, ex.Message); } return(string.Empty); }
/// <summary> /// Select a node within the tree view. /// </summary> /// <param name="mxnToSelect">A CustomXMLNode specifying a node which should be selected after the refresh is completed.</param> internal void SelectNodeFromTree(Office.CustomXMLNode mxnToSelect) { //select the node (happens on the calling thread) controlTreeView.SelectNodeFromTree(mxnToSelect); }
/// <summary> /// Refresh the dropdown list. /// </summary> /// <param name="bRebuildList">True if the list should be rebuilt from the data in the document, False otherwise.</param> /// <param name="bSelectFirstPart">True if the first part in the dropdown list should be selected after the refresh.</param> /// <param name="bSelectNewestPart">True if the last part in the dropdown list should be selected after the refresh.</param> /// <param name="strIdOfPartToSelect">A string specifying the ID of the part to be selected after the refresh.</param> /// <param name="strPartToIgnore">A string specifying the ID of a part to be ignored as part of the refresh (because it is being deleted).</param> /// <param name="mxnNodeToSelect">A CustomXMLNode specifying the node to be selected after the refresh.</param> internal void RefreshPartList(bool bRebuildList, bool bSelectFirstPart, bool bSelectNewestPart, string strIdOfPartToSelect, string strPartToIgnore, Office.CustomXMLNode mxnNodeToSelect) { this.SuspendLayout(); // store the location of the deleted item if we're losing one, since we need to reposition the selection afterwards int intPositionOfDeletedItem = -1; if (!string.IsNullOrEmpty(strPartToIgnore)) { intPositionOfDeletedItem = m_dicCurrentIndices[strPartToIgnore]; } // store the node to select m_mxnToSelect = mxnNodeToSelect; // only rebuild if we need to if (bRebuildList) { RebuildPartList(strPartToIgnore); } // get the right selection if (bSelectFirstPart) { comboBoxPartList.SelectedIndex = 0; } else if (bSelectNewestPart) { Debug.Assert(m_intLastSelected != comboBoxPartList.Items.Count - 2, "PERF: Double Refresh?", "Why are we refreshing on newest stream index?" + m_intLastSelected.ToString(CultureInfo.InvariantCulture) + " to " + comboBoxPartList.SelectedIndex.ToString(CultureInfo.InvariantCulture)); // move to the newest item // this will implicitly force a tree refresh, because we're switching the index Debug.WriteLine("Tree refresh in RefreshPartList w/ selectNewestPart."); comboBoxPartList.SelectedIndex = comboBoxPartList.Items.Count - 2; } else if (!string.IsNullOrEmpty(strIdOfPartToSelect)) { if (comboBoxPartList.SelectedIndex == m_dicCurrentIndices[strIdOfPartToSelect]) { ((ControlMain)Parent).SelectNodeFromTree(m_mxnToSelect); } else { comboBoxPartList.SelectedIndex = m_dicCurrentIndices[strIdOfPartToSelect]; if (m_intLastSelected != m_dicCurrentIndices[strIdOfPartToSelect]) { // refresh the treeview Debug.WriteLine("Tree refresh in RefreshStreamSelect w/ specific stream"); ((ControlMain)Parent).RefreshTreeControl(m_mxnToSelect); } } } else { //we want to keep on the same stream if (!string.IsNullOrEmpty(strPartToIgnore) && intPositionOfDeletedItem < m_intLastSelected) //deleting one above, so move the selection up one { comboBoxPartList.SelectedIndex = m_intLastSelected - 1; } else if (m_intLastSelected == intPositionOfDeletedItem) //deleting the one we're on, so go to the top { comboBoxPartList.SelectedIndex = 0; } else if (m_intLastSelected != comboBoxPartList.SelectedIndex) //deleting one below, so do nothing { comboBoxPartList.SelectedIndex = m_intLastSelected; } } //set the current selection m_intLastSelected = comboBoxPartList.SelectedIndex; //clear m_mxnToSelect = null; this.ResumeLayout(); this.PerformLayout(); }
/// <summary> /// Refresh the task pane based on some event. /// </summary> /// <param name="ehReason">A ChangeReason value specifying the reason for the refresh request.</param> /// <param name="mxnOldNode">A CustomXMLNode specifying the deleted node (if applicable).</param> /// <param name="mxnOldParent">A CustomXMLNode specifying the former parent node of the deleted node (if applicable).</param> /// <param name="mxnOldNextSibling">A CustomXMLNode specifying the former next sibling node of the affected node (if applicable).</param> /// <param name="mxnNewNode">A CustomXMLNode specifying the new node (if applicable).</param> /// <param name="cxpOldPart">A CustomXMLPart specifying the XML part being deleted (if applicable).</param> internal void RefreshControls(ChangeReason ehReason, Office.CustomXMLNode mxnOldNode, Office.CustomXMLNode mxnOldParent, Office.CustomXMLNode mxnOldNextSibling, Office.CustomXMLNode mxnNewNode, Office._CustomXMLPart cxpOldPart) { // determine why we've been asked to refresh the pane switch (ehReason) { case ChangeReason.DocumentChanged: Debug.WriteLine("UI refresh for document change."); if (!Globals.ThisAddIn.Application.ShowWindowsInTaskbar) { EventHandler.ChangeCurrentDocument(); } controlPartList.RefreshPartList(true, true, false, string.Empty, null, null); break; case ChangeReason.PartAdded: Debug.WriteLine("UI refresh for stream addition."); controlPartList.RefreshPartList(true, false, false, string.Empty, null, null); break; case ChangeReason.PartDeleted: Debug.WriteLine("UI refresh for stream deletion."); Debug.Assert(cxpOldPart != null, "We were handed a NULL cxp?"); controlPartList.RefreshPartList(true, false, false, string.Empty, cxpOldPart.Id, null); break; case ChangeReason.PartLoaded: Debug.WriteLine("UI refresh for stream load."); controlPartList.RefreshPartList(true, false, false, string.Empty, null, null); break; case ChangeReason.NodeAdded: Debug.WriteLine("UI refresh for node addition."); controlTreeView.AddMxnToTree(mxnNewNode); break; case ChangeReason.NodeDeleted: Debug.WriteLine("UI refresh for node deletion."); controlTreeView.RemoveMxnFromTree(mxnOldNode, mxnOldParent, mxnOldNextSibling, null); break; case ChangeReason.NodeReplaced: Debug.WriteLine("UI refresh for node replacement."); controlTreeView.ReplaceMxnInTree(mxnOldNode, mxnNewNode); break; case ChangeReason.DragDrop: Debug.WriteLine("UI refresh for drag/drop of XML."); controlPartList.RefreshPartList(true, false, true, string.Empty, null, null); break; case ChangeReason.OnEnter: Debug.WriteLine("UI refresh for BB enter."); Debug.Assert(mxnNewNode != null, "No mxn for CC?"); if ((controlTreeView.Options & ControlTreeView.cOptionsAutoSelectNode) != 0) { controlPartList.RefreshPartList(false, false, false, mxnNewNode.OwnerPart.Id, null, mxnNewNode); } break; default: Debug.Assert(false, "Unknown refresh event", "We got called on a refresh event that doesn't exist??"); break; } }
private void launchTaskPane() { //set the cursor to wait Globals.ThisAddIn.Application.System.Cursor = Word.WdCursorType.wdCursorWait; //set up the task pane CustomTaskPane ctpPaneForThisWindow = Globals.ThisAddIn.CustomTaskPanes.Add( new Controls.ControlMain(), Properties.Resources.TaskPaneName); ctpPaneForThisWindow.DockPositionRestrict = Office.MsoCTPDockPositionRestrict.msoCTPDockPositionRestrictNoHorizontal; //store it for later if (Globals.ThisAddIn.Application.ShowWindowsInTaskbar) { Globals.ThisAddIn.TaskPaneList.Add(Globals.ThisAddIn.Application.ActiveWindow, ctpPaneForThisWindow); } //connect task pane events Globals.ThisAddIn.ConnectTaskPaneEvents(ctpPaneForThisWindow); //get the control we hosted Controls.ControlMain ccm = (Controls.ControlMain)ctpPaneForThisWindow.Control; ccm.formPartList.ccm = ccm; // OK, OpenDoPE parts should exist Model model = Model.ModelFactory(Globals.ThisAddIn.Application.ActiveDocument); // hand the OpenDoPE model to the control ccm.model = model; //hand the eventing class to the control DocumentEvents de = new DocumentEvents(ccm); de.Ribbon = this; // so de can enable/disable stuff on ribbon ccm.EventHandlerAndOnChildren = de; // following is no good for us, since it selects first part //ccm.RefreshControls(Controls.ControlMain.ChangeReason.DocumentChanged, null, null, null, null, null); // The current cxp is stored in the DocumentEvents object // (which in turn is a field in ControlBase). // The user custom xml part is to current in DocumentEvents. // But we also need: string requiredRoot = System.Configuration.ConfigurationManager.AppSettings["RootElement"]; Office.CustomXMLPart userPart = model.getUserPart(requiredRoot); Office.CustomXMLNode mxnNewNode = userPart.DocumentElement; log.Debug("DocumentElement of user part: " + mxnNewNode.BaseName); ccm.formPartList.controlPartList.RefreshPartList(true, false, false, mxnNewNode.OwnerPart.Id, null, mxnNewNode); //ccm.RefreshControls(Controls.ControlMain.ChangeReason.OnEnter, null, null, null, mxnNewNode, null); // would also work, but is more opaque //show it ctpPaneForThisWindow.Visible = true; this.buttonBindEnabled = true; this.buttonConditionEnabled = true; this.buttonRepeatEnabled = true; this.menuAdvancedEnabled = true; this.buttonReplaceXMLEnabled = true; this.buttonClearAllEnabled = true; myInvalidate(); //reset the cursor Globals.ThisAddIn.Application.System.Cursor = Word.WdCursorType.wdCursorNormal; }