当前位置:   article > 正文

【MPS】Jetbrains MPS入门案例Shapes(四)

jetbrains mps

上一篇文章介绍了MPS入门案例中添加颜色属性的过程,这篇文章将介绍如何将实例模型转换为Java代码,并且通过调用Java图形化编程库来绘制图形的方法,主要是通过MPS的生成器Generator来生成Java代码的,这是本人觉得最有意思的一部分。除了生成Java代码还可以生成XML文件、JS文件等,还可以通过Editor Generator生成任意想要生成的问本或者语言。

配置Canvas到Rule的映射

首先我们打开Generator下的main,会打开一个配置Concept到Rule映射的编辑界面,该界面主要是配置Concept到生成模板文件的映射,如图所示:
在这里插入图片描述
我们先配置一下Canvas的模板映射,首先光标放置在root_mapping_rules下方的<<…>>上,通过按回车键会自动一个映射配置,如图所示:
在这里插入图片描述
在<choose applicable concept>处输入Canvas,在<no template>处按下ALT + Enter根据下方第一张截图创建一个Canvas生成Java代码的模板文件,下方第二张截图为配置好Canvas与其模板文件的映射:
在这里插入图片描述
在这里插入图片描述
打开map_Canvas模板文件我们可以看到Java模板的一个框架:
在这里插入图片描述

初步编辑Canvas的Java模板

在编辑Canvas的Java模板之前,我们要给generator模块添加JDK依赖,添加完JDK依赖之后我们像在IDEA里通过智能提示补全Java代码,在选中generator/Shapes/main后,按下ALT + Enter并切换到Dependencies,如下图所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
然后给main@generator添加swing和awt图形编程库的依赖:
在这里插入图片描述
在这里插入图片描述
添加完依赖之后就可以开始编辑模板了,首先让map_Canvas类继承JFrame,用过Java Swing的人都应该知道Java GUI的猪窗口都需要继承自JFrame,关于JFrame的内容在这里就不赘述了,模板中输入需要在map_Canvas后添加extends JFrame,这里注意一下当extends还没输入全时ex是紧贴着map_Canvas的,这没关系,当你输如完extends之后会自动加空格并提示补全父类,当然也可以在输入ex…之后按Ctrl + Space补全extends,然后在补全JFrame:
在这里插入图片描述
在类内部输入psvm可以自动生成main方法:
在这里插入图片描述
在这里插入图片描述
在类内部输入method可以创建一个方法框架,然后补全方法名、参数和方法体:
在这里插入图片描述
在这里插入图片描述
在类内部输入field可以创建一个类属性框架,然后补全类属性:在这里插入图片描述
在这里插入图片描述
将光标放在JPanel内部类中,按快捷键Ctrl + O,弹出JPanel中课被重写的方法,输入paintComponent(没有搜索框,直接在弹出的窗口后输入即可)快速定位到方法,如下第一张截图所示,确认后重写该绘制方法,如下第二张截图所示:
在这里插入图片描述
在这里插入图片描述
接下来把其他代码补全一下,补全过程就不多说了,Ctrl + Space以及IDEA智能缩写使劲用就是了:
在这里插入图片描述

参数化Canvas模板

上一步编辑的代码模板是固定各种参数的,而我们在创建Shapes模型实例时是可以随意设置各参数的值得,因此模板也需要参数化,其实就是占位符的使用。首先来看下最基本的占位符,下面的模板使用了一个占位符来参数化生成代码的类名,这个类名对我们前面定义的Canvas的name属性,首先将光标放在上一步创建的Java模板的类名上,按下快捷键ALT + Enter会弹出窗口,这里选择Add Property Macro(添加属性宏),如下方第一张截图所示,选中后会在编辑器上会添加占位符符号,如下方第二张截图所示:
在这里插入图片描述
在这里插入图片描述
在上方添加了占位符之后可以观察到占位符处$符号下方、IDE下方出现的Inspector窗口标红报错,这是因为我们还没给该占位符设置对应的属性值,需要在下方的Inspector窗口进行设置,仔细观察Inspector窗口可以发现此处value后包含几个参数,其中一个为node,这个node其实就是当前模板对应的Concept,在<no statement>先输入"node.",再通过快捷键Ctrl + Space补全代码,在弹出的可选项中我们可以发现IDE可以识别出当前模板对应的Concept,因此给出了Canvas包含的属性,如下方第一张截图所示,这里我们选择node,不全后如下方第二张截图所示,设置完这个占位符后在我们对Canvas实例进行代码生成操作时,生成的Java的类名就是Canvas的name属性值了:
在这里插入图片描述
在这里插入图片描述
以同样的方式我们对Title参数化:
在这里插入图片描述

Canvas中绘制图形模板(初步)

前面的内容只编写了Canvas代码模板的画布信息,具体图形绘制的部分仅仅是打印了一个"Draw Here"来占了一下绘图这个坑。对于绘制图形,我们首先考虑Canvas内包含多个Shape(shapes),因此会想到需要用到循环渲染的方法,在MPS中使用LOOP Macro实现,我们先进行shapes遍,首先将光标放在System.out.println("Draw here");这一行,按下快捷键Shift + ↑选中这一整行(这里无法使用鼠标直接选中)如下第一张截图所示,然后按下快捷键ALT + Enter在弹出选项中Add LOOP Macro over node.shapes选项,如下第二张截图所示,选中之后LOOP会将大于语句包裹起来,如下第三张图所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
由于我们需要的不是要控制台打印内容,所以我们要有替换打印语句为绘制语句的操作,这里使用COPY_SRC Macro实现,这个命令将会把其包裹的内容替换为指定的绘制具体模板,这个指定的模板将在后续实现,首先将光标放在上一步LOOP内的打印语句上,安装Shift + ↑选中整个打印语句(不包含LOOP)如如下第一张截图所示,然后按下ALT + ENTER在弹出选项中选择Add Node Macro,如下第二张截图所示,选中后会出现如下第三张截图所示标红内容,在$ $之间输入COPY,然后通过Ctrl + Space不全COPY_SRC,如下第四张截图所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

