Java Swing Variations

Ken Webb 2010-05-02T16:07:54Z

The default declarative format supported by Xholon for specifying Swing GUIs, is rather verbose.

It's now possible to express the same GUI much more concisely. For example, the MeTTTa GUI is now expressible as:

<?xml version="1.0" encoding="UTF-8"?>
<!--
  MeTTTa application - GUI - new concise format
  Xholon 0.8.1 http://www.primordion.com/Xholon
-->
<JFrame Title="Xholon meTTTa" DefaultCloseOperation="3"> <!-- 2 3 -->
  <JPanel>
    <JPanel Background="0xF0F0F0">
      <GridLayout Rows="3" Columns="3"/>
      <!-- row 1 -->
      <JButton
        MinimumSize="Dimension,50,50" PreferredSize="Dimension,50,50" ActionCommand="select0"
        SetFont="Monospaced,1,24" Background="0xEEF8E0"/>
      <JButton
        MinimumSize="Dimension,50,50" PreferredSize="Dimension,50,50" ActionCommand="select1"
        SetFont="Monospaced,1,24" Background="0xEEF8E0"/>
      <JButton
        MinimumSize="Dimension,50,50" PreferredSize="Dimension,50,50" ActionCommand="select2"
        SetFont="Monospaced,1,24" Background="0xEEF8E0"/>
      <!-- row 2 -->
      <JButton
        MinimumSize="Dimension,50,50" PreferredSize="Dimension,50,50" ActionCommand="select3"
        SetFont="Monospaced,1,24" Background="0xEEF8E0"/>
      <JButton
        MinimumSize="Dimension,50,50" PreferredSize="Dimension,50,50" ActionCommand="select4"
        SetFont="Monospaced,1,24" Background="0xEEF8E0"/>
      <JButton
        MinimumSize="Dimension,50,50" PreferredSize="Dimension,50,50" ActionCommand="select5"
        SetFont="Monospaced,1,24" Background="0xEEF8E0"/>
      <!-- row 3 -->
      <JButton
        MinimumSize="Dimension,50,50" PreferredSize="Dimension,50,50" ActionCommand="select6"
        SetFont="Monospaced,1,24" Background="0xEEF8E0"/>
      <JButton
        MinimumSize="Dimension,50,50" PreferredSize="Dimension,50,50" ActionCommand="select7"
        SetFont="Monospaced,1,24" Background="0xEEF8E0"/>
      <JButton
        MinimumSize="Dimension,50,50" PreferredSize="Dimension,50,50" ActionCommand="select8"
        SetFont="Monospaced,1,24" Background="0xEEF8E0"/>
    </JPanel>
    <VBox>
      <JButton Text="New Game" ActionCommand="newgame"/>
      <Strut Height="10"/>
      <JButton Text="Computer First" ActionCommand="computerfirst"/>
    </VBox>
  </JPanel>
</JFrame>

The above XML has a lot of repetitive attributes. The repetition can be removed by declaring a Java stylist script. Note the <SwingStylist> node in the following XML.

<?xml version="1.0" encoding="UTF-8"?>
<!--
  MeTTTa application - GUI - new concise format, with button stylist
  Xholon 0.8.1 http://www.primordion.com/Xholon
-->
<JFrame Title="Xholon meTTTa" DefaultCloseOperation="3"> <!-- 2 3 -->
  <JPanel>
    <JPanel Background="0xF0F0F0">
      <GridLayout Rows="3" Columns="3"/>
      <!-- row 1 -->
      <JButton ActionCommand="select0"/>
      <JButton ActionCommand="select1"/>
      <JButton ActionCommand="select2"/>
      <!-- row 2 -->
      <JButton ActionCommand="select3"/>
      <JButton ActionCommand="select4"/>
      <JButton ActionCommand="select5"/>
      <!-- row 3 -->
      <JButton ActionCommand="select6"/>
      <JButton ActionCommand="select7"/>
      <JButton ActionCommand="select8"/>
      <SwingStylist implName="org.primordion.user.app.MeTTTa.SwingButtonStylist"/>
    </JPanel>
    <VBox>
      <JButton Text="New Game" ActionCommand="newgame"/>
      <Strut Height="10"/>
      <JButton Text="Computer First" ActionCommand="computerfirst"/>
    </VBox>
  </JPanel>
