MobilityDesigner2CodeGenerator

Visual Mobility Designer - Using Code Generation API

Contents


Abstract

The Code Generation API helps generates source code based in presenters combined with components. Source code is regenerated every time when user makes changes to the Design Document and switch view of the Visual Designer to the "Source". This document shows how to use the Code Generation API in the ComponentDescriptors also how to implement Code Generation Presenter.

Funtionality

Most important part of Code Generation API is a CodeSetterPresenter. Most of the developers don't have to create components from scratch. In 99% of cases the ClassCD component descriptor is reused which means basics of the code generation is already implemented. Most common Code Generation asks are:

Functionality already implemented if developer (inherited from ClassCD descriptor) - generating fields and methods (implemented in ClassCD) - lazy initialization (implemented in ClassCD)

Common tasks to implement: - generating constructor for new component (from properties) - assigning values during code initialization (from properties) - creating some custom code during initialization and after initialization (optional)

Most of this tasks could be achieved using CodeSetterPresenter.

Code generated for the LoginScreen component. The LoginScreen descriptor derives from full chain of descriptors but in this case only two descriptors generate code: ClassCD and LoginScreenCD (as it's shown in the comments):

...

private LoginScreen loginScreen;                               // ClassCD

...

public LoginScreen getLoginScreen() {                          // ClassCD
        if (loginScreen == null) {                             // ClassCD                             
            // write pre-init user code here                   // ClassCD
            loginScreen = new LoginScreen(getDisplay());       // LoginScreenCD                             
            loginScreen.setLabelTexts("Username", "Password"); // LoginScreenCD        
            loginScreen.setTitle("loginScreen");               // LoginScreenCD        
            loginScreen.addCommand(LoginScreen.LOGIN_COMMAND); // LoginScreenCD        
            loginScreen.setCommandListener(this);              // LoginScreenCD        
            loginScreen.setBGColor(-3355444);                  // LoginScreenCD        
            loginScreen.setFGColor(0);                         // LoginScreenCD        
            loginScreen.setUseLoginButton(false);              // LoginScreenCD        
            loginScreen.setLoginButtonText("Login");           // LoginScreenCD                               
            // write post-init user code here                  // ClassCD
        }                                                      // ClassCD
        return loginScreen;                                    // ClassCD
    }

This part describes how code shown above was created.

In most of the cases developers should follow pattern for defining Code Generation in ComponentDescriptor as is shown below:

This code is part of the LoginScreenCD component descriptor. (vmd.midpnb module)

private Presenter createSetterPresenter () {
        return new CodeSetterPresenter () // 1
            .addParameters (MidpCustomCodePresenterSupport.createDisplayParameter ()) // 2
            .addParameters(MidpParameter.create(PROP_BGK_COLOR, PROP_FRG_COLOR, PROP_USERNAME, PROP_PASSWORD, PROP_LOGIN_TITLE,
                                                PROP_USE_LOGIN_BUTTON, PROP_USERNAME_LABEL, PROP_PASSWORD_LABEL, PROP_LOGIN_BUTTON_TEXT)) // 2
            .addSetters (MidpSetter.createConstructor (TYPEID, MidpVersionable.MIDP_2).addParameters (MidpCustomCodePresenterSupport.PARAM_DISPLAY)) // 3
            .addSetters(MidpSetter.createSetter("setBGColor", MidpVersionable.MIDP).addParameters(PROP_BGK_COLOR)) // 4
            .addSetters(MidpSetter.createSetter("setFGColor", MidpVersionable.MIDP).addParameters(PROP_FRG_COLOR)) // 4
            .addSetters(MidpSetter.createSetter("setPassword", MidpVersionable.MIDP).addParameters(PROP_PASSWORD)) // 4
            .addSetters(MidpSetter.createSetter("setUsername", MidpVersionable.MIDP).addParameters(PROP_USERNAME)) // 4
            .addSetters(MidpSetter.createSetter("setLoginTitle", MidpVersionable.MIDP).addParameters(PROP_LOGIN_TITLE)) //4
            .addSetters(MidpSetter.createSetter("setUseLoginButton", MidpVersionable.MIDP).addParameters(PROP_USE_LOGIN_BUTTON)) // 4 
            .addSetters(MidpSetter.createSetter("setLabelTexts", MidpVersionable.MIDP).addParameters(PROP_USERNAME_LABEL, PROP_PASSWORD_LABEL)) // 4 
            .addSetters(MidpSetter.createSetter("setLoginButtonText", MidpVersionable.MIDP).addParameters(PROP_LOGIN_BUTTON_TEXT)); // 4
    }

Presenter is created inside of the createSetterPresenter() method in the same ComponentDescriptor class

protected List<? extends Presenter> createPresenters() {
        return Arrays.asList(
               ...
               createSetterPresenter(),
               ...

                );
    }

Line by line explanation for Code Generation code in the LoginScreenCD descriptor (method createSetterPresenter() numbers represent). Points 1,2,3,4 represent lines in the code shown above also marked as 1,2,3,4 in code comments.

1) New CodeSetterPresenter is created

