Browse Source

Add project template for creating a custom tool AddIn.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/2.1@2196 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 19 years ago
parent
commit
2c108be5e5
  1. 190
      data/templates/project/CSharp/SharpDevelopCustomTool.xpt
  2. 27
      data/templates/project/CSharp/SharpDevelopCustomToolTemplate.xft.xml
  3. 2
      src/Setup/Files.wxs

190
data/templates/project/CSharp/SharpDevelopCustomTool.xpt

@ -0,0 +1,190 @@ @@ -0,0 +1,190 @@
<?xml version="1.0"?>
<Template originator = "Daniel Grunwald">
<!-- Template Header -->
<TemplateConfiguration>
<Name>Custom Tool</Name>
<Category>C#</Category>
<Subcategory>SharpDevelop</Subcategory>
<Icon>C#.Project.ControlLibrary</Icon>
<Description>A custom tool that implements a code generator transforming a source file into an output file whenever the source is changed inside SharpDevelop</Description>
</TemplateConfiguration>
<!-- Actions -->
<Actions>
<Open filename = "${ProjectName}.addin"/>
</Actions>
<Project language="C#">
<ProjectItems>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ProjectItems>
<PropertyGroup>
<OutputType>Library</OutputType>
</PropertyGroup>
<Files>
<File name="${ProjectName}.addin" CopyToOutputDirectory="Always"><![CDATA[<AddIn name = "${ProjectName}"
author = "${USER}"
url = ""
description = "TODO: Put description here">
<Runtime>
<Import assembly = "${ProjectName}.dll"/>
</Runtime>
<!-- make SharpDevelop look for file templates in your AddIn's directory -->
<Path name = "/SharpDevelop/BackendBindings/Templates">
<Directory id = "${ProjectName}Template" path = "." />
</Path>
<Path name = "/SharpDevelop/CustomTools">
<!--
Register the custom tool.
id: ID used to identify the custom tool. This ID will be used in project files to reference your generator.
class: fully qualified name of a class in your assembly that implements ICustomTool
fileNamePattern: a regular expression. For file names matched by this regex, SharpDevelop will display
your custom tool in the drop down box of the property grid when a file with that extension
is selected.
-->
<CustomTool id = "${ProjectName}Generator"
class = "${StandardNamespace}.${ProjectName}Tool"
fileNamePattern = "\.xml$"/>
</Path>
</AddIn>
]]></File>
<File name="${ProjectName}Tool.cs">
<![CDATA[${StandardHeader.C#}
using System;
using System.IO;
using System.CodeDom;
using System.Xml;
using ICSharpCode.EasyCodeDom; // defined in ICSharpCode.SharpDevelop.Dom.dll
using ICSharpCode.SharpDevelop.Project; // defined in ICSharpCode.SharpDevelop.dll
namespace ${StandardNamespace}
{
/// <summary>
/// Description of CustomTool.
/// </summary>
public class ${ProjectName}Tool : ICustomTool
{
/// <summary>
/// Called by SharpDevelop when your tool has to generate code.
/// </summary>
/// <param name="item">
/// The file for which your tool should generate code.
/// </param>
public void GenerateCode(FileProjectItem item, CustomToolContext context)
{
// make SharpDevelop generate a name for the output file
string outputFileName = context.GetOutputFileName(item, ".Generated");
// if item.FileName is "C:\somedir\SomeName.xml" and is inside a C# project,
// the output name will be "C:\somedir\SomeName.Generated.cs".
// context.GetOutputFileName will always append the extension for compilable files in
// the current project type, so if you want to always output xml, you could use
// string outputFileName = Path.ChangeExtension(item.FileName, ".Generated.xml");
// now read the input file:
XmlDocument doc = new XmlDocument();
doc.Load(item.FileName);
// and generate the code using System.CodeDom:
CodeCompileUnit ccu = GenerateCode(doc, context.OutputNamespace, Path.GetFileNameWithoutExtension(item.FileName));
// Finally save our generated CodeDom compile unit. SharpDevelop will take care of generating
// the code using the correct CodeDomProvider for the project type. This means code-generating
// custom tools are completely language-independent
context.WriteCodeDomToFile(item, outputFileName, ccu);
// If you don't want to generate code, you'll have to write the output file yourself and then use
// context.EnsureOutputFileIsInProject to add the generated file to the project if it isn't already
// part of it.
}
CodeCompileUnit GenerateCode(XmlDocument doc, string targetNamespace, string className)
{
// This method does the actual code generation.
// This sample accepts an object graph as XmlDocument and outputs a class with a static method
// constructing that object graph.
// We'll use ICSharpCode.EasyCodeDom for code generation. This is a small wrapper around CodeDom
// that provides convenience methods that create new objects and add them to the parent simultaniously.
// This makes the generation code much more concise.
// EasyCodeDom classes derive from the System.CodeDom types or have an implicit conversion operator, so
// use can use EasyCodeDom objects whereever CodeDom is expected.
EasyCompileUnit ccu = new EasyCompileUnit();
EasyTypeDeclaration generatedClass = ccu.AddNamespace(targetNamespace).AddType(className);
EasyMethod m = generatedClass.AddMethod("Create");
m.ReturnType = Easy.TypeRef(doc.DocumentElement.Name);
m.Attributes = MemberAttributes.Static | MemberAttributes.Public;
// now generate code. helper variables will be named "v#"
int helperVariableCounter = 0;
string rootVariableName = GenerateCodeForObject(m.Body, doc.DocumentElement, ref helperVariableCounter);
// generate "return v0;"
m.Body.Return(Easy.Var(rootVariableName));
return ccu;
}
string GenerateCodeForObject(EasyBlock block, XmlElement objectElement, ref int helperVariableCounter)
{
// generate code to create the object represented by "objectElement" and add it to the block
// generate "VarType v#;"
CodeVariableDeclarationStatement varDecl;
varDecl = block.DeclareVariable(Easy.TypeRef(objectElement.Name), "v" + helperVariableCounter);
helperVariableCounter += 1;
// generate "VarType v# = new VarType();"
varDecl.InitExpression = Easy.New(Easy.TypeRef(objectElement.Name));
// translate XML attribute to assignments to properties
foreach (XmlAttribute attribute in objectElement.Attributes) {
// generate 'v#.attributeName = "attributeValue";'
// attribute.Value is a string, thus Easy.Prim creates a string literal.
// This simple code generator does not support using other types for attributes.
block.Assign(Easy.Var(varDecl.Name).Property(attribute.Name),
Easy.Prim(attribute.Value));
}
foreach (XmlNode collectionNode in objectElement.ChildNodes) {
XmlElement collectionElement = collectionNode as XmlElement;
if (collectionElement != null) {
foreach (XmlNode itemNode in collectionElement.ChildNodes) {
XmlElement itemElement = itemNode as XmlElement;
if (itemElement != null) {
// add the object represented by "itemElement" to the collection represented by
// "collectionElement".
// generate code to create child object
string childVariableName = GenerateCodeForObject(block, itemElement, ref helperVariableCounter);
// generate 'v#.collectionName.Add(v##)'
block.InvokeMethod(Easy.Var(varDecl.Name).Property(collectionElement.Name),
"Add",
Easy.Var(childVariableName));
}
}
}
}
return varDecl.Name;
}
}
}
]]></File>
<File name="FileTemplate.xft" src="SharpDevelopCustomToolTemplate.xft.xml" binary="true" CopyToOutputDirectory="Always"/>
<File name="AssemblyInfo.cs" src="DefaultAssemblyInfo.cs"/>
</Files>
</Project>
</Template>

27
data/templates/project/CSharp/SharpDevelopCustomToolTemplate.xft.xml

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
<?xml version="1.0"?>
<Template author="-" version="1.0">
<Config
name = "CustomTool Template"
icon = "Icons.32x32.XMLFileIcon"
category = "${res:Templates.File.Categories.Misc}"
defaultname = "CustomToolTemplate${Number}.xml"
language = "XML"/>
<Description>A file template for ${ProjectName}</Description>
<Files>
<File name="${FullName}" language="XML"><![CDATA[<?xml version="1.0"?>
<Form Text = "Form title">
<Controls>
<Button Text = "Click me"/>
<Panel>
<Controls>
<Label Text = "A Label"/>
<Button Text = "Another button"/>
</Controls>
</Panel>
</Controls>
</Form>]]>
</File>
</Files>
</Template>

2
src/Setup/Files.wxs

@ -731,6 +731,8 @@ @@ -731,6 +731,8 @@
<File Source="..\..\data\templates\project\CSharp\SharpDevelopMacro.xpt" Name="SHARPD_2.XPT" Id="CSharpSharpDevelopMacro.xpt" LongName="SharpDevelopMacro.xpt" />
<File Source="..\..\data\templates\project\CSharp\WebpageProject.xpt" Name="WEBPAG_1.XPT" Id="CSharpWebpageProject.xpt" LongName="WebpageProject.xpt" />
<File Source="..\..\data\templates\project\CSharp\WPFApplication.xpt" Name="WPFAPP_1.XPT" Id="CSharpWPFApplication.xpt" LongName="WPFApplication.xpt" />
<File Source="..\..\data\templates\project\CSharp\SharpDevelopCustomTool.xpt" Name="SHARPD_3.XPT" Id="SharpDevelopCustomTool.xpt" LongName="SharpDevelopCustomTool.xpt" />
<File Source="..\..\data\templates\project\CSharp\SharpDevelopCustomToolTemplate.xft.xml" Name="SHARPD_1.XML" Id="SharpDevelopCustomToolTemplate.xft.xml" LongName="SharpDevelopCustomToolTemplate.xft.xml" />
</Component>
<Component Guid="2EBDC2FE-A2C9-4023-BC86-0E688B5897A3" Id="CSharpNotifyIconProjectTemplate" DiskId="1">
<File Source="..\..\data\templates\project\CSharp\NotifyIcon.xpt" Name="NOTIFY.XPT" Id="NotifyIcon.xpt" LongName="NotifyIcon.xpt" />

Loading…
Cancel
Save