/// <summary>
        /// Add a new topic file to the project and the editor
        /// </summary>
        /// <param name="filename">The filename of the topic to add</param>
        /// <param name="addAsChild">True to add as a child of the selected
        /// topic or false to add it as a sibling.</param>
        /// <returns>The topic that was just added</returns>
        private Topic AddTopicFile(string filename, bool addAsChild)
        {
            Topic newTopic, currentTopic = ucContentLayoutEditor.CurrentTopic;
            string newPath = filename, projectPath = Path.GetDirectoryName(
                contentLayoutFile.Project.Filename);

            // The file must reside under the project path
            if(!Path.GetDirectoryName(filename).StartsWith(projectPath, StringComparison.OrdinalIgnoreCase))
                newPath = Path.Combine(projectPath, Path.GetFileName(filename));

            // Add the file to the project if not already there
            FileItem newItem = contentLayoutFile.Project.AddFileToProject(filename, newPath);

            // Add the topic to the editor's collection
            newTopic = new Topic
            {
                TopicFile = new TopicFile(newItem.ToContentFile())
            };

            if(addAsChild && currentTopic != null)
            {
                currentTopic.Subtopics.Add(newTopic);
                currentTopic.IsExpanded = true;
            }
            else
                if(currentTopic == null)
                    ucContentLayoutEditor.Topics.Add(newTopic);
                else
                    currentTopic.Parent.Insert(currentTopic.Parent.IndexOf(currentTopic) + 1, newTopic);

            newTopic.IsSelected = true;

            return newTopic;
        }