</JFrame>

The next step in XML size reduction is to specify a multiplicity for the JButton instances, rather than repeating the JButton element nine times. An enhanced SwingStylist can generate the ActionCommand attributes at runtime.

<?xml version="1.0" encoding="UTF-8"?>
<!--
  MeTTTa application - GUI - tiny format, with button stylist
  Xholon 0.8.1 http://www.primordion.com/Xholon
-->
<JFrame Title="Xholon meTTTa" DefaultCloseOperation="3"> <!-- 2 3 -->
  <JPanel>
    <JPanel Background="0xF0F0F0">
      <GridLayout Rows="3" Columns="3"/>
      <JButton multiplicity="9"/>
      <SwingStylist
        implName="org.primordion.user.app.MeTTTa.SwingButtonStylist2"/>
    </JPanel>
    <VBox>
      <JButton Text="New Game" ActionCommand="newgame"/>
      <Strut Height="10"/>
      <JButton Text="Computer First" ActionCommand="computerfirst"/>
    </VBox>
  </JPanel>
</JFrame>

Here's the Java code for the final SwingStylist. It uses a Visitor pattern to visit all nodes that are children of the JPanel node. It only styles the JButton nodes that are children of that specific JPanel. It styles only the nine JButton nodes associated with the GridLayout, and does NOT style the "New Game" and "Computer First" JButton instances. If we wanted to style all eleven buttons, then the SwingStylist element could be placed as a last child of the JFrame node. Once the stylist finishes its work, it removes itself from the Xholon tree.

package org.primordion.user.app.MeTTTa;

import org.primordion.xholon.script.XholonScript;
import org.primordion.xholon.base.IXholon;
import javax.swing.JButton;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;

public class SwingButtonStylist2 extends XholonScript {
    
    private int selectCount = 0;
    
    public void postConfigure()
    {
        getParentNode().visit(this);
        removeChild();
    }
    
    public boolean visit(IXholon visitee)
    {
        if ("JButton".equals(visitee.getXhcName())) {
            JButton component = (JButton)visitee.getVal_Object();
            if (component != null) {
                component.setMinimumSize(new Dimension(100, 100));
                component.setPreferredSize(new Dimension(100, 100));
                component.setFont(new Font("Monospaced", 7, 60));
                component.setBackground(Color.ORANGE);
                component.setActionCommand("select" + selectCount++);
            }
        }
        return true;
    }
    
}

The following image shows the XML being edited in Eclipse, the optional Xholon GUI with its runtime tree view, and the MeTTTa GUI with the styled ORANGE buttons.

Other variations are also possible.

By the way, the original verbose XML looks like the following. This is still perfectly OK in Xholon, but more concise alternatives are now available.

<?xml version="1.0" encoding="UTF-8"?>
<!--
  MeTTTa application - GUI - original format
  Xholon 0.7.1 http://www.primordion.com/Xholon