创建绘制Circle、Square的模板

再次进入配置Concept到Generator映射的文件中(main@generator → main),在reduction rules下方添加Circle、Square的代码模板及其映射,如下图所示,其中可以看到有标红报错,原因是还未在模板里不全内容,后面补全后就可以消除这个标红。添加映射规则的方法在前面介绍了,在此不赘述:
在这里插入图片描述
在这里插入图片描述

补充Circle模板内容

然后我们进入到上一步创建的reduce_Circle模板补全绘制Circle的模板,先看一下这个模板最初的内容如下第一张截图所示,会有标红报错,首先输入BloSta再通过Ctrl + Space提示补全一对花括号,如下第二张截图所示,然后添加Graphics实例(多使用Ctrl + Space补全),如下第三张截图所示,然后在Graphics下方输入左半边花括号"{",按下Enter会补全出一对花括号,在花括号内添加如下第四张截图所示的内容:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
由于绘图部分不是固定不变的,是需要根据我们的模型参数动态变化的,所以在绘图模板里面需要添加模板片段,模板片段里的内容可以添加占位符、内置模板(LOOP等),可能由于MPS版本问题,模板片段无法直接添加,可以按照如下方法添加:

  • 将光标放在内层花括号左边,然后按下ALT + Enter,在弹出选项中选择Add LOOP macro,会生成如下第二张截图的内容,把多余的内容删除(箭头所指内容),剩下内容如下第三张截图所示,此时就不会有标红报错:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

参数化Circle模板

对于图形的尺寸也是根据模型实例动态变化的,因此需要个模板中尺寸的参数(10,10,10,10)添加占位符,drawOval是绘制椭圆的方法,但我们需要绘制的事圆,因此它的参数按顺序依次对应Circle中的圆心x坐标、y坐标、半径、半径(长轴半径和端州半径一样),添加过程如下图所示(在每个参数处使用ALT + Enter提示):
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
然后需要参数化颜色,将光标放在Color.red中的red前面,通过ALT + Enter提示添加一个Reference的占位符,如下第一张图所示,生成的内容会有一标红报错,需要在下方Inspector补全对应的值,如下第二张图所示,这个值的获取稍微有点复杂,在下一步介绍:
在这里插入图片描述
因为颜色这个属性在我们定义的模型中使用了一个Reference,对应Java中的事awt中的Color类,因此我们需要引入我们定义的模型和MPS中awt的依赖,下图是用于引用awt中Color的依赖,下图二适用于引用我们模型中Color这个Reference:
在这里插入图片描述
在这里插入图片描述
引入依赖之后我们需要边集Circle绘图模板中的颜色值,在Inspector输入以下内容(多使用Ctrl + Space):
在这里插入图片描述
需要注意的事node-ptr后面跟的Color是awt的Color,如下图所示:
在这里插入图片描述
到这里Circle的绘制模板就完成了,接下来按照同样的方式定义绘制Square的Java模板。

编辑绘制Square的Java模板

按照编辑绘制圆形Java模板的方法编辑绘制正方形Java模板,内容如下图所示:
在这里插入图片描述

预览生成的代码

以上就定义好了生成Java代码的模板,rebuild项目之后就可以预览模型实例生成的Java了,步骤:进入sandbox下的MyDrawing模型实例,在编辑页面下右键选择Preview Generated Text,如下第一张图所示,IDE会弹出生成代码模板,如下第二张图所示:
在这里插入图片描述
在这里插入图片描述
做到这一步看到了Java代码,可以复制粘贴到IDEA上运行跑出绘制的图像,你是不是比较激动了,反正我是挺激动的。不过这还不是最后一步,既然是DSL就应该在一个平台上执行完整的流程,没有必要把代码复制到IDEA上去跑,下面就介绍在MPS运行我们的模型实例。

运行代码

首先,我们需要添加执行代码的依赖,也就会添加MPS的执行引擎,如下图所示:
在这里插入图片描述
然后在Canvas这个Concept上添加implements的类IMainClass,表示Canvas的模型实例是可执行的模型实例,如下图所示:
在这里插入图片描述
此时rebuild一下项目我们就可以运行MyDrawing绘制图形了,右键MyDrawing → Run “Node MyDrawing”就有绘制的图形弹出来了,如下图所示:
在这里插入图片描述
在这里插入图片描述
到此就大功告成了,撒花!!!

结束语

Generator这一部分真的是太长了,断断续续好长时间才写完,与上一篇相隔一个月了,由于篇幅太长内容的编写可能比较乱,还请谅解,后续有时间我会重新整理一下这篇的内容。另外这一部分官网上有一小节非必须的内容,为了不增加离大家的理解压力,我在这就没写出来,有兴趣的可以看官方文档A more robust generation for Squares小节。网上除了官网也没有其他MPS详细的入门教程,能把这个教程整理完分享给大家我挺开心的,知乎冰封大神有几篇的MPS教程,Shapes这个案例能够顺利做下来的的可以去看一看。当然,对于DSL我还什么都不懂,还需要深入学习DSL、程序语言理论的东西,后续可能还会尝试用MPS写其他一些东西,有机会也会写成博客分享出来。

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号