EditFrame

For an actual type parameter Person this factory generates a class PersonEditFrame, which declares a method edit() that can be applied on an object of class Person. When called with a Person object, it displays a GUI that allows to edit the values of the object's public fields and when the OK-button of that GUI is clicked, the window closes, the edited values are written back into the object and method edit() returns.

The implementation uses Java's synchronization capabilities in order to ensure that edit() returns after the edit window has been closed. The GUI for the individual public attributes are generated by applications of factory InputField.

This example shows, how well Factory/Java is suited for the generation of GUIs. One could imagine a whole framework of adaptable GUI (and other) components that would save the programmer much time. External generator tools like the Janus Generator, for example, would not be needed any more.

Factory/Java Source

The source can be found in the Factory/Java .zip-archive in factory/classes/examples/EditFrame.factory:

<param> <var> T </var> </param>

package test;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class
<apply>
    <apply>
        <class> factory.Toolbox </class>
        <method> getRelativeName </method>
        <args>
            <var> T </var>
        </args>
    </apply>
    <method> concat </method>
    <args>
        <const> "EditFrame" </const>
    </args>
</apply>
implements ActionListener {
    <var> T </var> a = null;
    JFrame frame;
    JPanel panel;
    JButton okButton;

    <for> <var> F </var>
    <apply>
        <var> T </var>
        <method> getFields </method>
    </apply>
    <body>
        <let> <var> FN </var>
        <apply>
            <var> F </var>
            <method> getName </method>
        </apply>
        <body>
        
            JLabel
            <apply>
                <var> FN </var>
                <method> concat </method>
                <args>
                    <const> "Label" </const>
                </args>
            </apply>;
        
            <apply>
                <factory> examples/InputField </factory>
                <args>
                    <apply>
                        <var> F </var>
                        <method> getType </method>
                    </apply>
                </args>
            </apply>
            <apply>
                <var> FN </var>
                <method> concat </method>
                <args>
                    <const> "Text" </const>
                </args>
            </apply>;

        </body> </let>
    </body> </for>

    public
    <apply>
        <apply>
            <class> factory.Toolbox </class>
            <method> getRelativeName </method>
            <args>
                <var> T </var>
            </args>
        </apply>
        <method> concat </method>
        <args>
            <const> "EditFrame" </const>
        </args>
    </apply>
    () {
        frame = new JFrame("Edit "+
            <literal>
                <apply>
                    <class> factory.Toolbox </class>
                    <method> getRelativeName </method>
                    <args>
                        <var> T </var>
                    </args>
                </apply>
            </literal>
        );
        panel = new JPanel();
        panel.setLayout(new GridLayout(
            <literal>
                <apply>
                    <class> java.lang.reflect.Array </class>
                    <method> getLength </method>
                    <args>
                        <apply>
                            <var> T </var>
                            <method> getFields </method>
                        </apply>
                    </args>
                </apply>
            </literal>
            +1, 2));

            <for> <var> F </var>
            <apply>
                <var> T </var>
                <method> getFields </method>
            </apply>
            <body>
                <let> <var> FN </var>
                <apply>
                    <var> F </var>
                    <method> getName </method>
                </apply>
                <body>
                <let> <var> LN </var>
                <apply>
                    <var> FN </var>
                    <method> concat </method>
                    <args>
                        <const> "Label" </const>
                    </args>
                </apply>
                <body>
                <let> <var> TN </var>
                <apply>
                    <var> FN </var>
                    <method> concat </method>
                    <args>
                        <const> "Text" </const>
                    </args>
                </apply>
                <body>

                <var> LN </var> = new JLabel(
                    <literal> <var> FN </var> </literal>,
                    SwingConstants.LEFT);        
                panel.add(<var> LN </var>);
                
                
                <var> TN </var> =
                    new
                    <apply>
                        <factory> examples/InputField </factory>
                        <args>
                            <apply>
                                <var> F </var>
                                <method> getType </method>
                            </apply>
                        </args>
                    </apply>
                    (2);
                panel.add(<var> TN </var>);
        
            </body> </let>
            </body> </let>
            </body> </let>
        </body> </for>
        
        okButton = new JButton("Ok");
        panel.add(okButton);
        okButton.addActionListener(this);

        frame.getContentPane().add(panel, BorderLayout.CENTER);        
        
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                continueMain();
                frame.dispose();
            }
        });
    }

    public synchronized void edit(<var> T </var> o) {
        a = o;

        <for> <var> F </var>
        <apply>
            <var> T </var>
            <method> getFields </method>
        </apply>
        <body>
            <let> <var> FN </var>
            <apply>
                <var> F </var>
                <method> getName </method>
            </apply>
            <body>
            <let> <var> TN </var>
            <apply>
                <var> FN </var>
                <method> concat </method>
                <args>
                    <const> "Text" </const>
                </args>
            </apply>
            <body>
                
                <var> TN </var>.setValue(
                    a.<var> FN </var>
                );

            </body> </let>
            </body> </let>
        </body> </for>
        
        frame.pack();
        frame.show();
        
        pauseMain();
    }

    public void actionPerformed(ActionEvent event) {
        <for> <var> F </var>
        <apply>
            <var> T </var>
            <method> getFields </method>
        </apply>
        <body>
            <let> <var> FN </var>
            <apply>
                <var> F </var>
                <method> getName </method>
            </apply>
            <body>
            <let> <var> TN </var>
            <apply>
                <var> FN </var>
                <method> concat </method>
                <args>
                    <const> "Text" </const>
                </args>
            </apply>
            <body>
                
                a.<var> FN </var> = <var> TN </var>.getValue();

            </body> </let>
            </body> </let>
        </body> </for>
        
        continueMain();
        frame.dispose();
    }

    public synchronized void pauseMain() {
        try {
            this.wait();
        } catch(Exception e) {}
    }

    public synchronized void continueMain() {
        this.notify();
    }
}

Test Program

The following unparameterized factory can be found in factory/src/test/EditFrameTest.factory in the Factory/Java .zip-archive. It applies factory EditFrame to class Person and instantiates an object e of the resulting class PersonEditFrame. Then it applies factory Printable to class Person and instantiates an object p of the resulting class PrintablePerson. The edit() method of e is called with p and, after the edit window has been closed, the print() method of p is invoked to print out the values of its attributes.

package test;

class EditFrameTest {
    public static void main(String argv[]) {
        <let> <var> T </var>
        <apply>
            <factory> examples/EditFrame </factory>
            <args> <const> test.Person </const> </args>
        </apply>
        <body>
            <var> T </var> e = new <var> T </var>();
           
            <let> <var> PT </var>
            <apply>
                <factory> examples/Printable </factory>
                <args> <const> test.Person </const> </args>
            </apply>
            <body>

                <var> PT </var> p = new <var> PT </var>();
                p.name = "Mr.X";
                p.plz = 4711;
                p.id = 1;

                e.edit(p);
                p.print();
               
            </body> </let>
        </body> </let>
    }
}

This factory can be compiled in the factory directory with
java -classpath classes factory.Factory -javad src -classd classes src/test/EditFrameTest
and run with
java -classpath classes test.EditFrameTest
The following window is displayed: