/// <summary> /// If a node is double-clicked, paste it into the active editor window /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void tvEntities_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) { DataObject msg; string text; this.DockPanel.CheckFocusedContent(); // HACK TopicEditorWindow topic = this.DockPanel.ActiveDocument as TopicEditorWindow; if (e.Node != null && e.Node.Tag != null && topic != null) { msg = new DataObject(); clipboard = null; switch ((EntityType)cboContentType.SelectedIndex) { case EntityType.Tokens: text = ((Token)e.Node.Tag).ToToken(); break; case EntityType.Images: clipboard = e.Node.Tag; text = ((ImageReference)clipboard).ToMediaLink(); // Add it in its native form too so that the user has // a choice of styles when pasted into a topic editor. msg.SetData(typeof(ClipboardDataHandler), new ClipboardDataHandler(GetClipboardData)); break; case EntityType.CodeSnippets: text = ((CodeReference)e.Node.Tag).ToCodeReference(); break; default: clipboard = e.Node.Tag; text = ((CodeEntityReference)clipboard).ToCodeEntityReference(); // Add it in its native form too so that the user has // a choice of styles when pasted into a topic editor. msg.SetData(typeof(ClipboardDataHandler), new ClipboardDataHandler(GetClipboardData)); break; } msg.SetData(DataFormats.Text, text); Clipboard.SetDataObject(msg, false); topic.PasteFromClipboard(); } }
/// <summary> /// When the current topic window closes, disconnect from it /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void SpellCheckWindow_CurrentTopicClosed(object sender, EventArgs e) { if (currentTopicWindow != null) { currentTopicWindow.FormClosed -= SpellCheckWindow_CurrentTopicClosed; } currentTopicWindow = null; issues.Clear(); this.UpdateState(); lblMisspelledWord.Text = null; }
/// <summary> /// Edit the selected file for editing /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void cmdEdit_Executed(object sender, ExecutedRoutedEventArgs e) { // If the sender is a topic, use that instead. Due to the way the WPF tree view works, the // selected topic isn't always the one we just added when it's the first child of a parent topic. Topic t = sender as Topic; if (t == null) { t = ucContentLayoutEditor.CurrentTopic; } if (t.TopicFile != null) { string fullName = t.TopicFile.FullPath; // If the document is already open, just activate it foreach (IDockContent content in this.DockPanel.Documents) { if (String.Compare(content.DockHandler.ToolTipText, fullName, true, CultureInfo.CurrentCulture) == 0) { content.DockHandler.Activate(); return; } } if (File.Exists(fullName)) { TopicEditorWindow editor = new TopicEditorWindow(fullName); editor.Show(this.DockPanel); } else { WinFormsMessageBox.Show("File does not exist: " + fullName, Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); } } else { WinFormsMessageBox.Show("No file is associated with this topic", Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); } }
/// <summary> /// Get the active document window /// </summary> /// <returns>The active topic editor window or null if not found</returns> private TopicEditorWindow FindActiveDocumentWindow() { TopicEditorWindow topicWindow = this.DockPanel.ActiveDocument as TopicEditorWindow; if (topicWindow == null) { foreach (IDockContent content in this.DockPanel.Documents) { topicWindow = content as TopicEditorWindow; if (topicWindow != null) { break; } } } return(topicWindow); }
/// <summary> /// Find and replace all occurrences of the search text /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void btnReplaceAll_Click(object sender, EventArgs e) { TopicEditorWindow topicWindow = this.FindActiveDocumentWindow(); epErrors.Clear(); if (txtFindText.Text.Length == 0) { epErrors.SetError(txtFindText, "Enter some text to find"); return; } if (topicWindow != null) { if (!topicWindow.ReplaceAll(txtFindText.Text, txtReplaceWith.Text, chkCaseSensitive.Checked)) { MessageBox.Show("The specified text was not found", Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } }
/// <summary> /// Open the selected file for editing /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void cmdEdit_Executed(object sender, ExecutedRoutedEventArgs e) { TocEntry t = ucTopicPreviewer.CurrentTopic; if (t.SourceFile.Exists) { string fullName = t.SourceFile; // If the document is already open, just activate it foreach (IDockContent content in this.DockPanel.Documents) { if (String.Compare(content.DockHandler.ToolTipText, fullName, true, CultureInfo.CurrentCulture) == 0) { content.DockHandler.Activate(); return; } } if (File.Exists(fullName)) { TopicEditorWindow editor = new TopicEditorWindow(fullName); editor.Show(this.DockPanel); } else { WinFormsMessageBox.Show("File does not exist: " + fullName, Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); } } else { WinFormsMessageBox.Show("No file is associated with this topic", Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); } }
/// <summary> /// Edit the selected file for editing /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void cmdEdit_Executed(object sender, ExecutedRoutedEventArgs e) { // If the sender is a topic, use that instead. Due to the way the WPF tree view works, the // selected topic isn't always the one we just added when it's the first child of a parent topic. TocEntry t = sender as TocEntry; if(t == null) t = ucSiteMapEditor.CurrentTopic; if(t.SourceFile.Path.Length != 0) { string fullName = t.SourceFile; // If the document is already open, just activate it foreach(IDockContent content in this.DockPanel.Documents) if(String.Compare(content.DockHandler.ToolTipText, fullName, true, CultureInfo.CurrentCulture) == 0) { content.DockHandler.Activate(); return; } if(File.Exists(fullName)) { TopicEditorWindow editor = new TopicEditorWindow(fullName); editor.Show(this.DockPanel); } else WinFormsMessageBox.Show("File does not exist: " + fullName, Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); } else WinFormsMessageBox.Show("No file is associated with this topic", Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); }
/// <summary> /// Edit the selected topic file /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void tsbEditTopic_Click(object sender, EventArgs e) { Topic t = (Topic)tvContent.SelectedNode.Tag; if(t.TopicFile != null) { string fullName = t.TopicFile.FullPath; // If the document is already open, just activate it foreach(IDockContent content in this.DockPanel.Documents) if(String.Compare(content.DockHandler.ToolTipText, fullName, true, CultureInfo.CurrentCulture) == 0) { content.DockHandler.Activate(); return; } if(File.Exists(fullName)) { TopicEditorWindow editor = new TopicEditorWindow(fullName); editor.Show(this.DockPanel); } else MessageBox.Show("File does not exist: " + fullName, Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); } else MessageBox.Show("No file is associated with this entry", Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); }
/// <summary> /// Open the selected file for editing /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void cmdEdit_Executed(object sender, ExecutedRoutedEventArgs e) { TocEntry t = ucTopicPreviewer.CurrentTopic; if(t.SourceFile.Exists) { string fullName = t.SourceFile; // If the document is already open, just activate it foreach(IDockContent content in this.DockPanel.Documents) if(String.Compare(content.DockHandler.ToolTipText, fullName, true, CultureInfo.CurrentCulture) == 0) { content.DockHandler.Activate(); return; } if(File.Exists(fullName)) { TopicEditorWindow editor = new TopicEditorWindow(fullName); editor.Show(this.DockPanel); } else WinFormsMessageBox.Show("File does not exist: " + fullName, Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); } else WinFormsMessageBox.Show("No file is associated with this topic", Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); }
/// <summary> /// Create an editor for the specified file /// </summary> /// <param name="fullName">The full path to the file</param> /// <param name="fileItem">The project file item or null if the method should find it for itself</param> /// <returns>The editor window created for the file</returns> public DockContent CreateFileEditor(string fullName, FileItem fileItem) { DockContent editor = null; string ext = Path.GetExtension(fullName).ToLowerInvariant(); if(fileItem == null) { if(this.CurrentProject != null) fileItem = this.CurrentProject.FindFile(fullName); if(fileItem == null) return null; } if(!File.Exists(fullName)) return null; // Try for a built in editor switch(SandcastleProject.DefaultBuildAction(fullName)) { case BuildAction.None: case BuildAction.Content: switch(ext) { case ".aml": case ".asp": case ".aspx": case ".ascx": case ".cmp": case ".config": case ".css": case ".htm": case ".html": case ".js": case ".log": case ".topic": case ".txt": case ".xml": editor = new TopicEditorWindow(fullName); break; default: break; } break; case BuildAction.CodeSnippets: case BuildAction.TopicTransform: case BuildAction.XamlConfiguration: editor = new TopicEditorWindow(fullName); break; case BuildAction.ContentLayout: editor = new ContentLayoutWindow(fileItem); break; case BuildAction.ResourceItems: // The content of the resource items could be bad (ill-formed XML) so edit as text if it // cannot be loaded using the default editor. try { editor = new ResourceItemEditorWindow(fileItem); } catch(Exception ex) { System.Diagnostics.Debug.WriteLine(ex); MessageBox.Show("Unable to load file using the resource item editor: " + ex.Message + "\r\n\r\nThe file will be opened using the standard text editor.", Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); editor = new TopicEditorWindow(fullName); } break; case BuildAction.SiteMap: editor = new SiteMapEditorWindow(fileItem); break; case BuildAction.Tokens: // The content of the tokens could be bad (ill-formed XML) so edit as text if it cannot be // loaded using the default editor. try { editor = new TokenEditorWindow(fileItem); } catch(Exception ex) { System.Diagnostics.Debug.WriteLine(ex); MessageBox.Show("Unable to load file using the token editor: " + ex.Message + "\r\n\r\nThe file will be opened using the standard text editor.", Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); editor = new TopicEditorWindow(fullName); } break; default: // No association, the caller may try to launch an external editor break; } // If we couldn't create one and it looks like a text file, use the topic editor if(editor == null) try { if(!reBinary.IsMatch(File.ReadAllText(fullName))) editor = new TopicEditorWindow(fullName); } catch(Exception ex) { System.Diagnostics.Debug.WriteLine(ex); } return editor; }
/// <summary> /// Open the file for editing using the text editor if possible /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void miOpenWithTextEditor_Click(object sender, EventArgs e) { NodeData nodeData = (NodeData)tvProjectFiles.SelectedNode.Tag; DockContent editor; FileItem fileItem; string fullName; if(nodeData.BuildAction >= BuildAction.Folder) return; fileItem = (FileItem)nodeData.Item; fullName = fileItem.Include; // If the document is already open, just activate it foreach(IDockContent content in this.DockPanel.Contents) if(String.Compare(content.DockHandler.ToolTipText, fullName, true, CultureInfo.CurrentCulture) == 0) { content.DockHandler.Activate(); return; } if(!File.Exists(fullName)) { MessageBox.Show("File does not exist: " + fullName, Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } try { if(!reBinary.IsMatch(File.ReadAllText(fullName))) { editor = new TopicEditorWindow(fullName); editor.Show(this.DockPanel); } else MessageBox.Show("The selected file does not appear to be a text file. Use the Open " + "option instead to open the default editor", Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); } catch(Exception ex) { System.Diagnostics.Debug.WriteLine(ex); MessageBox.Show("Unable to create text editor: " + ex.Message, Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); } }
/// <summary> /// When the parent is activated, make sure we're still spell checking the same document. If not, /// spell check the new one if there is one. /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void SpellCheckWindow_ParentActivatedChanged(object sender, EventArgs e) { if(!currentParent.IsActivated) return; // When floating, force the parent window to show the entire control if(this.DockState == DockState.Float && (this.Parent.Parent.Size.Width < this.Size.Width || this.Parent.Parent.Size.Height < this.Size.Height)) this.Parent.Parent.Size = new Size(this.Size.Width + 20, this.Size.Height + 20); var activeWindow = this.FindActiveDocumentWindow(); if(activeWindow != currentTopicWindow) { issues.Clear(); this.UpdateState(); lblMisspelledWord.Text = null; currentTopicWindow = activeWindow; if(currentTopicWindow != null) { currentTopicWindow.FormClosed += SpellCheckWindow_CurrentTopicClosed; if(this.SpellCheckCurrentDocument()) this.UpdateState(); } } }
/// <summary> /// When the current topic window closes, disconnect from it /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void SpellCheckWindow_CurrentTopicClosed(object sender, EventArgs e) { if(currentTopicWindow != null) currentTopicWindow.FormClosed -= SpellCheckWindow_CurrentTopicClosed; currentTopicWindow = null; issues.Clear(); this.UpdateState(); lblMisspelledWord.Text = null; }
/// <summary> /// Edit the selected node's file if possible /// </summary> /// <param name="node">The node to edit</param> private void EditNodeFile(TreeNode node) { NodeData nodeData = (NodeData)node.Tag; DockContent editor = null; FileItem fileItem; string fullName, ext; if(nodeData.BuildAction >= BuildAction.Folder) return; fileItem = (FileItem)nodeData.Item; fullName = fileItem.Include; ext = Path.GetExtension(fullName).ToLower(CultureInfo.InvariantCulture); // If the document is already open, just activate it foreach(IDockContent content in this.DockPanel.Contents) if(String.Compare(content.DockHandler.ToolTipText, fullName, true, CultureInfo.CurrentCulture) == 0) { content.DockHandler.Activate(); return; } if(!File.Exists(fullName)) { MessageBox.Show("File does not exist: " + fullName, Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // Give preference to the external editors if any are defined foreach(ContentFileEditor fileEditor in ContentFileEditorCollection.GlobalEditors) if(fileEditor.IsEditorFor(ext)) if(ContentFileEditorCollection.GlobalEditors.LaunchEditorFor( fullName, currentProject.Filename)) return; // Try for a built in editor switch(SandcastleProject.DefaultBuildAction(fullName)) { case BuildAction.None: case BuildAction.Content: switch(ext) { case ".aml": case ".asp": case ".aspx": case ".ascx": case ".cmp": case ".config": case ".css": case ".htm": case ".html": case ".items": case ".js": case ".log": case ".snippets": case ".topic": case ".tokens": case ".txt": case ".xml": editor = new TopicEditorWindow(fullName); break; default: break; } break; case BuildAction.CodeSnippets: case BuildAction.TopicTransform: editor = new TopicEditorWindow(fullName); break; case BuildAction.ContentLayout: editor = new ContentLayoutWindow(fileItem); break; case BuildAction.ResourceItems: // The content of the resource items could be bad // (ill-formed XML) so edit as text if it cannot be // loaded using the default editor. try { editor = new ResourceItemEditorWindow(fileItem); } catch(Exception ex) { System.Diagnostics.Debug.WriteLine(ex); MessageBox.Show("Unable to load file using the " + "resource item editor: " + ex.Message + "\r\n\r\nThe file " + "will be opened using the standard text editor", Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); editor = new TopicEditorWindow(fullName); } break; case BuildAction.SiteMap: editor = new SiteMapEditorWindow(fileItem); break; case BuildAction.Tokens: // The content of the tokens could be bad (ill-formed XML) // so edit as text if it cannot be loaded using the default // editor. try { editor = new TokenEditorWindow(fileItem); } catch(Exception ex) { System.Diagnostics.Debug.WriteLine(ex); MessageBox.Show("Unable to load file using the " + "token editor: " + ex.Message + "\r\n\r\nThe file " + "will be opened using the standard text editor", Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); editor = new TopicEditorWindow(fullName); } break; default: // Try to launch an external editor break; } if(editor != null) editor.Show(this.DockPanel); else if(!ContentFileEditorCollection.GlobalEditors.LaunchEditorFor( fullName, currentProject.Filename)) MessageBox.Show(String.Format(CultureInfo.CurrentCulture, "Unable to launch '{0}' for editing. Reason: {1}", fullName, ContentFileEditorCollection.GlobalEditors.LastError.Message), Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error); }