Difference: DuckySebastianSukesh539dProjectUpdate (3 vs. 4)

Revision 42006-03-26 - TWikiGuest

Line: 1 to 1
 
META TOPICPARENT name="DuckySebastianSukesh539Project"

Using Aspects to build GUIs

Sukesh Chopra, Kaitlin Duck Sherwood, and Sebastian Streg
Changed:
<
<
Using traditional Object-Oriented programming techniques, code for building a GUI becomes tangled: layout code becomes tangled with behavior code. For example, consider a simple GUI with one button and one label, where the the label displays the number of times that the button has been pushed. When creating the label, the developer has to specify not only the visual aspects of the label, but also keep a pointer to the label that the button can use. When creating the button, the developer has to specify not only the visual aspects, but also define the behavior that the button should take when it is pushed.
>
>
Using traditional Object-Oriented programming techniques, code for building a GUI becomes tangled: layout code becomes tangled with behavior code. For example, consider a simple GUI with one button and one label, shown below, where the the label displays the number of times that the button has been pushed. When creating the label, the developer has to specify not only the visual aspects of the label, but also keep a pointer to the label that the button can use. When creating the button, the developer has to specify not only the visual aspects, but also define the behavior that the button should take when it is pushed.
 
Changed:
<
<
@@@ code example
>
>
public class Main {
   JFrame mainFrame;
   JPanel mainPanel;
   JLabel countLabel;
   public JButton countButton;
   int pressCount;

   
   public Main() {
      //Create and set up the window.
      mainFrame = new JFrame("Sample");
   
      //Create and set up the panel.
      mainPanel = new JPanel(new GridLayout(2, 2));
      
      //Add the widgets.
      countLabel = new JLabel("0", SwingConstants.LEFT);
      countButton = new JButton("Count");
      
      //Add the widgets to the container.
      mainPanel.add(countLabel);
      mainPanel.add(countButton);

      // BEHAVIOR
      pressCount = 0;        
      countButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            pressCount++;
            countLabel.setText(""+ pressCount);
         }
      });

      //Add the panel to the window.
      mainFrame.getContentPane().add(mainPanel, BorderLayout.CENTER);
            
      //Display the window.
      mainFrame.pack();
      mainFrame.setVisible(true);
   }

While the visual aspects of the GUI can easily be generated with XML or a GUI builder, the behaviour aspects cannot. Because the behavioural aspects must be embedded in the class that lays out the GUI, it is difficult to use automatically generate the layout code: re-generating it would stomp on the behavioural code.

  Our goal in this project is to separate out the visual description from the behavioural description. We want to allow users to write
  • XML that describes the layout of the GUI
Line: 48 to 91
 

Instance-level aspects

We considered several solutions for instance-level aspects.
Changed:
<
<
One thing we considered was to make a different class for each instance, with each class subclassed from the "true" class. For example, we could have e.g. JButtonFahrenheitButton and JButtonCelsiusButton both be subclasses of JButton. This looked ugly: we would need to programmatically generate the wrapper classes on the fly; in order to write the aspects properly, the developer would need to understand that dummy classes were being built with ugly names.
>
>
One thing we considered was to make a different class for each instance, with each class subclassed from the "true" class. For example, we could have e.g. JButtonButtonOne and JButtonButtonTwo to both be subclasses of JButton. This looked ugly: we would need to programmatically generate the wrapper classes on the fly; in order to write the aspects properly, the developer would need to understand that dummy classes were being built with ugly names.
  Similarly, we considered inserting a dummy method in the wrapper class(es) to correspond to each instance. The only function of the dummy methods would be to give the developer something unique to the instance that they could then exploit with a pointcut.
Changed:
<
<
Instead, we realized that since we had to use a wrapper anyway, we could pass an instance identifier to a wrapper's constructor and use that id in advice to determine whether it was the correct instance for that advice. In the case of widgets with behaviour (e.g. "execute foo() when this button is pushed", the behaviour is attached to the widget once, right after construction of the widget. In cases where the widget has state that needs to be maintained, a pointer to the widget can be grabbed once, right after construction of the widget.
>
>
Instead, we realized that since we had to use a wrapper anyway, we could pass an instance identifier to a wrapper's constructor and use that id in advice to determine whether it was the correct instance for that advice.

public aspect AddListener {
  private XTextField countField;
  private XLabel pressCount;

  after(String aName, String aLabel): execution(XButton.new(String, String)) && args(aName, aLabel)   
  {     
    if(aName == "buttonOne") 
    {       
      XButton xb = (XButton)(thisJoinPoint.getThis());       
      xb.addActionListener(new ActionListener() 
      {       
        public void actionPerformed(ActionEvent e) 
        {         
          <i>button1 action</i>;       
        });     
      }
   }   

  after(String aName, String aLabel): execution(XButton.new(String, String)) && args(aName, aLabel)   
  {     
    if(aName == "buttonTwo") 
    {       
      XButton xb = (XButton)(thisJoinPoint.getThis());       
      xb.addActionListener(new ActionListener() 
      {       
        public void actionPerformed(ActionEvent e) 
        {         
          <i>button2 action</i>;       
        });     
      }
   }   

 }  

Broadly speaking, there are two important characteristics of widgets: actions (e.g. button pushes) and state (e.g. text fields, labels). Actions can be attached to widgets once, in advice after() the widget is created. Widgets with state need to have a pointer to them kept in the state.

This structure is so regular that a skeleton can be generated automatically.

 
Changed:
<
<
@@@ example code?
>
>
In the case of widgets with behaviour, the behaviour is attached to the widget once, right after construction of the widget. In cases where the widget has state that needs to be maintained, a pointer to the widget can be grabbed once, right after construction of the widget.
  Unmodified, Swix takes as inputs
  • an XML file describing the layout
 
This site is powered by the TWiki collaboration platform Powered by PerlCopyright © 2008-2025 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback