Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Subclassing code generators (example: Swing UI)
Subclassing code generators (example: Swing UI) [message #1386854] Sat, 21 June 2014 15:36 Go to next message
Gary Worsham is currently offline Gary WorshamFriend
Messages: 176
Registered: September 2013
Senior Member
I'm extending my DSL to help create UI components of my Swing application.

For example, I am using JSliders and JCheckBoxes.

Each type of Swing control has a few things that need to happen. This is independent of Xtend, I am just trying to describe the design challenge.

#1 Declare the variable that the control is going to adjust.
#2 Declare and initialize the control itself.
#3 Add the control to the Swing JFrame that this class uses, inside of a "Runnable" construct that puts the code on the event thread which is Swing requirement for thread safety.
#4 Set the Listener for the control to "this".
#5 Create a suitable "Listener" for the Swing control. For example, JSliders use a ChangeListener and JCheckBoxes use ActionListeners, ChangeListeners, and ItemListeners. In my code I am only interested in creating an ItemListener for CheckBoxes.
#6 Create setters and getters for the variable declared in step #1.
#7 Create class specific conversion functions for relationships between the JSlider and the variable it represents. For example, I may want a slider that displays 0 to 100 but the variable is adjusted between 0.01 and 0.25 (arbitrary linear scaling) or possibly the slider going from -12 to +6 representing a variable from 0.25 to 2.0 (logarithmic scaling).

I created a top class "ControlPanel" in Xtend that has methods for items #2 through #6. This is more of an Interface as the methods don't do anything. Then I created a class "SliderLabel" which is a combination JSlider and JLabel and extends the ControlPanel class. Similarly, I created a "CheckBox" class that handles these things for CheckBoxes. The similarly named methods in these functions perform the actual code generation. Strictly speaking they are not overloaded because the type of the method argument is not the same as the super-class.

Any of you who have ever written a Swing program can see the utility of this I hope! It is a massive amount of code to accomplish something simple, and even if you get it conceptually, writing it by hand is tedious and error prone. Xtend to the rescue!

Here's the problem I'm trying to solve:

Back in my main code generator, I have places in the template where the above things need to happen. What I'd like to do for each control as I iterate through my model is simply to call down to the ControlPanel generator and have it figure out which type of control it is and call the appropriate methods. The problem is that the methods which help create a JCheckBox are expecting an argument of type "CheckBox" within my code and I can't send them a higher-level class reference "ControlPanel".

Now, in my code generator, I iterate through the entire model at each of these various steps and perform a switch statement to see if the element (e) is a CheckBox or a SliderLabel. Then I call either CheckBox.declare(e) or SliderLabel.declare(e) accordingly. I'd rather say in my grammar that a ControlPanel can be either a CheckBox or a SliderLabel, and then during code generation, determine that the element is a ControlPanel and simply call ControlPanel.declare(e). The method that would get called to spit out template code would be the overloaded method within the subclass. If there were no overloaded method, for example there would be no ChangeListener method called out for CheckBox, then nothing would happen.

The issue is with the typing of the model element (e) not matching the methods.

I'm guessing that this issue is not specific to Xtend because I can't think of how I would solve it in Java either. Any ideas?

Many thanks!

GW

[Updated on: Sat, 21 June 2014 15:49]

Report message to a moderator

Re: Subclassing code generators (example: Swing UI) [message #1386857 is a reply to message #1386854] Sat, 21 June 2014 17:25 Go to previous messageGo to next message
Gary Worsham is currently offline Gary WorshamFriend
Messages: 176
Registered: September 2013
Senior Member
Here's an idea that I had, which is not very elegant.

I can use the ControlPanel class to act as a method dispatcher to the other classes.

For example,

declare(SliderLabel e) {
SliderLabel.declare(e)
}

declare(CheckBox e) {
CheckBox.declare(e)
}

etc.

Then it would seem that CheckBox and SliderLabel don't need to be subclassed from ControlPanel. Not sure yet. this seems fairly clunky I haven't really changed much from the original implementation other than where the decision is made. Still, it is useful because I was able to pull out all of the required functions for each control type to its own class. I don't think I simplified the structure of the program, but I made its organization easier to deal with.
Re: Subclassing code generators (example: Swing UI) [message #1386867 is a reply to message #1386857] Sun, 22 June 2014 02:41 Go to previous messageGo to next message
Gary Worsham is currently offline Gary WorshamFriend
Messages: 176
Registered: September 2013
Senior Member
Ah well, I just did a refactoring to create Xtend classes for my control panel elements. Cleaner organization. Slowly getting all functionality implemented.
Re: Subclassing code generators (example: Swing UI) [message #1386879 is a reply to message #1386867] Sun, 22 June 2014 09:37 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14664
Registered: July 2009
Senior Member
Hi,


it is hard to give general advice but xtends dispatch methods are often suitable for such usecases


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Subclassing code generators (example: Swing UI) [message #1386896 is a reply to message #1386879] Sun, 22 June 2014 16:32 Go to previous messageGo to next message
Gary Worsham is currently offline Gary WorshamFriend
Messages: 176
Registered: September 2013
Senior Member
I think one of the problems I was facing is that I wanted elements of my grammar to adopt a class/subclass structure, so that I did not have to have each one specifically be called out in the main code generator. I realize this was naive, but let me continue.

Suppose I had the parser rules:

CheckBox: name = ID value = ID;

SliderLabel: name = ID value = ID minVal = int maxVal = int


You can see that there is some commonality between these two structures so there is a tendency to want to create a class that combines the common parts, while the subclasses would add the unique parts. In Java I have some flexibility to refer to a derived class either by its own name or that of its superclass, as long as I am just accessing the common elements.

I thought (again naively) that adding a rule:

Control: CheckBox | SliderLabel ;

would somehow create this relationship, so that I could reduce the number of separate calls required when iterating the model in the code generator.

So, rather than needing:

«FOR Element e : pr.elements»
    «switch e {
	SliderLabel: { SliderLabel.genChangeListener(e)}
	CheckBox: { CheckBox.genChangeListener(e)}
    }»
«ENDFOR»


I could have:

    «switch e {
	Control: { Control.genChangeListener(e)}
    }»


and then this would call the genChangeListener method for either SliderLabel or CheckBox, whichever the current element corresponded to. In this case, CheckBox has no genChangeListener method, but if the base class had an empty genChangeListener method, then that would get called and nothing would be generated, which is exactly what I wanted.

But I think I was getting confused between classes and some simplifying things in the DSL grammar (like the ability to OR two rules together).
}

[Updated on: Sun, 22 June 2014 16:34]

Report message to a moderator

Re: Subclassing code generators (example: Swing UI) [message #1386897 is a reply to message #1386896] Sun, 22 June 2014 16:44 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14664
Registered: July 2009
Senior Member
HI,

yes you can always introduce a supertype by (uncalled rule) Parent: Child1 | ... | ChildN


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Subclassing code generators (example: Swing UI) [message #1386901 is a reply to message #1386897] Sun, 22 June 2014 19:49 Go to previous messageGo to next message
David Wegener is currently offline David WegenerFriend
Messages: 1445
Registered: July 2009
Senior Member
You should also spend some time studying Xtend dispatch methods as Christian suggested. Combining the two allows you to have Xtend pick the method specific to the type.

Here is an example:
grammar org.test.form.FormDsl with org.eclipse.xtext.common.Terminals

generate formDsl "http://www.test.org/form/FormDsl"

Form:
	controls+=Control*;	
Control:
	Slider | Checkbox;
Checkbox :
	name = ID value = ID;
Slider:
	name = ID value = ID minValue = INT maxValue = INT;


Using the following generator:
package org.test.form.generator
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.xtext.generator.IGenerator
import org.eclipse.xtext.generator.IFileSystemAccess
import org.test.form.formDsl.Slider
import org.test.form.formDsl.Checkbox
import org.test.form.formDsl.Form
class FormDslGenerator implements IGenerator {
	override void doGenerate(Resource resource, IFileSystemAccess fsa) {
		val form = resource.contents.get(0) as Form
		for (control : form.controls) {
			generateControl(control)
		}
	}
	
	def dispatch void generateControl(Slider slider) {
		System.out.println("Slider " + slider.name)
	}
	
	def dispatch void generateControl(Checkbox checkbox) {
		System.out.println("Checkbox " + checkbox.name)
	}
}


will automatically pick the correct generateControl method based on the actual type of the control.
Re: Subclassing code generators (example: Swing UI) [message #1387091 is a reply to message #1386901] Tue, 24 June 2014 05:45 Go to previous message
Gary Worsham is currently offline Gary WorshamFriend
Messages: 176
Registered: September 2013
Senior Member
I'm sure that was the answer I was looking for.

I haven't tried it yet because I'm so thrilled that my Swing code generation works that I spent most of my evening actually USING my program and using the DSL to quickly add new functional blocks instead of fixing it. I remember how hard it was getting started with Xtext and Xtend and now I'm just bouncing between them as I add new language features.

Thanks again!!!!!!! GW
Previous Topic:"Select" option as default in list parameter
Next Topic:Preference page for separate generator
Goto Forum:
  


Current Time: Tue Apr 16 07:33:42 GMT 2024

Powered by FUDForum. Page generated in 0.78792 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top