return new CodeSetterPresenter()

2) Defining parameters used by code generation for "code setters" Method responsible for adding parameters:

CodeSetterPresenter addParameters (Parameter... parameters)

Names of the parameters (properties) are defined at the beginning of the LoginScreenCD descriptor and parameters for code generation are added in the lines of code markes as 2 in the code :


...
    //(Properties) Parameter names
    public static final String PROP_USERNAME = "username"; //NOI18N
    public static final String PROP_PASSWORD = "password"; //NOI18N
    public static final String PROP_USE_LOGIN_BUTTON = "useButton"; //NOI18N
    public static final String PROP_LOGIN_TITLE = "loginTitle"; //NOI18N
    public static final String PROP_USERNAME_LABEL = "usernameLabel"; //NOI18N
    public static final String PROP_PASSWORD_LABEL = "passwordLabel"; //NOI18N
    public static final String PROP_BGK_COLOR = "backgroundColor"; //NOI18N
    public static final String PROP_FRG_COLOR = "foregroungColor"; //NOI18N
    public static final String PROP_LOGIN_BUTTON_TEXT = "loginButtonText"; //NOI18N

...

.addParameters (MidpCustomCodePresenterSupport.createDisplayParameter ()) 
            .addParameters(MidpParameter.create(PROP_BGK_COLOR, PROP_FRG_COLOR, PROP_USERNAME, PROP_PASSWORD, PROP_LOGIN_TITLE,
                                                PROP_USE_LOGIN_BUTTON, PROP_USERNAME_LABEL, PROP_PASSWORD_LABEL, PROP_LOGIN_BUTTON_TEXT)) 

3) Defining code generation for components constructors Constructor could be define using following method

.addSetters(MidpSetter.createConstructor(TypeID type, MidpVersionable version).addParameters(String parameterName))

The LoginScreenCD has only one possible constructor: Generated Code:

loginScreen = new LoginScreen(getDisplay());

There is only one argument in the LoginScreen constructor and its defined as MidpCustomCodePresenterSupport.PARAM_DISPLAY. Full definition of the LoginScreen constructor:

.addSetters (MidpSetter.createConstructor (TYPEID, MidpVersionable.MIDP_2).addParameters (MidpCustomCodePresenterSupport.PARAM_DISPLAY))

Another good example of construcotr defenition is the Form component (FormCD descriptor). The Form component can have two possible constructors and both are defined below: Generated Code:

form = new Form("Title Name");

First constructor has only one parameter which is represented by DisplayableCD.PROP_TITLE. Definition of constructor code generation

.addSetters(MidpSetter.createConstructor(TYPEID, MidpVersionable.MIDP).addParameters(DisplayableCD.PROP_TITLE))

and second possibility constructor which has parameter title like previous one and array of items added to the object Form. Generated Code:

form = new Form("Title Name", new Item[] { getStringItem(), getImageItem() });

Definition of the code generation for this constructor

