Replaced the old VS templates with ones that offer more flexiblity. Started replacing the Content Project for the samples with our custom project type. Inlcuded a basic not yet working AssimpImporter.
321 lines
14 KiB
C#
321 lines
14 KiB
C#
/* ****************************************************************************
|
|
*
|
|
* Copyright (c) Microsoft Corporation.
|
|
*
|
|
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
|
|
* copy of the license can be found in the License.html file at the root of this distribution. If
|
|
* you cannot locate the Apache License, Version 2.0, please send an email to
|
|
* vspython@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
|
|
* by the terms of the Apache License, Version 2.0.
|
|
*
|
|
* You must not remove this notice, or any other, from this software.
|
|
*
|
|
* ***************************************************************************/
|
|
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using EnvDTE;
|
|
using Microsoft.VisualStudio;
|
|
using Microsoft.VisualStudio.Shell;
|
|
using Microsoft.VisualStudio.Shell.Interop;
|
|
using VSConstants = Microsoft.VisualStudio.VSConstants;
|
|
|
|
namespace Microsoft.VisualStudio.Project.Automation {
|
|
/// <summary>
|
|
/// Represents an automation object for a file in a project
|
|
/// </summary>
|
|
[SuppressMessage("Microsoft.Interoperability", "CA1405:ComVisibleTypeBaseTypesShouldBeComVisible")]
|
|
[ComVisible(true)]
|
|
public class OAFileItem : OAProjectItem {
|
|
#region ctors
|
|
public OAFileItem(OAProject project, FileNode node)
|
|
: base(project, node) {
|
|
}
|
|
|
|
#endregion
|
|
|
|
private new FileNode Node {
|
|
get {
|
|
return (FileNode)base.Node;
|
|
}
|
|
}
|
|
|
|
public override string Name {
|
|
get {
|
|
return this.Node.FileName;
|
|
}
|
|
set {
|
|
UIThread.Instance.RunSync(() =>
|
|
base.Name = value);
|
|
}
|
|
}
|
|
|
|
#region overridden methods
|
|
/// <summary>
|
|
/// Returns the dirty state of the document.
|
|
/// </summary>
|
|
/// <exception cref="InvalidOperationException">Is thrown if the project is closed or it the service provider attached to the project is invalid.</exception>
|
|
/// <exception cref="ComException">Is thrown if the dirty state cannot be retrived.</exception>
|
|
public override bool IsDirty {
|
|
get {
|
|
CheckProjectIsValid();
|
|
|
|
bool isDirty = false;
|
|
|
|
using (AutomationScope scope = new AutomationScope(this.Node.ProjectMgr.Site)) {
|
|
UIThread.Instance.RunSync(() => {
|
|
DocumentManager manager = this.Node.GetDocumentManager();
|
|
VsUtilities.CheckNotNull(manager);
|
|
|
|
bool isOpen, isOpenedByUs;
|
|
uint docCookie;
|
|
IVsPersistDocData persistDocData;
|
|
manager.GetDocInfo(out isOpen, out isDirty, out isOpenedByUs, out docCookie, out persistDocData);
|
|
});
|
|
}
|
|
return isDirty;
|
|
}
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the Document associated with the item, if one exists.
|
|
/// </summary>
|
|
public override EnvDTE.Document Document {
|
|
get {
|
|
CheckProjectIsValid();
|
|
|
|
EnvDTE.Document document = null;
|
|
|
|
using (AutomationScope scope = new AutomationScope(this.Node.ProjectMgr.Site)) {
|
|
UIThread.Instance.RunSync(() => {
|
|
IVsUIHierarchy hier;
|
|
uint itemid;
|
|
|
|
IVsWindowFrame windowFrame;
|
|
|
|
VsShellUtilities.IsDocumentOpen(this.Node.ProjectMgr.Site, this.Node.Url, VSConstants.LOGVIEWID_Any, out hier, out itemid, out windowFrame);
|
|
|
|
if (windowFrame != null) {
|
|
object var;
|
|
ErrorHandler.ThrowOnFailure(windowFrame.GetProperty((int)__VSFPROPID.VSFPROPID_DocCookie, out var));
|
|
object documentAsObject;
|
|
ErrorHandler.ThrowOnFailure(scope.Extensibility.GetDocumentFromDocCookie((int)var, out documentAsObject));
|
|
VsUtilities.CheckNotNull(documentAsObject);
|
|
|
|
document = (Document)documentAsObject;
|
|
}
|
|
});
|
|
}
|
|
|
|
return document;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Opens the file item in the specified view.
|
|
/// </summary>
|
|
/// <param name="ViewKind">Specifies the view kind in which to open the item (file)</param>
|
|
/// <returns>Window object</returns>
|
|
public override EnvDTE.Window Open(string viewKind) {
|
|
CheckProjectIsValid();
|
|
|
|
IVsWindowFrame windowFrame = null;
|
|
IntPtr docData = IntPtr.Zero;
|
|
|
|
using (AutomationScope scope = new AutomationScope(this.Node.ProjectMgr.Site)) {
|
|
UIThread.Instance.RunSync(() => {
|
|
try {
|
|
// Validate input params
|
|
Guid logicalViewGuid = VSConstants.LOGVIEWID_Primary;
|
|
try {
|
|
if (!(String.IsNullOrEmpty(viewKind))) {
|
|
logicalViewGuid = new Guid(viewKind);
|
|
}
|
|
} catch (FormatException) {
|
|
// Not a valid guid
|
|
throw new ArgumentException(SR.GetString(SR.ParameterMustBeAValidGuid, CultureInfo.CurrentUICulture), "viewKind");
|
|
}
|
|
|
|
uint itemid;
|
|
IVsHierarchy ivsHierarchy;
|
|
uint docCookie;
|
|
IVsRunningDocumentTable rdt = this.Node.ProjectMgr.Site.GetService(typeof(SVsRunningDocumentTable)) as IVsRunningDocumentTable;
|
|
Debug.Assert(rdt != null, " Could not get running document table from the services exposed by this project");
|
|
VsUtilities.CheckNotNull(rdt);
|
|
|
|
ErrorHandler.ThrowOnFailure(rdt.FindAndLockDocument((uint)_VSRDTFLAGS.RDT_NoLock, this.Node.Url, out ivsHierarchy, out itemid, out docData, out docCookie));
|
|
|
|
// Open the file using the IVsProject interface
|
|
// We get the outer hierarchy so that projects can customize opening.
|
|
var project = Node.ProjectMgr.GetOuterInterface<IVsProject>();
|
|
ErrorHandler.ThrowOnFailure(project.OpenItem(Node.ID, ref logicalViewGuid, docData, out windowFrame));
|
|
} finally {
|
|
if (docData != IntPtr.Zero) {
|
|
Marshal.Release(docData);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Get the automation object and return it
|
|
return ((windowFrame != null) ? VsShellUtilities.GetWindowObject(windowFrame) : null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Saves the project item.
|
|
/// </summary>
|
|
/// <param name="fileName">The name with which to save the project or project item.</param>
|
|
/// <exception cref="InvalidOperationException">Is thrown if the save operation failes.</exception>
|
|
/// <exception cref="ArgumentNullException">Is thrown if fileName is null.</exception>
|
|
public override void Save(string fileName) {
|
|
UIThread.Instance.RunSync(() => {
|
|
this.DoSave(false, fileName);
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Saves the project item.
|
|
/// </summary>
|
|
/// <param name="fileName">The file name with which to save the solution, project, or project item. If the file exists, it is overwritten</param>
|
|
/// <returns>true if the rename was successful. False if Save as failes</returns>
|
|
public override bool SaveAs(string fileName) {
|
|
try {
|
|
UIThread.Instance.RunSync(() => {
|
|
this.DoSave(true, fileName);
|
|
});
|
|
} catch (InvalidOperationException) {
|
|
return false;
|
|
} catch (COMException) {
|
|
return false;
|
|
}
|
|
return true;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a value indicating whether the project item is open in a particular view type.
|
|
/// </summary>
|
|
/// <param name="viewKind">A Constants.vsViewKind* indicating the type of view to check./param>
|
|
/// <returns>A Boolean value indicating true if the project is open in the given view type; false if not. </returns>
|
|
public override bool get_IsOpen(string viewKind) {
|
|
CheckProjectIsValid();
|
|
|
|
// Validate input params
|
|
Guid logicalViewGuid = VSConstants.LOGVIEWID_Primary;
|
|
try {
|
|
if (!(String.IsNullOrEmpty(viewKind))) {
|
|
logicalViewGuid = new Guid(viewKind);
|
|
}
|
|
} catch (FormatException) {
|
|
// Not a valid guid
|
|
throw new ArgumentException(SR.GetString(SR.ParameterMustBeAValidGuid, CultureInfo.CurrentUICulture), "viewKind");
|
|
}
|
|
|
|
bool isOpen = false;
|
|
|
|
using (AutomationScope scope = new AutomationScope(this.Node.ProjectMgr.Site)) {
|
|
UIThread.Instance.RunSync(() => {
|
|
IVsUIHierarchy hier;
|
|
uint itemid;
|
|
|
|
IVsWindowFrame windowFrame;
|
|
|
|
isOpen = VsShellUtilities.IsDocumentOpen(this.Node.ProjectMgr.Site, this.Node.Url, logicalViewGuid, out hier, out itemid, out windowFrame);
|
|
});
|
|
}
|
|
|
|
return isOpen;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the ProjectItems for the object.
|
|
/// </summary>
|
|
public override ProjectItems ProjectItems {
|
|
get {
|
|
return UIThread.Instance.RunSync<ProjectItems>(() => {
|
|
if (this.Project.ProjectNode.CanFileNodesHaveChilds)
|
|
return new OAProjectItems(this.Project, this.Node);
|
|
else
|
|
return base.ProjectItems;
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#region helpers
|
|
/// <summary>
|
|
/// Saves or Save As the file
|
|
/// </summary>
|
|
/// <param name="isCalledFromSaveAs">Flag determining which Save method called , the SaveAs or the Save.</param>
|
|
/// <param name="fileName">The name of the project file.</param>
|
|
private void DoSave(bool isCalledFromSaveAs, string fileName) {
|
|
VsUtilities.ArgumentNotNull("fileName", fileName);
|
|
|
|
CheckProjectIsValid();
|
|
|
|
using (AutomationScope scope = new AutomationScope(this.Node.ProjectMgr.Site)) {
|
|
|
|
UIThread.Instance.RunSync(() => {
|
|
IntPtr docData = IntPtr.Zero;
|
|
|
|
try {
|
|
IVsRunningDocumentTable rdt = this.Node.ProjectMgr.Site.GetService(typeof(SVsRunningDocumentTable)) as IVsRunningDocumentTable;
|
|
Debug.Assert(rdt != null, " Could not get running document table from the services exposed by this project");
|
|
VsUtilities.CheckNotNull(rdt);
|
|
|
|
// First we see if someone else has opened the requested view of the file.
|
|
uint itemid;
|
|
IVsHierarchy ivsHierarchy;
|
|
uint docCookie;
|
|
int canceled;
|
|
string url = this.Node.Url;
|
|
|
|
ErrorHandler.ThrowOnFailure(rdt.FindAndLockDocument((uint)_VSRDTFLAGS.RDT_NoLock, url, out ivsHierarchy, out itemid, out docData, out docCookie));
|
|
|
|
// If an empty file name is passed in for Save then make the file name the project name.
|
|
if (!isCalledFromSaveAs && fileName.Length == 0) {
|
|
ErrorHandler.ThrowOnFailure(this.Node.ProjectMgr.SaveItem(VSSAVEFLAGS.VSSAVE_SilentSave, url, this.Node.ID, docData, out canceled));
|
|
} else {
|
|
VsUtilities.ValidateFileName(this.Node.ProjectMgr.Site, fileName);
|
|
|
|
// Compute the fullpath from the directory of the existing Url.
|
|
string fullPath = CommonUtils.GetAbsoluteFilePath(Path.GetDirectoryName(url), fileName);
|
|
|
|
if (!isCalledFromSaveAs) {
|
|
if (!CommonUtils.IsSamePath(this.Node.Url, fullPath)) {
|
|
throw new InvalidOperationException();
|
|
}
|
|
|
|
ErrorHandler.ThrowOnFailure(this.Node.ProjectMgr.SaveItem(VSSAVEFLAGS.VSSAVE_SilentSave, fullPath, this.Node.ID, docData, out canceled));
|
|
} else {
|
|
ErrorHandler.ThrowOnFailure(this.Node.ProjectMgr.SaveItem(VSSAVEFLAGS.VSSAVE_SilentSave, fullPath, this.Node.ID, docData, out canceled));
|
|
}
|
|
}
|
|
|
|
if (canceled == 1) {
|
|
throw new InvalidOperationException();
|
|
}
|
|
} catch (COMException e) {
|
|
throw new InvalidOperationException(e.Message);
|
|
} finally {
|
|
if (docData != IntPtr.Zero) {
|
|
Marshal.Release(docData);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
}
|
|
#endregion
|
|
|
|
}
|
|
}
|