/// <summary> /// Resumes file change notifications to the environment for the wrapped file. /// </summary> public void Resume() { if (!this.suspended) { return; } // Get the environment's change notifier. IVsFileChangeEx changeNotifier = Package.Instance.Context.GetService(typeof(SVsFileChangeEx)) as IVsFileChangeEx; Tracer.WriteLineIf(classType, "Resume", Tracer.Level.Warning, changeNotifier == null, "Could not get an instance of the IVsChangeEx interface."); if (changeNotifier != null) { // Tell the environment to resume sending change notifications for the file. int hr = changeNotifier.IgnoreFile(0, this.FilePath, ResumeNotification); Tracer.WriteLineIf(classType, "Resume", Tracer.Level.Warning, NativeMethods.Failed(hr), "Could not tell the environment to resume file change notifications to '{0}': Hr=0x{1:x}", this.FilePath, hr); } // Tell the environment to resume sending change notifications to editors. if (this.docDataFileChangeControl != null) { int hr = this.docDataFileChangeControl.IgnoreFileChanges(ResumeNotification); Tracer.WriteLineIf(classType, "Resume", Tracer.Level.Warning, NativeMethods.Failed(hr), "Could not tell the environment to resume file change notifications to editors of file '{0}': Hr=0x{1:x}", this.FilePath, hr); this.docDataFileChangeControl = null; } // At this point we can consider ourself resumed. this.suspended = false; Tracer.WriteLineVerbose(classType, "Resume", "Resumed file change notifications for '{0}'.", this.FilePath); }
/// <summary> /// The environment calls this to set the currently selected objects that the property page should show. /// </summary> /// <param name="cObjects">The count of elements in <paramref name="ppunk"/>.</param> /// <param name="ppunk">An array of <b>IUnknown</b> objects to show in the property page.</param> /// <remarks> /// We are supposed to cache these objects until we get another call with <paramref name="cObjects"/> = 0. /// Also, the environment is supposed to call this before calling <see cref="IPropertyPage.Activate"/>, /// but like all things when interacting with Visual Studio, don't trust that and code defensively. /// </remarks> void IPropertyPage.SetObjects(uint cObjects, object[] ppunk) { if (ppunk == null || ppunk.Length == 0 || cObjects == 0) { this.project = null; this.UnbindObject(); return; } // Check the incoming parameters Tracer.WriteLineIf(classType, "IPropertyPage.SetObjects", Tracer.Level.Verbose, cObjects != ppunk.Length, "Visual Studio passed us a ppunk array of size {0} but the count is {1}.", ppunk.Length, cObjects); // We get called when the user selects "Properties" from the context menu on the project node if (ppunk[0] is NodeProperties) { if (this.project == null) { this.project = ((NodeProperties)ppunk[0]).Node.Hierarchy.AttachedProject; } } // Refresh the page with the new settings if (this.Project != null) { this.BindObject(); } }
/// <summary> /// Makes the property page dialog box visible or invisible according to the <paramref name="nCmdShow"/> /// parameter. If the page is made visible, the page should set the focus to itself, specifically to the /// first property on the page. /// </summary> /// <param name="nCmdShow"> /// Command describing whether to become visible (SW_SHOW or SW_SHOWNORMAL) or hidden (SW_HIDE). No other values are valid for this parameter. /// </param> void IPropertyPage.Show(uint nCmdShow) { if (this.Panel != null) { if (nCmdShow == NativeMethods.SW_HIDE) { this.Panel.Hide(); } else { Tracer.WriteLineIf(classType, "IPropertyPage.Show", Tracer.Level.Verbose, nCmdShow == NativeMethods.SW_SHOW || nCmdShow == NativeMethods.SW_SHOWNORMAL, "VS passed us an invalid nCmdShow: {0}. Defaulting to SW_SHOW.", nCmdShow); this.Panel.Show(); } } }
/// <summary> /// Saves the document if it is dirty. /// </summary> /// <param name="filePath">The absolute path to the file.</param> public void SaveIfDirty(string filePath) { DocumentInfo docInfo = this.FindByPath(filePath); if (docInfo != null && docInfo.IsDirty && docInfo.SupportsInterface(typeof(IVsPersistDocData))) { string newPath; int saveCanceled; IVsPersistDocData persistDocData = docInfo.DocumentData as IVsPersistDocData; Tracer.Assert(persistDocData != null, "DocumentInfo.SupportsInterface returned true when it shouldn't have."); if (persistDocData != null) { int hr = persistDocData.SaveDocData(VSSAVEFLAGS.VSSAVE_SilentSave, out newPath, out saveCanceled); Tracer.WriteLineIf(classType, "SaveIfDirty", Tracer.Level.Information, NativeMethods.Succeeded(hr), "Successfully saved '{0}'.", filePath); NativeMethods.ThrowOnFailure(hr); } } }
/// <summary> /// Suspends any file change notifications to the environment for the wrapped file in /// preparation for a multi-stage file operation such as a rename. /// </summary> public void Suspend() { // We only want to suspend once. if (this.suspended) { return; } // Get the environment's change notifier. IVsFileChangeEx changeNotifier = Package.Instance.Context.GetService(typeof(SVsFileChangeEx)) as IVsFileChangeEx; if (changeNotifier == null) { Tracer.WriteLineWarning(classType, "Suspend", "Could not get an instance of the IVsChangeEx interface."); return; } // Tell the environment to stop sending change notifications for the file. int hr = changeNotifier.IgnoreFile(0, this.FilePath, IgnoreChanges); Tracer.WriteLineIf(classType, "Suspend", Tracer.Level.Warning, NativeMethods.Failed(hr), "Could not tell the environment to ignore file changes to '{0}': Hr=0x{1:x}", this.FilePath, hr); NativeMethods.ThrowOnFailure(hr); // Get the IVsDocDataFileChangeControl interface from the DocumentData. We need this // to suspend file change notifications to all editors. DocumentInfo docInfo = Package.Instance.Context.RunningDocumentTable.FindByPath(this.FilePath); if (docInfo != null) { this.docDataFileChangeControl = docInfo.DocumentData as IVsDocDataFileChangeControl; if (this.docDataFileChangeControl != null) { hr = this.docDataFileChangeControl.IgnoreFileChanges(IgnoreChanges); NativeMethods.ThrowOnFailure(hr); } } // At this point we can consider ourself suspended. this.suspended = true; Tracer.WriteLineVerbose(classType, "Suspend", "Suspended file change notifications for '{0}'.", this.FilePath); }
//========================================================================================== // Constructors //========================================================================================== /// <summary> /// Initializes a new instance of the <see cref="Package"/> class. /// </summary> public Package() { Tracer.WriteLineIf(classType, Tracer.ConstructorMethodName, Tracer.Level.Warning, Instance != null, "There is more than one Package instance. There should only be one."); instance = this; }