Beispiel #2
0
        //=====================================================================
        /// <summary>
        /// This is used to load the topic information from the project
        /// file.
        /// </summary>
        /// <param name="xr">The XML text reader from which the information
        /// is loaded.</param>
        internal void ReadXml(XmlReader xr)
        {
            Topic newTopic;
            string guid, parentMode;
            bool visible, attrValue;

            guid = xr.GetAttribute("id");

            if(guid != null && guid.Trim().Length != 0)
                contentId = guid;
            else
                contentId = Guid.NewGuid().ToString();

            if(!Boolean.TryParse(xr.GetAttribute("noFile"), out noFile))
                noFile = false;

            if(!Boolean.TryParse(xr.GetAttribute("visible"), out visible))
                visible = true;

            if(Boolean.TryParse(xr.GetAttribute("isDefault"), out attrValue))
                this.IsDefaultTopic = attrValue;

            if(Boolean.TryParse(xr.GetAttribute("isMSHVRoot"), out attrValue))
                this.IsMSHVRootContentContainer = attrValue;

            parentMode = xr.GetAttribute("apiParentMode");

            if(!String.IsNullOrEmpty(parentMode))
                this.ApiParentMode = (ApiParentMode)Enum.Parse(typeof(ApiParentMode), parentMode, true);

            this.Visible = visible;
            this.Title = xr.GetAttribute("title");
            this.TocTitle = xr.GetAttribute("tocTitle");
            this.LinkText = xr.GetAttribute("linkText");

            if(!xr.IsEmptyElement)
                while(!xr.EOF)
                {
                    xr.Read();

                    if(xr.NodeType == XmlNodeType.EndElement && xr.Name == "Topic")
                        break;

                    if(xr.NodeType == XmlNodeType.Element)
                        if(xr.Name == "HelpAttributes")
                            helpAttributes.ReadXml(xr);
                        else
                            if(xr.Name == "HelpKeywords")
                                keywords.ReadXml(xr);
                            else
                                if(xr.Name == "Topic")
                                {
                                    newTopic = new Topic();
                                    newTopic.ReadXml(xr);
                                    this.Subtopics.Add(newTopic);
                                }
                }
        }
        /// <summary>
        /// Load the tree view with the topics and set the form up to edit them
        /// </summary>
        /// <param name="selectedEntry">If not null, the node containing the
        /// specified entry is set as the selected node.  If null, the first
        /// node is selected.</param>
        private void LoadTopics(Topic selectedEntry)
        {
            TreeNode node;
            Topic defTopic = topics.DefaultTopic, apiTopic = topics.ApiContentInsertionPoint,
                rootContainer = topics.MSHVRootContentContainer;

            try
            {
                tvContent.SuspendLayout();
                tvContent.Nodes.Clear();

                defaultNode = apiInsertionNode = rootContainerNode = firstNode = null;
                firstSelection = selectedEntry;

                if(topics.Count != 0)
                {
                    foreach(Topic t in topics)
                    {
                        node = tvContent.Nodes.Add(t.DisplayTitle);
                        node.Name = t.Id;
                        node.Tag = t;

                        if(t == defTopic)
                            defaultNode = node;

                        if(t == apiTopic)
                            apiInsertionNode = node;

                        if(t == rootContainer)
                            rootContainerNode = node;

                        if(t == firstSelection)
                            firstNode = node;

                        if(t.Subtopics.Count != 0)
                            this.AddChildren(t.Subtopics, node);
                    }

                    this.UpdateDefaultAndApiNodeImages();
                    tvContent.ExpandAll();

                    if(firstNode != null)
                    {
                        tvContent.SelectedNode = firstNode;
                        firstNode.EnsureVisible();
                    }
                    else
                    {
                        tvContent.SelectedNode = tvContent.Nodes[0];
                        tvContent.SelectedNode.EnsureVisible();
                    }
                }
                else
                    this.UpdateControlStatus();
            }
            finally
            {
                tvContent.ResumeLayout();
            }
        }
        /// <summary>
        /// Add an empty container node that is not associated with any topic
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">The event arguments</param>
        private void tsbAddTopic_ButtonClick(object sender, EventArgs e)
        {
            ToolStripItem tiAdd = (ToolStripItem)sender;
            Topic topic, parentTopic;
            TreeNode tnNew, tnParent;

            topic = new Topic();
            topic.Title = "Table of Contents Container";
            topic.TopicFile = null;
            tnNew = new TreeNode(topic.DisplayTitle);
            tnNew.Name = topic.Id;
            tnNew.Tag = topic;

            if(tiAdd == tsbAddChildTopic || tiAdd.Owner == cmsNewChildTopic)
            {
                tvContent.SelectedNode.Nodes.Add(tnNew);
                parentTopic = (Topic)tvContent.SelectedNode.Tag;
                parentTopic.Subtopics.Add(topic);
            }
            else
                if(tvContent.SelectedNode == null)
                {
                    tvContent.Nodes.Add(tnNew);
                    topics.Add(topic);
                }
                else
                {
                    if(tvContent.SelectedNode.Parent == null)
                        tvContent.Nodes.Insert(tvContent.Nodes.IndexOf(
                            tvContent.SelectedNode) + 1, tnNew);
                    else
                    {
                        tnParent = tvContent.SelectedNode.Parent;
                        tnParent.Nodes.Insert(tnParent.Nodes.IndexOf(
                            tvContent.SelectedNode) + 1, tnNew);
                    }

                    parentTopic = (Topic)tvContent.SelectedNode.Tag;
                    parentTopic.Parent.Insert(
                        parentTopic.Parent.IndexOf(parentTopic) + 1,
                        topic);
                }

            tvContent.SelectedNode = tnNew;
        }
        /// <summary>
        /// Paste the selected topic as a sibling or child of the selected topic
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">The event arguments</param>
        private void cmdPaste_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            Topic targetTopic = this.CurrentTopic, newTopic = clipboardTopic;

            if(newTopic != null)
            {
                // Don't allow pasting multiple copies of the same item in here as the IDs must be unique
                clipboardTopic = null;

                if(targetTopic == null)
                    topics.Add(newTopic);
                else
                {
                    if(e.Command == EditorCommands.PasteAsChild)
                    {
                        targetTopic.Subtopics.Add(newTopic);
                        targetTopic.IsExpanded = true;
                    }
                    else
                        targetTopic.Parent.Insert(targetTopic.Parent.IndexOf(targetTopic) + 1, newTopic);
                }

                newTopic.IsSelected = true;
                tvContent.Focus();
            }
        }
        /// <summary>
        /// Add a new topic file
        /// </summary>
        /// <param name="filename">The filename of the topic to add</param>
        /// <param name="addAsChild">True to add as a child of the selected
        /// node or false to add it as a sibling.</param>
        private void AddTopicFile(string filename, bool addAsChild)
        {
            Topic topic, parentTopic;
            TreeNode tnNew, tnParent;
            string newPath = filename, projectPath = Path.GetDirectoryName(
                topics.FileItem.ProjectElement.Project.Filename);

            // The file must reside under the project path
            if(!Path.GetDirectoryName(filename).StartsWith(projectPath,
              StringComparison.OrdinalIgnoreCase))
                newPath = Path.Combine(projectPath, Path.GetFileName(filename));

            // Add the file to the project
            FileItem newItem = topics.FileItem.ProjectElement.Project.AddFileToProject(
                filename, newPath);
            topic = new Topic();
            topic.TopicFile = new TopicFile(newItem);

            tnNew = new TreeNode(topic.DisplayTitle);
            tnNew.Name = topic.Id;
            tnNew.Tag = topic;

            if(addAsChild)
            {
                tvContent.SelectedNode.Nodes.Add(tnNew);
                parentTopic = (Topic)tvContent.SelectedNode.Tag;
                parentTopic.Subtopics.Add(topic);
            }
            else
                if(tvContent.SelectedNode == null)
                {
                    tvContent.Nodes.Add(tnNew);
                    topics.Add(topic);
                }
                else
                {
                    if(tvContent.SelectedNode.Parent == null)
                        tvContent.Nodes.Insert(tvContent.Nodes.IndexOf(
                            tvContent.SelectedNode) + 1, tnNew);
                    else
                    {
                        tnParent = tvContent.SelectedNode.Parent;
                        tnParent.Nodes.Insert(tnParent.Nodes.IndexOf(
                            tvContent.SelectedNode) + 1, tnNew);
                    }

                    parentTopic = (Topic)tvContent.SelectedNode.Tag;
                    parentTopic.Parent.Insert(
                        parentTopic.Parent.IndexOf(parentTopic) + 1,
                        topic);
                }

            tvContent.SelectedNode = tnNew;
        }
        /// <summary>
        /// Cut the selected topic to the internal clipboard
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">The event arguments</param>
        private void cmdCut_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            clipboardTopic = this.CurrentTopic;

            if(clipboardTopic != null)
            {
                clipboardTopic.Parent.Remove(clipboardTopic);
                tvContent.Focus();
            }
        }
        //=====================================================================

        /// <summary>
        /// Add an empty container topic to the collection that is not associated with any file
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">The event arguments</param>
        private void cmdAddItem_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            Topic currentTopic = this.CurrentTopic,
                newTopic = new Topic
                {
                    Title = "Table of Contents Container",
                    TopicFile = null,   // Assign a default GUID
                };

            // If the command parameter is null, add it as a sibling.  If not, add it as a child.
            if(e.Parameter == null || currentTopic == null)
            {
                if(currentTopic == null || topics.Count == 0)
                    topics.Add(newTopic);
                else
                    currentTopic.Parent.Insert(currentTopic.Parent.IndexOf(currentTopic) + 1, newTopic);
            }
            else
            {
                currentTopic.Subtopics.Add(newTopic);
                currentTopic.IsExpanded = true;
            }

            newTopic.IsSelected = true;
        }
        /// <summary>
        /// Import attribute information from a companion file
        /// </summary>
        /// <param name="filename">The companion filename</param>
        private void ImportCompanionFileInfo(string filename)
        {
            XPathDocument info = new XPathDocument(filename);
            XPathNavigator navTopics = info.CreateNavigator();
            Topic t;

            foreach(XPathNavigator topic in navTopics.Select("metadata/topic"))
            {
                if(!topicSettings.TryGetValue(topic.GetAttribute("id",
                  String.Empty), out t))
                {
                    t = new Topic();
                    topicSettings.Add(topic.GetAttribute("id", String.Empty), t);
                }

                foreach(XPathNavigator attr in topic.Select("*"))
                    switch(attr.Name)
                    {
                        case "title":
                            t.Title = attr.Value;
                            break;

                        case "tableOfContentsTitle":
                            t.TocTitle = attr.Value;
                            break;

                        case "attribute":
                            t.HelpAttributes.Add(attr.GetAttribute("name",
                                String.Empty), attr.Value);
                            break;

                        default:
                            break;
                    }
            }
        }
        /// <summary>
        /// Topic settings were found but no content layout file.  In such
        /// cases, this is called to create a default content layout file
        /// based on the settings alone.
        /// </summary>
        private void CreateDefaultContentLayoutFile()
        {
            string filename = Path.Combine(base.ProjectFolder,
                "ContentLayout.content");
            Topic commonSettings, t;

            if(!topicSettings.TryGetValue("*", out commonSettings))
                commonSettings = new Topic();
            else
                topicSettings.Remove("*");

            if(topicSettings.Count == 0)
                return;

            XmlWriterSettings settings = new XmlWriterSettings();
            XmlWriter writer = null;

            try
            {
                settings.Indent = true;
                settings.CloseOutput = true;
                writer = XmlWriter.Create(filename, settings);

                writer.WriteStartDocument();
                writer.WriteStartElement("Topics");

                foreach(string key in topicSettings.Keys)
                {
                    t = topicSettings[key];

                    foreach(MSHelpKeyword kw in commonSettings.Keywords)
                        t.Keywords.Add(kw);

                    writer.WriteStartElement("Topic");
                    writer.WriteAttributeString("id", key);
                    writer.WriteAttributeString("visible", "true");

                    if(!String.IsNullOrEmpty(t.Title))
                        writer.WriteAttributeString("title", t.Title);

                    if(!String.IsNullOrEmpty(t.TocTitle) && t.TocTitle != t.Title)
                        writer.WriteAttributeString("tocTitle", t.TocTitle);

                    if(!String.IsNullOrEmpty(t.LinkText))
                        writer.WriteAttributeString("linkText", t.LinkText);

                    if(t.HelpAttributes.Count != 0)
                        t.HelpAttributes.WriteXml(writer, true);

                    if(t.Keywords.Count != 0)
                        t.Keywords.WriteXml(writer);

                    writer.WriteEndElement();
                }

                writer.WriteEndElement();
                writer.WriteEndDocument();
            }
            finally
            {
                if(writer != null)
                    writer.Close();
            }

            project.AddFileToProject(filename, filename);
        }
Beispiel #11
0
        /// <summary>
        /// Insert a link to a topic
        /// </summary>
        /// <param name="extension">The extension of the file in which the
        /// link is being inserted.</param>
        /// <param name="topic">The topic for which to create a link</param>
        /// <remarks>If dropped inside some selected text, the link will
        /// wrap the selected text.</remarks>
        private void InsertTopicLink(string extension, Topic topic)
        {
            TextArea textArea = editor.ActiveTextAreaControl.TextArea;
            int offset = textArea.Caret.Offset;
            string selectedText;

            if(textArea.SelectionManager.HasSomethingSelected &&
              textArea.SelectionManager.SelectionCollection[0].ContainsOffset(offset))
                selectedText = textArea.SelectionManager.SelectionCollection[0].SelectedText;
            else
                selectedText = String.Empty;

            if(extension == ".htm" || extension == ".html")
                ContentEditorControl.InsertString(textArea, topic.ToAnchor(selectedText));
            else
                ContentEditorControl.InsertString(textArea, topic.ToLink(selectedText));
        }