主にプログラミングに関して。Python, .NET Framework(C#), JavaScript, その他いくらか。
記事にあるサンプルやコードは要検証。使用に際しては責任を負いかねます

スポンサーサイト

                
tags:
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Boo, WPF: Convert XAML to Boo Code

                
Boo, running on .NET Framework or Mono, is interesting language. Boo can run on interpreter like dynamic language, however Boo is static language. Boo's performance is even equal C#. Boo code looks like Python, on the other hand, Boo has many c# functions(type interface, Access Modifiers, and etc...). Boo is called "like a Python". I think "Not just like Python. Boo is C# with indent block".

On .NET Framework, we can make GUI application with WPF(Windows Presentation Foundation). With WPF, we can make UI with XML named XAML. However...

C# and WPF project on IDE(like Visual Studio, Sharp Develop), it's automatic to connect namespace between C# code and XAML. How about Boo? VisualStudio and SharpDevelop do not support Boo and WPF project.

I wrote a prototype Boo code to convert XAML to Boo code. It helps to develop Boo and WPF project. The code in under development.

namespace XAML2Boo

import Boo.Lang.Compiler
import Boo.Lang.Compiler.IO
import Boo.Lang.Compiler.Pipelines

import System
import System.Windows
import System.Windows.Controls
import System.Windows.Markup
import System.IO
import System.Environment
import System.Xml
import System.Diagnostics;
import System.Windows.Automation
import System.Windows.Controls.Primitives
import System.Windows.Data
import System.Windows.Documents
import System.Windows.Ink
import System.Windows.Input
import System.Windows.Media
import System.Windows.Media.Animation
import System.Windows.Media.Effects
import System.Windows.Media.Imaging
import System.Windows.Media.Media3D
import System.Windows.Media.TextFormatting
import System.Windows.Navigation
import System.Windows.Shapes
import System.Windows.Shell
import System.Reflection


def RunScript(input) as bool:
booC = BooCompiler()
booC.Parameters.Input.Add(StringInput("<script>", input))
booC.Parameters.Pipeline = CompileToMemory() //No need for an on-disk file.
booC.Parameters.Ducky = true //By default, all objects will be ducked typed; no need for the user to "var as string" anywhere.
assemblies = [typeof(Console).Assembly,
typeof(Control).Assembly,
typeof(BitmapImage).Assembly]
for assembly in assemblies:
booC.Parameters.References.Add(assembly)

context as CompilerContext = booC.Run()
if context.GeneratedAssembly is null:
print join(e for e in context.Errors, "\n")
return false
else:
return true


static class XAML2Boo:
private attributesIgnored as Boo.Lang.List
private controlList as Boo.Lang.List
private elementCounter = {} as Boo.Lang.Hash
private reader as XmlReader
public methods = [] as Boo.Lang.List
public baseClass as string
public haveName as Boo.Lang.List

// define variables
def constructor():
attributesIgnored = ["xmlns",
"x:Class",
"xmlns:x"]

assembly = Assembly.GetAssembly(Control)
types = assembly.GetTypes()
controlList = []
for t in types:
if (t.Namespace == "System.Windows.Controls") & t.IsPublic & t.IsClass & (not t.IsSubclassOf(EventArgs)) & (t.BaseType != MulticastDelegate):
controlList.Add(t.Name.ToString())

private def ElementCounter(element as string) as int:
if element in elementCounter.Keys:
num as int = elementCounter[element]
elementCounter[element] = num + 1
else:
elementCounter[element] = 1
return elementCounter[element]

def Convert(fileName as string) as bool:
streamReader = StreamReader(fileName)
reader = XmlReader.Create(streamReader)
variableDefinitionCode = ""
depth = -1
elements = []
haveName = []
spaceName = ""
className = ""
while reader.Read():
if reader.NodeType == XmlNodeType.Element:

// get type by element name
if reader.Name in controlList:
type = Activator.CreateInstance("PresentationFramework", "System.Windows.Controls." + reader.Name).Unwrap().GetType()
elif reader.Name == "Window":
type = Activator.CreateInstance("PresentationFramework", "System.Windows." + reader.Name).Unwrap().GetType()

elementCount = ElementCounter(type.Name)
target = reader.Name.ToLower() + elementCount
print "\nElement Type: " + reader.Name
print reader.Depth

// make list to treat node connection
// elements[x][0]:name of variable, elements[x][1]:type
if reader.Depth == 0:
elements.Add(["self", type] as Boo.Lang.List)
elif reader.Depth > depth:
elements.Add([target, type] as Boo.Lang.List)
elif reader.Depth == depth:
elements[reader.Depth] = [target, type] as Boo.Lang.List

// make code to declare object
depth = reader.Depth
if reader.Depth == 0:
baseClass = reader.Name
else: # make Instance
variableDefinitionCode += "\n{0} = {1}()\n" %(target, reader.Name)

// make code to connect parent node
if reader.Depth > 0:
parent as Boo.Lang.List = elements[reader.Depth - 1]
parentType as Type = parent[1]
if parentType.GetProperty("Content"):
variableDefinitionCode += "{0}.Content = {1}\n" %(parent[0], target)
elif parentType.GetProperty("Children"):
variableDefinitionCode += "{0}.Children.Add({1})\n" %(parent[0], target)

// make code to treat attributes
while reader.MoveToNextAttribute():
print "Attribute: " + reader.Name + " " + reader.Value
str = ""

if reader.Name == "Name":
haveName.Add([reader.Value, type])
variableDefinitionCode += "{0} = {1}\n" %(reader.Value, target)
variableDefinitionCode += "{0}.Name = '{1}'\n" %(target, reader.Value)
continue

if (reader.Name == "x:Class") & (depth == 0):
li = reader.Value.Split(char('.'))
spaceName = li[0]
className = li[1]
continue

p as PropertyInfo = type.GetProperty(reader.Name)
propertyType as Type = null
if p:
print p.PropertyType.Name
propertyType = p.PropertyType
if propertyType == System.Double:
str = "{0} = {1}\n" %(reader.Name, reader.Value)
elif propertyType == System.String:
str = "{0} = '{1}'\n" %(reader.Name, reader.Value)
elif propertyType.IsEnum:
str = "{0} = {1}.{2}\n" %(reader.Name, propertyType.Name, reader.Value)
else:
str = "{0} = {1}({2})\n" %(reader.Name, propertyType.Name, reader.Value)

else:
events = [e.Name for e in type.GetEvents()]
if reader.Name in events:
methods.Add("{0}.{1} += {2}\n" %(target, reader.Name, reader.Value))

if str:
if depth > 0:
str = "{0}.{1}" %(target, str)
variableDefinitionCode += str

elif reader.NodeType == XmlNodeType.Text:
print "Element Text: " + reader.Value
print target
variableDefinitionCode += "{0}.Content = '{1}'\n" %(target, reader.Value)
elif reader.NodeType == XmlNodeType.XmlDeclaration:
pass
elif reader.NodeType == XmlNodeType.ProcessingInstruction:
print reader.Name + " " + reader.Value
elif reader.NodeType == XmlNodeType.Comment:
print reader.Value
elif reader.NodeType == XmlNodeType.EndElement:
print "End of " + reader.Name
print ""

print "XML parse Finished\n"
print elements


code = """namespace {0}

import System
import System.Windows
import System.Windows.Controls
import System.Windows.Markup
import System.IO
import System.Environment
import System.Xml
import System.Diagnostics;
import System.Windows.Automation
import System.Windows.Controls.Primitives
import System.Windows.Data
import System.Windows.Documents
import System.Windows.Ink
import System.Windows.Input
import System.Windows.Media
import System.Windows.Media.Animation
import System.Windows.Media.Effects
import System.Windows.Media.Imaging
import System.Windows.Media.Media3D
import System.Windows.Media.TextFormatting
import System.Windows.Navigation
import System.Windows.Shapes
import System.Windows.Shell

partial class {1}({2}):
""" %(spaceName, className, baseClass)

for propertyName as Boo.Lang.List in haveName:
code += " internal " + propertyName[0] + " as " + propertyName[1].ToString() + "\n"

indentedCode = "\n def InitializeComponent():\n"
strReader = StringReader(variableDefinitionCode)
while true:
str = strReader.ReadLine()
if str == null:
break
indentedCode += " " * 8 + str + "\n"

fileText = code + indentedCode
print "********************************\n"
print fileText
if RunScript(fileText):
for str in methods:
fileText += "\n" + " " * 8 + "// Events\n"
fileText += " " * 8 + str
using file = File.CreateText(fileName + ".boo"):
file.Write(fileText)
print "**************************"
print fileName + ".boo is generated"
print "**************************"
return false

[STAThread]
def Main():
XAML2Boo.Convert("Window1.xaml")
Console.ReadKey(true)



Example:
XAML before convert
<?xml version="1.0" encoding="utf-8"?>
<Window
x:Class="Test.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="XAML2Script"
Height="300"
Width="300">
<StackPanel
Name="stackpanel1"
VerticalAlignment="Stretch"
HorizontalAlignment="Center"
Height="159"
Width="159">
<Button
Name="b1">button1</Button>
<Button
Name="b2">button2</Button>
<Button
Name="b3"
Margin="0,0,0,0"
Click="b3Clicked">button3</Button>
</StackPanel>
</Window>


Boo code converted from XAML
namespace Test

import System
import System.Windows
import System.Windows.Controls
import System.Windows.Markup
import System.IO
import System.Environment
import System.Xml
import System.Diagnostics;
import System.Windows.Automation
import System.Windows.Controls.Primitives
import System.Windows.Data
import System.Windows.Documents
import System.Windows.Ink
import System.Windows.Input
import System.Windows.Media
import System.Windows.Media.Animation
import System.Windows.Media.Effects
import System.Windows.Media.Imaging
import System.Windows.Media.Media3D
import System.Windows.Media.TextFormatting
import System.Windows.Navigation
import System.Windows.Shapes
import System.Windows.Shell

partial class Window1(Window):
internal stackpanel1 as System.Windows.Controls.StackPanel
internal b1 as System.Windows.Controls.Button
internal b2 as System.Windows.Controls.Button
internal b3 as System.Windows.Controls.Button

def InitializeComponent():
Title = 'XAML2Script'
Height = 300
Width = 300

stackpanel1 = StackPanel()
self.Content = stackpanel1
stackpanel1 = stackpanel1
stackpanel1.Name = 'stackpanel1'
stackpanel1.VerticalAlignment = VerticalAlignment.Stretch
stackpanel1.HorizontalAlignment = HorizontalAlignment.Center
stackpanel1.Height = 159
stackpanel1.Width = 159

button1 = Button()
stackpanel1.Children.Add(button1)
b1 = button1
button1.Name = 'b1'
button1.Content = 'button1'

button2 = Button()
stackpanel1.Children.Add(button2)
b2 = button2
button2.Name = 'b2'
button2.Content = 'button2'

button3 = Button()
stackpanel1.Children.Add(button3)
b3 = button3
button3.Name = 'b3'
button3.Margin = Thickness(0,0,0,0)
button3.Content = 'button3'

// Events
button3.Click += hoge
            

コメントの投稿

非公開コメント

プロフィール

hMatoba

Author:hMatoba
Github

最新記事
リンク
作ったものなど
月別アーカイブ
カテゴリ
タグリスト

検索フォーム
Amazon
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。