-->
<JFrame>
  <Attribute_String roleName="Title">Xholon meTTTa</Attribute_String>
  <Attribute_int roleName="DefaultCloseOperation">3</Attribute_int> <!-- 2 3 -->
  <JPanel>
    <JPanel>
      <Attribute_String roleName="Background">0xF0F0F0</Attribute_String>
      <GridLayout>
        <Attribute_int roleName="Rows">3</Attribute_int>
        <Attribute_int roleName="Columns">3</Attribute_int>
      </GridLayout>
      <!-- row 1 -->
      <JButton>
        <Attribute_String roleName="MinimumSize">Dimension,50,50</Attribute_String>
        <Attribute_String roleName="PreferredSize">Dimension,50,50</Attribute_String>
        <Attribute_String roleName="ActionCommand">select0</Attribute_String>
        <Attribute_String roleName="SetFont">Monospaced,1,24</Attribute_String>
        <Attribute_String roleName="Background">0xEEF8E0</Attribute_String>
      </JButton>
      <JButton>
        <Attribute_String roleName="MinimumSize">Dimension,50,50</Attribute_String>
        <Attribute_String roleName="PreferredSize">Dimension,50,50</Attribute_String>
        <Attribute_String roleName="ActionCommand">select1</Attribute_String>
        <Attribute_String roleName="SetFont">Monospaced,1,24</Attribute_String>
        <Attribute_String roleName="Background">0xEEF8E0</Attribute_String>
      </JButton>
      <JButton>
        <Attribute_String roleName="MinimumSize">Dimension,50,50</Attribute_String>
        <Attribute_String roleName="PreferredSize">Dimension,50,50</Attribute_String>
        <Attribute_String roleName="ActionCommand">select2</Attribute_String>
        <Attribute_String roleName="SetFont">Monospaced,1,24</Attribute_String>
        <Attribute_String roleName="Background">0xEEF8E0</Attribute_String>
      </JButton>
      <!-- row 2 -->
      <JButton>
        <Attribute_String roleName="MinimumSize">Dimension,50,50</Attribute_String>
        <Attribute_String roleName="PreferredSize">Dimension,50,50</Attribute_String>
        <Attribute_String roleName="ActionCommand">select3</Attribute_String>
        <Attribute_String roleName="SetFont">Monospaced,1,24</Attribute_String>
        <Attribute_String roleName="Background">0xEEF8E0</Attribute_String>
      </JButton>
      <JButton>
        <Attribute_String roleName="MinimumSize">Dimension,50,50</Attribute_String>
        <Attribute_String roleName="PreferredSize">Dimension,50,50</Attribute_String>
        <Attribute_String roleName="ActionCommand">select4</Attribute_String>
        <Attribute_String roleName="SetFont">Monospaced,1,24</Attribute_String>
        <Attribute_String roleName="Background">0xEEF8E0</Attribute_String>
      </JButton>
      <JButton>
        <Attribute_String roleName="MinimumSize">Dimension,50,50</Attribute_String>
        <Attribute_String roleName="PreferredSize">Dimension,50,50</Attribute_String>
        <Attribute_String roleName="ActionCommand">select5</Attribute_String>
        <Attribute_String roleName="SetFont">Monospaced,1,24</Attribute_String>
        <Attribute_String roleName="Background">0xEEF8E0</Attribute_String>
      </JButton>
      <!-- row 3 -->
      <JButton>
        <Attribute_String roleName="MinimumSize">Dimension,50,50</Attribute_String>
        <Attribute_String roleName="PreferredSize">Dimension,50,50</Attribute_String>
        <Attribute_String roleName="ActionCommand">select6</Attribute_String>
        <Attribute_String roleName="SetFont">Monospaced,1,24</Attribute_String>
        <Attribute_String roleName="Background">0xEEF8E0</Attribute_String>
      </JButton>
      <JButton>
        <Attribute_String roleName="MinimumSize">Dimension,50,50</Attribute_String>
        <Attribute_String roleName="PreferredSize">Dimension,50,50</Attribute_String>
        <Attribute_String roleName="ActionCommand">select7</Attribute_String>
        <Attribute_String roleName="SetFont">Monospaced,1,24</Attribute_String>
        <Attribute_String roleName="Background">0xEEF8E0</Attribute_String>
      </JButton>
      <JButton>
        <Attribute_String roleName="MinimumSize">Dimension,50,50</Attribute_String>
        <Attribute_String roleName="PreferredSize">Dimension,50,50</Attribute_String>
        <Attribute_String roleName="ActionCommand">select8</Attribute_String>
        <Attribute_String roleName="SetFont">Monospaced,1,24</Attribute_String>
        <Attribute_String roleName="Background">0xEEF8E0</Attribute_String>
      </JButton>
      <!--<SwingStylist implName="lang:groovy:/Xholon/script/groovy/SwingStylist2.groovy"/>-->
    </JPanel>
    <VBox>
      <JButton>
        <Attribute_String roleName="Text">New Game</Attribute_String>
        <Attribute_String roleName="ActionCommand">newgame</Attribute_String>
      </JButton>
      <Strut><Attribute_int roleName="Height">10</Attribute_int></Strut>
      <JButton>
        <Attribute_String roleName="Text">Computer First</Attribute_String>
        <Attribute_String roleName="ActionCommand">computerfirst</Attribute_String>
      </JButton>
    </VBox>
  </JPanel>
</JFrame>

return to main page