.addSetters(MidpSetter.createConstructor(TYPEID, MidpVersionable.MIDP).addParameters(DisplayableCD.PROP_TITLE, PROP_ITEMS))

__4) Setting additional properties:

First example: Code generation for "setPassword" in LoginScreen Generated code:

loginScreen.setPassword("Some password");

In this example setPasword method is created based on the property value "PROP_PASSWORD" in the LoginScreen component. This code is generated only if property PROP_PASSWORD is not null. Presenter definition

.addSetters(MidpSetter.createSetter("setPassword", MidpVersionable.MIDP).addParameters(PROP_PASSWORD)) 

Very similar example but with different argument (property/parameter PROP_BGK_COLOR). Generated code

loginScreen.setBGColor(-3355444);
.addSetters(MidpSetter.createSetter("setBGColor", MidpVersionable.MIDP).addParameters(PROP_BGK_COLOR)) 

Remember to define all parameters which will be used in additional "setters" just like is shown in section 2)

Examples

Many examples of code generation can be found in modules vmd.midp and vmd.midpnb. Almost all ComponentDescription contain use cases of Code Generation API. Presenters used for code generation are marked in comments as "// code" (method createPresenters() class ComponentDescriptors).


Full listing of LoginScreenCD

LoginScreenCD class:


public final class LoginScreenCD extends ComponentDescriptor {
    
    public static final TypeID TYPEID = new TypeID(TypeID.Kind.COMPONENT, "org.netbeans.microedition.lcdui.LoginScreen"); // NOI18N
    
    public static final String ICON_PATH = "org/netbeans/modules/vmd/midpnb/resources/login_screen_16.png"; // NOI18N
    public static final String ICON_LARGE_PATH = "org/netbeans/modules/vmd/midpnb/resources/login_screen_32.png"; // NOI18N
    
    public static final String PROP_USERNAME = "username"; //NOI18N
    public static final String PROP_PASSWORD = "password"; //NOI18N
    public static final String PROP_USE_LOGIN_BUTTON = "useButton"; //NOI18N
    public static final String PROP_LOGIN_TITLE = "loginTitle"; //NOI18N
    public static final String PROP_USERNAME_LABEL = "usernameLabel"; //NOI18N
    public static final String PROP_PASSWORD_LABEL = "passwordLabel"; //NOI18N
    public static final String PROP_BGK_COLOR = "backgroundColor"; //NOI18N
    public static final String PROP_FRG_COLOR = "foregroungColor"; //NOI18N
    public static final String PROP_LOGIN_BUTTON_TEXT = "loginButtonText"; //NOI18N
    
    public static final String USERNAME_LOGIN = NbBundle.getMessage(LoginScreenCD.class, "DISP_LoginScreen_Username"); //NOI18N 
    public static final String PASSWORD_LOGIN = NbBundle.getMessage(LoginScreenCD.class, "DISP_LoginScreen_Password"); //NOI18N  
    public static final String LOGIN_BUTTON_TEXT = NbBundle.getMessage(LoginScreenCD.class, "LBL_LoginScreen_LoginButtonScreen"); //NOI18N  

    static {
        MidpTypes.registerIconResource(TYPEID, ICON_PATH);
    }
    
    public TypeDescriptor getTypeDescriptor() {
        return new TypeDescriptor(CanvasCD.TYPEID, TYPEID, true, true);
    }
    
    public VersionDescriptor getVersionDescriptor() {
        return MidpVersionDescriptor.MIDP_2;
    }
    
    public List<PropertyDescriptor> getDeclaredPropertyDescriptors() {
        return Arrays.asList(
            new PropertyDescriptor(PROP_USERNAME, MidpTypes.TYPEID_JAVA_LANG_STRING, PropertyValue.createNull(), true, true, MidpVersionable.MIDP_2),
            new PropertyDescriptor(PROP_PASSWORD, MidpTypes.TYPEID_JAVA_LANG_STRING, PropertyValue.createNull(), true, true, MidpVersionable.MIDP_2),
            new PropertyDescriptor(PROP_USE_LOGIN_BUTTON, MidpTypes.TYPEID_BOOLEAN, PropertyValue.createNull(), true, true, MidpVersionable.MIDP_2),
            new PropertyDescriptor(PROP_LOGIN_TITLE, MidpTypes.TYPEID_JAVA_LANG_STRING, PropertyValue.createNull(), true, true, MidpVersionable.MIDP_2),
            new PropertyDescriptor(PROP_BGK_COLOR, MidpTypes.TYPEID_INT, MidpTypes.createIntegerValue(-3355444), true, true, MidpVersionable.MIDP_2),
            new PropertyDescriptor(PROP_FRG_COLOR, MidpTypes.TYPEID_INT, MidpTypes.createIntegerValue(-16777216), true, true, MidpVersionable.MIDP_2),
            new PropertyDescriptor(PROP_USERNAME_LABEL, MidpTypes.TYPEID_JAVA_LANG_STRING, PropertyValue.createNull(), true, true, MidpVersionable.MIDP_2),
            new PropertyDescriptor(PROP_PASSWORD_LABEL, MidpTypes.TYPEID_JAVA_LANG_STRING, PropertyValue.createNull(), true, true, MidpVersionable.MIDP_2),
            new PropertyDescriptor(PROP_LOGIN_BUTTON_TEXT, MidpTypes.TYPEID_JAVA_LANG_STRING, PropertyValue.createNull(), true, true, MidpVersionable.MIDP_2)
        
        );
    }
    
    private static DefaultPropertiesPresenter createPropertiesPresenter() {
       return new DefaultPropertiesPresenter(DesignEventFilterResolver.THIS_COMPONENT)
               .addPropertiesCategory(MidpNbPropertiesCategories.CATEGORY_LOGIN)
                   .addProperty(NbBundle.getMessage(LoginScreenCD.class, "DISP_LoginScreen_Username"), // NOI18N
                        PropertyEditorString.createInstance(NbBundle.getMessage(LoginScreenCD.class,
                            "LBL_LoginScreen_Username")), PROP_USERNAME) // NOI18N
                   .addProperty(NbBundle.getMessage(LoginScreenCD.class, "DISP_LoginScreen_Password"), // NOI18N
                        PropertyEditorString.createTextFieldInstance(NbBundle.getMessage(LoginScreenCD.class,
                            "LBL_LoginScreen_Password")), PROP_PASSWORD) // NOI18N
               .addPropertiesCategory(MidpPropertiesCategories.CATEGORY_PROPERTIES)
                   .addProperty(NbBundle.getMessage(LoginScreenCD.class, "DISP_LoginScreen_UsernameLabel"), // NOI18N
                        PropertyEditorString.createInstance(NbBundle.getMessage(LoginScreenCD.class,
                            "LBL_LoginScreen_Username")), PROP_USERNAME_LABEL) // NOI18N
                   .addProperty(NbBundle.getMessage(LoginScreenCD.class, "DISP_LoginScreen_PasswordLabel"), // NOI18N
                        PropertyEditorString.createInstance(NbBundle.getMessage(LoginScreenCD.class,
                            "LBL_LoginScreen_Password")), PROP_PASSWORD_LABEL) // NOI18N
                   .addProperty(NbBundle.getMessage(LoginScreenCD.class, "DISP_LoginScreen_UseLoginButton"), // NOI18N
                        PropertyEditorBooleanUC.createInstance(), PROP_USE_LOGIN_BUTTON)
                   .addProperty(NbBundle.getMessage(LoginScreenCD.class, "DISP_LoginScreen_LoginTitle"), // NOI18N
                        PropertyEditorString.createInstance(NbBundle.getMessage(LoginScreenCD.class,
                            "LBL_LoginScreen_LoginTitle")), PROP_LOGIN_TITLE) // NOI18N
                   .addProperty(NbBundle.getMessage(LoginScreenCD.class, "DISP_LoginScreen_BackgroundColor"), // NOI18N
                        new PropertyEditorColorChooser(true), PROP_BGK_COLOR)
                   .addProperty(NbBundle.getMessage(LoginScreenCD.class, "DISP_LoginScreen_ForegroundColor"), // NOI18N
                        new PropertyEditorColorChooser(true), PROP_FRG_COLOR)
                   .addProperty(NbBundle.getMessage(LoginScreenCD.class, "DISP_LoginScreen_LoginButtonText"), // NOI18N
                        PropertyEditorString.createInstance(NbBundle.getMessage(LoginScreenCD.class, 
                            "LBL_LoginScreen_LoginButtonText_LABEL")), PROP_LOGIN_BUTTON_TEXT); //NOI18N
    }
    
    private Presenter createSetterPresenter () {
        return new CodeSetterPresenter ()
            .addParameters (MidpCustomCodePresenterSupport.createDisplayParameter ())
            .addParameters(MidpParameter.create(PROP_BGK_COLOR, PROP_FRG_COLOR, PROP_USERNAME, PROP_PASSWORD, PROP_LOGIN_TITLE,
                                                PROP_USE_LOGIN_BUTTON, PROP_USERNAME_LABEL, PROP_PASSWORD_LABEL, PROP_LOGIN_BUTTON_TEXT))
            .addSetters (MidpSetter.createConstructor (TYPEID, MidpVersionable.MIDP_2).addParameters (MidpCustomCodePresenterSupport.PARAM_DISPLAY))
            .addSetters(MidpSetter.createSetter("setBGColor", MidpVersionable.MIDP).addParameters(PROP_BGK_COLOR)) //NOI18N
            .addSetters(MidpSetter.createSetter("setFGColor", MidpVersionable.MIDP).addParameters(PROP_FRG_COLOR)) //NOI18N
            .addSetters(MidpSetter.createSetter("setPassword", MidpVersionable.MIDP).addParameters(PROP_PASSWORD)) //NOI18N
            .addSetters(MidpSetter.createSetter("setUsername", MidpVersionable.MIDP).addParameters(PROP_USERNAME)) //NOI18N
            .addSetters(MidpSetter.createSetter("setLoginTitle", MidpVersionable.MIDP).addParameters(PROP_LOGIN_TITLE)) //NOI18N
            .addSetters(MidpSetter.createSetter("setUseLoginButton", MidpVersionable.MIDP).addParameters(PROP_USE_LOGIN_BUTTON)) //NOI18N
            .addSetters(MidpSetter.createSetter("setLabelTexts", MidpVersionable.MIDP).addParameters(PROP_USERNAME_LABEL, PROP_PASSWORD_LABEL)) //NOI18N
            .addSetters(MidpSetter.createSetter("setLoginButtonText", MidpVersionable.MIDP).addParameters(PROP_LOGIN_BUTTON_TEXT)); //NOI18N
    }

    protected List<? extends Presenter> createPresenters() {
        return Arrays.asList (
            //properties
            createPropertiesPresenter(),
            // code
            createSetterPresenter(),
            MidpCodePresenterSupport.createAddImportPresenter(),
            // actions
            AddActionPresenter.create(AddActionPresenter.ADD_ACTION, 10, CommandCD.TYPEID),
            // screen
            new LoginScreenDisplayPresenter()
        );
    }

    @Override
    public void postInitialize(DesignComponent component) {
        super.postInitialize(component);
        MidpProjectSupport.addLibraryToProject (component.getDocument (), AbstractInfoScreenCD.MIDP_NB_LIBRARY_BASIC); //NOI18N
    }

    @Override
    protected void gatherPresenters(ArrayList<Presenter> presenters) {
        DocumentSupport.removePresentersOfClass(presenters, AddActionPresenter.class);
        DocumentSupport.removePresentersOfClass(presenters, DisplayableDisplayPresenter.class);
        MidpActionsSupport.addUnusedCommandsAddActionForDisplayable(presenters);
        super.gatherPresenters(presenters);
    }

}



contact: Karol Harezlak

Not logged in. Log in, Register

By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo